diff options
1424 files changed, 28723 insertions, 12267 deletions
diff --git a/Android.bp b/Android.bp index 516fc9c55222..811755d0bdaf 100644 --- a/Android.bp +++ b/Android.bp @@ -368,6 +368,7 @@ java_defaults { jarjar_rules: ":framework-jarjar-rules", javac_shard_size: 150, plugins: [ + "cached-property-annotation-processor", "view-inspector-annotation-processor", "staledataclass-annotation-processor", "error_prone_android_framework", diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java index 52a761f8d486..31d2ecdb83b0 100644 --- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java +++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java @@ -34,6 +34,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; import android.os.RemoteException; +import android.os.Process; import android.system.SystemCleaner; import android.util.Log; @@ -638,6 +639,12 @@ public class JobParameters implements Parcelable { * @hide */ public void enableCleaner() { + // JobParameters objects are passed by reference in local Binder + // transactions for clients running as SYSTEM. The life cycle of the + // JobParameters objects are no longer controlled by the client. + if (Process.myUid() == Process.SYSTEM_UID) { + return; + } if (mJobCleanupCallback == null) { initCleaner(new JobCleanupCallback(IJobCallback.Stub.asInterface(callback), jobId)); } diff --git a/api/api.go b/api/api.go index e9f1feebd899..1bbf3709480a 100644 --- a/api/api.go +++ b/api/api.go @@ -514,7 +514,7 @@ func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) { func combinedApisModuleFactory() android.Module { module := &CombinedApis{} module.AddProperties(&module.properties) - android.InitAndroidModule(module) + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.createInternalModules(ctx) }) return module } diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index c2f6e3072507..87c9fa4dbe28 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -106,7 +106,6 @@ static const int TEXT_CENTER_VALUE = INT_MAX; static const int TEXT_MISSING_VALUE = INT_MIN; static const char EXIT_PROP_NAME[] = "service.bootanim.exit"; static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; -static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const char CLOCK_ENABLED_PROP_NAME[] = "persist.sys.bootanim.clock.enabled"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static const int MAX_CHECK_EXIT_INTERVAL_US = 50000; @@ -514,50 +513,9 @@ status_t BootAnimation::readyToRun() { return NAME_NOT_FOUND; } - // this system property specifies multi-display IDs to show the boot animation - // multiple ids can be set with comma (,) as separator, for example: - // setprop persist.boot.animation.displays 19260422155234049,19261083906282754 - Vector<PhysicalDisplayId> physicalDisplayIds; - char displayValue[PROPERTY_VALUE_MAX] = ""; - property_get(DISPLAYS_PROP_NAME, displayValue, ""); - bool isValid = displayValue[0] != '\0'; - if (isValid) { - char *p = displayValue; - while (*p) { - if (!isdigit(*p) && *p != ',') { - isValid = false; - break; - } - p ++; - } - if (!isValid) - SLOGE("Invalid syntax for the value of system prop: %s", DISPLAYS_PROP_NAME); - } - if (isValid) { - std::istringstream stream(displayValue); - for (PhysicalDisplayId id; stream >> id.value; ) { - physicalDisplayIds.add(id); - if (stream.peek() == ',') - stream.ignore(); - } - - // the first specified display id is used to retrieve mDisplayToken - for (const auto id : physicalDisplayIds) { - if (std::find(ids.begin(), ids.end(), id) != ids.end()) { - if (const auto token = SurfaceComposerClient::getPhysicalDisplayToken(id)) { - mDisplayToken = token; - break; - } - } - } - } - - // If the system property is not present or invalid, display 0 is used + mDisplayToken = SurfaceComposerClient::getPhysicalDisplayToken(ids.front()); if (mDisplayToken == nullptr) { - mDisplayToken = SurfaceComposerClient::getPhysicalDisplayToken(ids.front()); - if (mDisplayToken == nullptr) { - return NAME_NOT_FOUND; - } + return NAME_NOT_FOUND; } DisplayMode displayMode; @@ -577,17 +535,8 @@ status_t BootAnimation::readyToRun() { ISurfaceComposerClient::eOpaque); SurfaceComposerClient::Transaction t; - if (isValid) { - // In the case of multi-display, boot animation shows on the specified displays - for (const auto id : physicalDisplayIds) { - if (std::find(ids.begin(), ids.end(), id) != ids.end()) { - if (const auto token = SurfaceComposerClient::getPhysicalDisplayToken(id)) { - t.setDisplayLayerStack(token, ui::DEFAULT_LAYER_STACK); - } - } - } - t.setLayerStack(control, ui::DEFAULT_LAYER_STACK); - } + t.setDisplayLayerStack(mDisplayToken, ui::DEFAULT_LAYER_STACK); + t.setLayerStack(control, ui::DEFAULT_LAYER_STACK); t.setLayer(control, 0x40000000) .apply(); diff --git a/cmds/hid/Android.bp b/cmds/hid/Android.bp index a6e27698e36c..b93227a60d99 100644 --- a/cmds/hid/Android.bp +++ b/cmds/hid/Android.bp @@ -22,5 +22,5 @@ java_binary { name: "hid", wrapper: "hid.sh", srcs: ["**/*.java"], - required: ["libhidcommand_jni"], + jni_libs: ["libhidcommand_jni"], } diff --git a/cmds/uinput/Android.bp b/cmds/uinput/Android.bp index da497dcf908e..cec8a0d88b99 100644 --- a/cmds/uinput/Android.bp +++ b/cmds/uinput/Android.bp @@ -25,7 +25,7 @@ java_binary { "src/**/*.java", ":uinputcommand_aidl", ], - required: ["libuinputcommand_jni"], + jni_libs: ["libuinputcommand_jni"], } filegroup { diff --git a/core/api/current.txt b/core/api/current.txt index 67b328057efe..44b3c6232d59 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -4947,8 +4947,10 @@ package android.app { method public void update(android.app.ActivityOptions); field public static final String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time"; field public static final String EXTRA_USAGE_TIME_REPORT_PACKAGES = "android.usage_time_packages"; - field public static final int MODE_BACKGROUND_ACTIVITY_START_ALLOWED = 1; // 0x1 - field public static final int MODE_BACKGROUND_ACTIVITY_START_DENIED = 2; // 0x2 + field @Deprecated @FlaggedApi("com.android.window.flags.bal_additional_start_modes") public static final int MODE_BACKGROUND_ACTIVITY_START_ALLOWED = 1; // 0x1 + field @FlaggedApi("com.android.window.flags.bal_additional_start_modes") public static final int MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS = 3; // 0x3 + field @FlaggedApi("com.android.window.flags.bal_additional_start_modes") public static final int MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE = 4; // 0x4 + field @FlaggedApi("com.android.window.flags.bal_additional_start_modes") public static final int MODE_BACKGROUND_ACTIVITY_START_DENIED = 2; // 0x2 field public static final int MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED = 0; // 0x0 } @@ -6858,43 +6860,43 @@ package android.app { @FlaggedApi("android.app.api_rich_ongoing") public static class Notification.ProgressStyle extends android.app.Notification.Style { ctor public Notification.ProgressStyle(); + method @NonNull public android.app.Notification.ProgressStyle addProgressPoint(@NonNull android.app.Notification.ProgressStyle.Point); method @NonNull public android.app.Notification.ProgressStyle addProgressSegment(@NonNull android.app.Notification.ProgressStyle.Segment); - method @NonNull public android.app.Notification.ProgressStyle addProgressStep(@NonNull android.app.Notification.ProgressStyle.Step); method public int getProgress(); method @Nullable public android.graphics.drawable.Icon getProgressEndIcon(); method public int getProgressMax(); + method @NonNull public java.util.List<android.app.Notification.ProgressStyle.Point> getProgressPoints(); method @NonNull public java.util.List<android.app.Notification.ProgressStyle.Segment> getProgressSegments(); method @Nullable public android.graphics.drawable.Icon getProgressStartIcon(); - method @NonNull public java.util.List<android.app.Notification.ProgressStyle.Step> getProgressSteps(); method @Nullable public android.graphics.drawable.Icon getProgressTrackerIcon(); method public boolean isProgressIndeterminate(); method public boolean isStyledByProgress(); method @NonNull public android.app.Notification.ProgressStyle setProgress(int); method @NonNull public android.app.Notification.ProgressStyle setProgressEndIcon(@Nullable android.graphics.drawable.Icon); method @NonNull public android.app.Notification.ProgressStyle setProgressIndeterminate(boolean); + method @NonNull public android.app.Notification.ProgressStyle setProgressPoints(@NonNull java.util.List<android.app.Notification.ProgressStyle.Point>); method @NonNull public android.app.Notification.ProgressStyle setProgressSegments(@NonNull java.util.List<android.app.Notification.ProgressStyle.Segment>); method @NonNull public android.app.Notification.ProgressStyle setProgressStartIcon(@Nullable android.graphics.drawable.Icon); - method @NonNull public android.app.Notification.ProgressStyle setProgressSteps(@NonNull java.util.List<android.app.Notification.ProgressStyle.Step>); method @NonNull public android.app.Notification.ProgressStyle setProgressTrackerIcon(@Nullable android.graphics.drawable.Icon); method @NonNull public android.app.Notification.ProgressStyle setStyledByProgress(boolean); } + public static final class Notification.ProgressStyle.Point { + ctor public Notification.ProgressStyle.Point(int); + method @ColorInt public int getColor(); + method public int getId(); + method public int getPosition(); + method @NonNull public android.app.Notification.ProgressStyle.Point setColor(@ColorInt int); + method @NonNull public android.app.Notification.ProgressStyle.Point setId(int); + } + public static final class Notification.ProgressStyle.Segment { ctor public Notification.ProgressStyle.Segment(int); method @ColorInt public int getColor(); + method public int getId(); method public int getLength(); - method public int getStableId(); method @NonNull public android.app.Notification.ProgressStyle.Segment setColor(@ColorInt int); - method @NonNull public android.app.Notification.ProgressStyle.Segment setStableId(int); - } - - public static final class Notification.ProgressStyle.Step { - ctor public Notification.ProgressStyle.Step(int); - method @ColorInt public int getColor(); - method public int getPosition(); - method public int getStableId(); - method @NonNull public android.app.Notification.ProgressStyle.Step setColor(@ColorInt int); - method @NonNull public android.app.Notification.ProgressStyle.Step setStableId(int); + method @NonNull public android.app.Notification.ProgressStyle.Segment setId(int); } public abstract static class Notification.Style { @@ -8673,6 +8675,8 @@ package android.app.admin { field public static final int TAG_MAX_SCREEN_LOCK_TIMEOUT_SET = 210019; // 0x33463 field public static final int TAG_MEDIA_MOUNT = 210013; // 0x3345d field public static final int TAG_MEDIA_UNMOUNT = 210014; // 0x3345e + field @FlaggedApi("android.nfc.nfc_state_change_security_log_event_enabled") public static final int TAG_NFC_DISABLED = 210046; // 0x3347e + field @FlaggedApi("android.nfc.nfc_state_change_security_log_event_enabled") public static final int TAG_NFC_ENABLED = 210045; // 0x3347d field public static final int TAG_OS_SHUTDOWN = 210010; // 0x3345a field public static final int TAG_OS_STARTUP = 210009; // 0x33459 field public static final int TAG_PACKAGE_INSTALLED = 210041; // 0x33479 @@ -8787,7 +8791,7 @@ package android.app.appfunctions { @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public abstract class AppFunctionService extends android.app.Service { ctor public AppFunctionService(); method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent); - method @Deprecated @MainThread public abstract void onExecuteFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull java.util.function.Consumer<android.app.appfunctions.ExecuteAppFunctionResponse>); + method @Deprecated @MainThread public void onExecuteFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull java.util.function.Consumer<android.app.appfunctions.ExecuteAppFunctionResponse>); method @MainThread public void onExecuteFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<android.app.appfunctions.ExecuteAppFunctionResponse>); field @NonNull public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService"; } @@ -8822,13 +8826,12 @@ package android.app.appfunctions { field @NonNull public static final android.os.Parcelable.Creator<android.app.appfunctions.ExecuteAppFunctionResponse> CREATOR; field public static final String PROPERTY_RETURN_VALUE = "returnValue"; field public static final int RESULT_APP_UNKNOWN_ERROR = 2; // 0x2 - field public static final int RESULT_CANCELLED = 7; // 0x7 + field public static final int RESULT_CANCELLED = 6; // 0x6 field public static final int RESULT_DENIED = 1; // 0x1 - field public static final int RESULT_DISABLED = 6; // 0x6 + field public static final int RESULT_DISABLED = 5; // 0x5 field public static final int RESULT_INTERNAL_ERROR = 3; // 0x3 field public static final int RESULT_INVALID_ARGUMENT = 4; // 0x4 field public static final int RESULT_OK = 0; // 0x0 - field public static final int RESULT_TIMED_OUT = 5; // 0x5 } } @@ -12114,6 +12117,7 @@ package android.content.om { method @NonNull public void setResourceValue(@NonNull String, int, @NonNull String, @Nullable String); method @NonNull public void setResourceValue(@NonNull String, @NonNull android.os.ParcelFileDescriptor, @Nullable String); method @FlaggedApi("android.content.res.asset_file_descriptor_frro") @NonNull public void setResourceValue(@NonNull String, @NonNull android.content.res.AssetFileDescriptor, @Nullable String); + method @FlaggedApi("android.content.res.dimension_frro") public void setResourceValue(@NonNull String, float, int, @Nullable String); method public void setTargetOverlayable(@Nullable String); } @@ -21411,6 +21415,7 @@ package android.media { field public static final int ENCODING_AAC_XHE = 16; // 0x10 field public static final int ENCODING_AC3 = 5; // 0x5 field public static final int ENCODING_AC4 = 17; // 0x11 + field @FlaggedApi("android.media.audio.dolby_ac4_level4_encoding_api") public static final int ENCODING_AC4_L4 = 32; // 0x20 field public static final int ENCODING_DEFAULT = 1; // 0x1 field public static final int ENCODING_DOLBY_MAT = 19; // 0x13 field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe @@ -26914,7 +26919,6 @@ package android.media.session { field public static final int STATE_FAST_FORWARDING = 4; // 0x4 field public static final int STATE_NONE = 0; // 0x0 field public static final int STATE_PAUSED = 2; // 0x2 - field @FlaggedApi("com.android.media.flags.enable_notifying_activity_manager_with_media_session_status_change") public static final int STATE_PLAYBACK_SUPPRESSED = 12; // 0xc field public static final int STATE_PLAYING = 3; // 0x3 field public static final int STATE_REWINDING = 5; // 0x5 field public static final int STATE_SKIPPING_TO_NEXT = 10; // 0xa @@ -32821,7 +32825,7 @@ package android.os { field @NonNull public static final String RELEASE_OR_PREVIEW_DISPLAY; field @Deprecated public static final String SDK; field public static final int SDK_INT; - field @FlaggedApi("android.sdk.major_minor_versioning_scheme") public static final int SDK_MINOR_INT; + field @FlaggedApi("android.sdk.major_minor_versioning_scheme") public static final int SDK_INT_FULL; field public static final String SECURITY_PATCH; } @@ -32865,6 +32869,9 @@ package android.os { field public static final int VANILLA_ICE_CREAM = 35; // 0x23 } + @FlaggedApi("android.sdk.major_minor_versioning_scheme") public static class Build.VERSION_CODES_FULL { + } + public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { ctor public Bundle(); ctor public Bundle(ClassLoader); @@ -36989,7 +36996,7 @@ package android.provider { } @FlaggedApi("android.provider.new_default_account_api_enabled") public static final class ContactsContract.RawContacts.DefaultAccount { - ctor public ContactsContract.RawContacts.DefaultAccount(); + method @FlaggedApi("android.provider.new_default_account_api_enabled") @NonNull public static android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState getDefaultAccountForNewContacts(@NonNull android.content.ContentResolver); } @FlaggedApi("android.provider.new_default_account_api_enabled") public static final class ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState { @@ -37429,6 +37436,7 @@ package android.provider { field public static final String ACTION_APPLICATION_SETTINGS = "android.settings.APPLICATION_SETTINGS"; field public static final String ACTION_APP_LOCALE_SETTINGS = "android.settings.APP_LOCALE_SETTINGS"; field public static final String ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS = "android.settings.APP_NOTIFICATION_BUBBLE_SETTINGS"; + field @FlaggedApi("android.app.api_rich_ongoing") public static final String ACTION_APP_NOTIFICATION_PROMOTION_SETTINGS = "android.settings.APP_NOTIFICATION_PROMOTION_SETTINGS"; field public static final String ACTION_APP_NOTIFICATION_SETTINGS = "android.settings.APP_NOTIFICATION_SETTINGS"; field public static final String ACTION_APP_OPEN_BY_DEFAULT_SETTINGS = "android.settings.APP_OPEN_BY_DEFAULT_SETTINGS"; field public static final String ACTION_APP_SEARCH_SETTINGS = "android.settings.APP_SEARCH_SETTINGS"; @@ -54956,6 +54964,7 @@ package android.view.accessibility { method public boolean addAccessibilityStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener); method public void addAccessibilityStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener, @Nullable android.os.Handler); method public void addAudioDescriptionRequestedChangeListener(@NonNull java.util.concurrent.Executor, @NonNull android.view.accessibility.AccessibilityManager.AudioDescriptionRequestedChangeListener); + method @FlaggedApi("com.android.graphics.hwui.flags.high_contrast_text_small_text_rect") public void addHighContrastTextStateChangeListener(@NonNull java.util.concurrent.Executor, @NonNull android.view.accessibility.AccessibilityManager.HighContrastTextStateChangeListener); method public boolean addTouchExplorationStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener); method public void addTouchExplorationStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, @Nullable android.os.Handler); method @ColorInt public int getAccessibilityFocusColor(); @@ -54968,12 +54977,14 @@ package android.view.accessibility { method public static boolean isAccessibilityButtonSupported(); method public boolean isAudioDescriptionRequested(); method public boolean isEnabled(); + method @FlaggedApi("com.android.graphics.hwui.flags.high_contrast_text_small_text_rect") public boolean isHighContrastTextEnabled(); method public boolean isRequestFromAccessibilityTool(); method public boolean isTouchExplorationEnabled(); method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer); method public boolean removeAccessibilityServicesStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener); method public boolean removeAccessibilityStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener); method public boolean removeAudioDescriptionRequestedChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AudioDescriptionRequestedChangeListener); + method @FlaggedApi("com.android.graphics.hwui.flags.high_contrast_text_small_text_rect") public void removeHighContrastTextStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.HighContrastTextStateChangeListener); method public boolean removeTouchExplorationStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener); method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent); field public static final int FLAG_CONTENT_CONTROLS = 4; // 0x4 @@ -54993,6 +55004,10 @@ package android.view.accessibility { method public void onAudioDescriptionRequestedChanged(boolean); } + @FlaggedApi("com.android.graphics.hwui.flags.high_contrast_text_small_text_rect") public static interface AccessibilityManager.HighContrastTextStateChangeListener { + method public void onHighContrastTextStateChanged(boolean); + } + public static interface AccessibilityManager.TouchExplorationStateChangeListener { method public void onTouchExplorationStateChanged(boolean); } @@ -61645,6 +61660,7 @@ package android.window { method public void unregisterOnBackInvokedCallback(@NonNull android.window.OnBackInvokedCallback); field public static final int PRIORITY_DEFAULT = 0; // 0x0 field public static final int PRIORITY_OVERLAY = 1000000; // 0xf4240 + field @FlaggedApi("com.android.window.flags.predictive_back_priority_system_navigation_observer") public static final int PRIORITY_SYSTEM_NAVIGATION_OBSERVER = -2; // 0xfffffffe } public interface SplashScreen { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 4b6c62ecb032..8edfc21036ad 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -694,6 +694,7 @@ package android.app { field public static final String OPSTR_PROJECT_MEDIA = "android:project_media"; field @FlaggedApi("android.view.contentprotection.flags.rapid_clear_notifications_by_listener_app_op_enabled") public static final String OPSTR_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER = "android:rapid_clear_notifications_by_listener"; field public static final String OPSTR_READ_CLIPBOARD = "android:read_clipboard"; + field @FlaggedApi("android.permission.flags.replace_body_sensor_permission_enabled") public static final String OPSTR_READ_HEART_RATE = "android:read_heart_rate"; field public static final String OPSTR_READ_ICC_SMS = "android:read_icc_sms"; field public static final String OPSTR_READ_MEDIA_AUDIO = "android:read_media_audio"; field public static final String OPSTR_READ_MEDIA_IMAGES = "android:read_media_images"; @@ -3495,8 +3496,8 @@ package android.companion.virtual { method @NonNull public android.content.Context createContext(); method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.companion.virtual.audio.VirtualAudioDevice createVirtualAudioDevice(@NonNull android.hardware.display.VirtualDisplay, @Nullable java.util.concurrent.Executor, @Nullable android.companion.virtual.audio.VirtualAudioDevice.AudioConfigurationChangeCallback); method @FlaggedApi("android.companion.virtual.flags.virtual_camera") @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.companion.virtual.camera.VirtualCamera createVirtualCamera(@NonNull android.companion.virtual.camera.VirtualCameraConfig); - method @Deprecated @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback); - method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull android.hardware.display.VirtualDisplayConfig, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback); + method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback); + method @Nullable @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull android.hardware.display.VirtualDisplayConfig, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback); method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualDpad createVirtualDpad(@NonNull android.hardware.input.VirtualDpadConfig); method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.input.VirtualKeyboardConfig); method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int); @@ -3509,8 +3510,9 @@ package android.companion.virtual { method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualTouchscreen createVirtualTouchscreen(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int); method public int getDeviceId(); method @FlaggedApi("android.companion.virtual.flags.vdm_public_apis") @Nullable public String getPersistentDeviceId(); - method @NonNull public java.util.List<android.companion.virtual.sensor.VirtualSensor> getVirtualSensorList(); - method public void launchPendingIntent(int, @NonNull android.app.PendingIntent, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.IntConsumer); + method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public java.util.List<android.companion.virtual.sensor.VirtualSensor> getVirtualSensorList(); + method @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void goToSleep(); + method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void launchPendingIntent(int, @NonNull android.app.PendingIntent, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.IntConsumer); method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void registerIntentInterceptor(@NonNull android.content.IntentFilter, @NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback); method public void removeActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener); method @FlaggedApi("android.companion.virtual.flags.dynamic_policy") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void removeActivityPolicyExemption(@NonNull android.content.ComponentName); @@ -3521,6 +3523,7 @@ package android.companion.virtual { method @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setDisplayImePolicy(int, int); method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setShowPointerIcon(boolean); method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void unregisterIntentInterceptor(@NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback); + method @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void wakeUp(); } public final class VirtualDeviceParams implements android.os.Parcelable { @@ -8540,11 +8543,14 @@ package android.media.tv.tuner.filter { method public long getAudioHandle(); method @NonNull public java.util.List<android.media.AudioPresentation> getAudioPresentations(); method public long getAvDataId(); + method @FlaggedApi("android.media.tv.flags.tuner_w_apis") public int getDataGroupId(); method public long getDataLength(); method public long getDts(); method @Nullable public android.media.tv.tuner.filter.AudioDescriptor getExtraMetaData(); + method @FlaggedApi("android.media.tv.flags.tuner_w_apis") @IntRange(from=0) public int getIndexInDataGroup(); method @Nullable public android.media.MediaCodec.LinearBlock getLinearBlock(); method @IntRange(from=0) public int getMpuSequenceNumber(); + method @FlaggedApi("android.media.tv.flags.tuner_w_apis") @IntRange(from=0) public int getNumDataPieces(); method public long getOffset(); method public long getPts(); method public int getScIndexMask(); @@ -11950,6 +11956,15 @@ package android.provider { field @Deprecated public static final String STATE = "state"; } + @FlaggedApi("android.provider.new_default_account_api_enabled") public static final class ContactsContract.RawContacts.DefaultAccount { + method @FlaggedApi("android.provider.new_default_account_api_enabled") @NonNull @RequiresPermission(android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS) public static java.util.List<android.accounts.Account> getEligibleCloudAccounts(@NonNull android.content.ContentResolver); + method @FlaggedApi("android.provider.new_default_account_api_enabled") @RequiresPermission(allOf={android.Manifest.permission.READ_CONTACTS, android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS}) public static int getNumberOfMovableLocalContacts(@NonNull android.content.ContentResolver); + method @FlaggedApi("android.provider.new_default_account_api_enabled") @RequiresPermission(allOf={android.Manifest.permission.READ_CONTACTS, android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS}) public static int getNumberOfMovableSimContacts(@NonNull android.content.ContentResolver); + method @FlaggedApi("android.provider.new_default_account_api_enabled") @RequiresPermission(allOf={android.Manifest.permission.WRITE_CONTACTS, android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS}) public static void moveLocalContactsToCloudDefaultAccount(@NonNull android.content.ContentResolver); + method @FlaggedApi("android.provider.new_default_account_api_enabled") @RequiresPermission(allOf={android.Manifest.permission.WRITE_CONTACTS, android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS}) public static void moveSimContactsToCloudDefaultAccount(@NonNull android.content.ContentResolver); + method @FlaggedApi("android.provider.new_default_account_api_enabled") @RequiresPermission(android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS) public static void setDefaultAccountForNewContacts(@NonNull android.content.ContentResolver, @NonNull android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState); + } + public static final class ContactsContract.Settings implements android.provider.ContactsContract.SettingsColumns { method @RequiresPermission(android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS) public static void setDefaultAccount(@NonNull android.content.ContentResolver, @Nullable android.accounts.Account); } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 9bcdf959a6a7..76e9ca060547 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -2603,7 +2603,7 @@ package android.os { public abstract class Vibrator { method public int getDefaultVibrationIntensity(int); - method @Nullable public android.os.vibrator.VibratorFrequencyProfile getFrequencyProfile(); + method @Nullable public android.os.vibrator.VibratorFrequencyProfileLegacy getFrequencyProfileLegacy(); method public boolean hasFrequencyControl(); field public static final int VIBRATION_INTENSITY_HIGH = 3; // 0x3 field public static final int VIBRATION_INTENSITY_LOW = 1; // 0x1 @@ -2793,7 +2793,7 @@ package android.os.vibrator { field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.VibrationEffectSegment> CREATOR; } - public final class VibratorFrequencyProfile { + public final class VibratorFrequencyProfileLegacy { method public float getMaxAmplitudeMeasurementInterval(); method @FloatRange(from=0, to=1) @NonNull public float[] getMaxAmplitudeMeasurements(); method public float getMaxFrequency(); diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index d31881265064..3bd121a4a19b 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -1323,4 +1323,12 @@ public abstract class ActivityManagerInternal { */ public abstract void killApplicationSync(String pkgName, int appId, int userId, String reason, int exitInfoReason); + + /** + * Add a creator token for all embedded intents (stored as extra) of the given intent. + * + * @param intent The given intent + * @hide + */ + public abstract void addCreatorToken(Intent intent); } diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 0d183c7c37aa..6ab39b028032 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -68,6 +68,8 @@ import android.window.RemoteTransition; import android.window.SplashScreen; import android.window.WindowContainerToken; +import com.android.window.flags.Flags; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -109,35 +111,64 @@ public class ActivityOptions extends ComponentOptions { MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS, MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE}) public @interface BackgroundActivityStartMode {} + /** - * No explicit value chosen. The system will decide whether to grant privileges. + * The system determines whether to grant background activity start privileges. This is the + * default behavior if no explicit mode is specified. */ public static final int MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED = 0; /** - * Allow the {@link PendingIntent} to use the background activity start privileges. - */ + * Grants the {@link PendingIntent} background activity start privileges. + * + * This behaves the same as {@link #MODE_BACKGROUND_ACTIVITY_START_ALLOWED_ALWAYS}, except it + * does not grant background activity launch permissions based on the privileged permission + * <code>START_ACTIVITIES_FROM_BACKGROUND</code>. + * + * @deprecated Use {@link #MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE} to allow starts + * only when the app is visible or {@link #MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS} to + * allow starts at any time (see <a + * href="https://developer.android.com/guide/components/activities/background-starts"> + * Restrictions on starting activities from the background</a>). + */ + @Deprecated + @FlaggedApi(Flags.FLAG_BAL_ADDITIONAL_START_MODES) public static final int MODE_BACKGROUND_ACTIVITY_START_ALLOWED = 1; /** - * Deny the {@link PendingIntent} to use the background activity start privileges. + * Denies the {@link PendingIntent} any background activity start privileges. */ + @FlaggedApi(Flags.FLAG_BAL_ADDITIONAL_START_MODES) public static final int MODE_BACKGROUND_ACTIVITY_START_DENIED = 2; /** - * Allow the {@link PendingIntent} to use ALL background activity start privileges, including - * special permissions that will allow starts at any time. + * Grants the {@link PendingIntent} all background activity start privileges, including + * those normally reserved for privileged contexts (e.g., companion apps or those with the + * {@code START_ACTIVITIES_FROM_BACKGROUND} permission). * - * @hide + * <p><b>Caution:</b> This mode should be used sparingly. Most apps should use + * {@link #MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE} instead, relying on notifications + * or foreground services for background interactions to minimize user disruption. However, + * this mode is necessary for specific use cases, such as companion apps responding to + * prompts from a connected device. + * + * <p>For more information on background activity start restrictions, see: + * <a href="https://developer.android.com/guide/components/activities/background-starts"> + * Restrictions on starting activities from the background</a> */ + @FlaggedApi(Flags.FLAG_BAL_ADDITIONAL_START_MODES) public static final int MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS = 3; /** - * Allow the {@link PendingIntent} to use background activity start privileges based on - * visibility of the app. + * Grants the {@link PendingIntent} background activity start privileges only when the app + * has a visible window (i.e., is visible to the user). This is the recommended mode for most + * apps to minimize disruption to the user experience. * - * @hide + * <p>For more information on background activity start restrictions, see: + * <a href="https://developer.android.com/guide/components/activities/background-starts"> + * Restrictions on starting activities from the background</a> */ + @FlaggedApi(Flags.FLAG_BAL_ADDITIONAL_START_MODES) public static final int MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE = 4; /** - * Special behavior for compatibility. - * Similar to {@link #MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED} + * Provides compatibility with previous Android versions regarding background activity starts. + * Similar to {@link #MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED}. * * @hide */ diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 5b556cc22640..0c02ba44fddb 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1960,8 +1960,12 @@ public final class ActivityThread extends ClientTransactionHandler @Override public void dumpCacheInfo(ParcelFileDescriptor pfd, String[] args) { - PropertyInvalidatedCache.dumpCacheInfo(pfd, args); - IoUtils.closeQuietly(pfd); + try { + PropertyInvalidatedCache.dumpCacheInfo(pfd, args); + BroadcastStickyCache.dump(pfd); + } finally { + IoUtils.closeQuietly(pfd); + } } private File getDatabasesDir(Context context) { @@ -6281,7 +6285,7 @@ public final class ActivityThread extends ClientTransactionHandler } r.activity.mConfigChangeFlags |= configChanges; - r.mPreserveWindow = tmp.mPreserveWindow; + r.mPreserveWindow = r.activity.mWindowAdded && tmp.mPreserveWindow; r.activity.mChangingConfigurations = true; diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index f27dc322a2b7..0472ff8c9f50 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -54,6 +54,7 @@ import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.database.DatabaseUtils; import android.health.connect.HealthConnectManager; +import android.health.connect.HealthPermissions; import android.media.AudioAttributes.AttributeUsage; import android.media.MediaRouter2; import android.os.Binder; @@ -1607,9 +1608,12 @@ public class AppOpsManager { public static final int OP_RECEIVE_SENSITIVE_NOTIFICATIONS = AppProtoEnums.APP_OP_RECEIVE_SENSITIVE_NOTIFICATIONS; + /** @hide Access to read heart rate sensor. */ + public static final int OP_READ_HEART_RATE = AppProtoEnums.APP_OP_READ_HEART_RATE; + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final int _NUM_OP = 149; + public static final int _NUM_OP = 150; /** * All app ops represented as strings. @@ -1762,6 +1766,7 @@ public class AppOpsManager { OPSTR_UNARCHIVAL_CONFIRMATION, OPSTR_EMERGENCY_LOCATION, OPSTR_RECEIVE_SENSITIVE_NOTIFICATIONS, + OPSTR_READ_HEART_RATE, }) public @interface AppOpString {} @@ -2499,6 +2504,11 @@ public class AppOpsManager { public static final String OPSTR_RECEIVE_SENSITIVE_NOTIFICATIONS = "android:receive_sensitive_notifications"; + /** @hide Access to read heart rate sensor. */ + @SystemApi + @FlaggedApi(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) + public static final String OPSTR_READ_HEART_RATE = "android:read_heart_rate"; + /** {@link #sAppOpsToNote} not initialized yet for this op */ private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0; /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */ @@ -2572,6 +2582,8 @@ public class AppOpsManager { OP_NEARBY_WIFI_DEVICES, // Notifications OP_POST_NOTIFICATION, + // Health + Flags.replaceBodySensorPermissionEnabled() ? OP_READ_HEART_RATE : OP_NONE, }; /** @@ -2612,6 +2624,7 @@ public class AppOpsManager { OP_READ_SYSTEM_GRAMMATICAL_GENDER, }; + @SuppressWarnings("FlaggedApi") static final AppOpInfo[] sAppOpInfos = new AppOpInfo[]{ new AppOpInfo.Builder(OP_COARSE_LOCATION, OPSTR_COARSE_LOCATION, "COARSE_LOCATION") .setPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) @@ -3079,6 +3092,10 @@ public class AppOpsManager { new AppOpInfo.Builder(OP_RECEIVE_SENSITIVE_NOTIFICATIONS, OPSTR_RECEIVE_SENSITIVE_NOTIFICATIONS, "RECEIVE_SENSITIVE_NOTIFICATIONS") .setDefaultMode(MODE_IGNORED).build(), + new AppOpInfo.Builder(OP_READ_HEART_RATE, OPSTR_READ_HEART_RATE, "READ_HEART_RATE") + .setPermission(Flags.replaceBodySensorPermissionEnabled() ? + HealthPermissions.READ_HEART_RATE : null) + .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(), }; // The number of longs needed to form a full bitmask of app ops @@ -3132,6 +3149,10 @@ public class AppOpsManager { } } for (int op : RUNTIME_PERMISSION_OPS) { + if (op == OP_NONE) { + // Skip ops with a disabled feature flag. + continue; + } if (sAppOpInfos[op].permission != null) { sPermToOp.put(sAppOpInfos[op].permission, op); } @@ -10153,6 +10174,9 @@ public class AppOpsManager { } p.writeInt(Parcel.EX_HAS_NOTED_APPOPS_REPLY_HEADER); + final int sizePosition = p.dataPosition(); + // Write size placeholder. With this size we can easily skip it in native. + p.writeInt(0); int numAttributionWithNotesAppOps = notedAppOps.size(); p.writeInt(numAttributionWithNotesAppOps); @@ -10169,6 +10193,12 @@ public class AppOpsManager { } } } + + final int payloadPosition = p.dataPosition(); + p.setDataPosition(sizePosition); + // Total header size including 4 bytes size itself. + p.writeInt(payloadPosition - sizePosition); + p.setDataPosition(payloadPosition); } /** @@ -10182,6 +10212,8 @@ public class AppOpsManager { * @hide */ public static void readAndLogNotedAppops(@NonNull Parcel p) { + // Skip size. + p.readInt(); int numAttributionsWithNotedAppOps = p.readInt(); for (int i = 0; i < numAttributionsWithNotedAppOps; i++) { diff --git a/core/java/android/app/ApplicationStartInfo.java b/core/java/android/app/ApplicationStartInfo.java index edcdb6cc58ea..f34341fd14e1 100644 --- a/core/java/android/app/ApplicationStartInfo.java +++ b/core/java/android/app/ApplicationStartInfo.java @@ -34,6 +34,7 @@ import android.util.proto.ProtoInputStream; import android.util.proto.ProtoOutputStream; import android.util.proto.WireTypeMismatchException; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.XmlUtils; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; @@ -777,7 +778,9 @@ public final class ApplicationStartInfo implements Parcelable { mStartComponent = other.mStartComponent; } - private ApplicationStartInfo(@NonNull Parcel in) { + /** @hide */ + @VisibleForTesting + public ApplicationStartInfo(@NonNull Parcel in) { mStartupState = in.readInt(); mPid = in.readInt(); mRealUid = in.readInt(); @@ -1061,12 +1064,21 @@ public final class ApplicationStartInfo implements Parcelable { if (other == null || !(other instanceof ApplicationStartInfo)) { return false; } + final ApplicationStartInfo o = (ApplicationStartInfo) other; - return mPid == o.mPid && mRealUid == o.mRealUid && mPackageUid == o.mPackageUid - && mDefiningUid == o.mDefiningUid && mReason == o.mReason - && mStartupState == o.mStartupState && mStartType == o.mStartType - && mLaunchMode == o.mLaunchMode && TextUtils.equals(mProcessName, o.mProcessName) - && timestampsEquals(o) && mWasForceStopped == o.mWasForceStopped + + return mPid == o.mPid + && mRealUid == o.mRealUid + && mPackageUid == o.mPackageUid + && mDefiningUid == o.mDefiningUid + && mReason == o.mReason + && mStartupState == o.mStartupState + && mStartType == o.mStartType + && mLaunchMode == o.mLaunchMode + && TextUtils.equals(mPackageName, o.mPackageName) + && TextUtils.equals(mProcessName, o.mProcessName) + && timestampsEquals(o) + && mWasForceStopped == o.mWasForceStopped && mMonoticCreationTimeMs == o.mMonoticCreationTimeMs && mStartComponent == o.mStartComponent; } @@ -1074,7 +1086,7 @@ public final class ApplicationStartInfo implements Parcelable { @Override public int hashCode() { return Objects.hash(mPid, mRealUid, mPackageUid, mDefiningUid, mReason, mStartupState, - mStartType, mLaunchMode, mProcessName, mStartupTimestampsNs, + mStartType, mLaunchMode, mPackageName, mProcessName, mStartupTimestampsNs, mMonoticCreationTimeMs, mStartComponent); } diff --git a/core/java/android/app/BroadcastStickyCache.java b/core/java/android/app/BroadcastStickyCache.java index d6f061be3b00..ea8173191a3f 100644 --- a/core/java/android/app/BroadcastStickyCache.java +++ b/core/java/android/app/BroadcastStickyCache.java @@ -27,16 +27,21 @@ import android.net.TetheringManager; import android.net.nsd.NsdManager; import android.net.wifi.WifiManager; import android.net.wifi.p2p.WifiP2pManager; +import android.os.ParcelFileDescriptor; import android.os.SystemProperties; import android.os.UpdateLock; import android.telephony.TelephonyManager; import android.util.ArrayMap; +import android.util.IndentingPrintWriter; import android.view.WindowManagerPolicyConstants; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; +import com.android.internal.util.FastPrintWriter; +import java.io.FileOutputStream; +import java.io.PrintWriter; import java.util.ArrayList; /** @hide */ @@ -214,6 +219,41 @@ public class BroadcastStickyCache { } } + public static void dump(@NonNull ParcelFileDescriptor pfd) { + if (!Flags.useStickyBcastCache()) { + return; + } + final PrintWriter pw = new FastPrintWriter(new FileOutputStream(pfd.getFileDescriptor())); + synchronized (sCachedStickyBroadcasts) { + dumpLocked(pw); + } + pw.flush(); + } + + @GuardedBy("sCachedStickyBroadcasts") + private static void dumpLocked(@NonNull PrintWriter pw) { + final IndentingPrintWriter ipw = new IndentingPrintWriter( + pw, " " /* singleIndent */, " " /* prefix */); + ipw.println("Cached sticky broadcasts:"); + ipw.increaseIndent(); + final int count = sCachedStickyBroadcasts.size(); + if (count == 0) { + ipw.println("<empty>"); + } else { + for (int i = 0; i < count; ++i) { + final CachedStickyBroadcast cachedStickyBroadcast = sCachedStickyBroadcasts.get(i); + ipw.print("Entry #"); ipw.print(i); ipw.println(":"); + ipw.increaseIndent(); + ipw.print("filter="); ipw.println(cachedStickyBroadcast.filter.toLongString()); + ipw.print("intent="); ipw.println(cachedStickyBroadcast.intent); + ipw.print("version="); ipw.println(cachedStickyBroadcast.version); + ipw.print("handle="); ipw.println(cachedStickyBroadcast.propertyHandle); + ipw.decreaseIndent(); + } + } + ipw.decreaseIndent(); + } + private static final class CachedStickyBroadcast { @NonNull public final IntentFilter filter; @Nullable public Intent intent; diff --git a/core/java/android/app/IUserSwitchObserver.aidl b/core/java/android/app/IUserSwitchObserver.aidl index cfdb426d6026..1ff7a17e578f 100644 --- a/core/java/android/app/IUserSwitchObserver.aidl +++ b/core/java/android/app/IUserSwitchObserver.aidl @@ -19,10 +19,10 @@ package android.app; import android.os.IRemoteCallback; /** {@hide} */ -oneway interface IUserSwitchObserver { +interface IUserSwitchObserver { void onBeforeUserSwitching(int newUserId); - void onUserSwitching(int newUserId, IRemoteCallback reply); - void onUserSwitchComplete(int newUserId); - void onForegroundProfileSwitch(int newProfileId); - void onLockedBootComplete(int newUserId); + oneway void onUserSwitching(int newUserId, IRemoteCallback reply); + oneway void onUserSwitchComplete(int newUserId); + oneway void onForegroundProfileSwitch(int newProfileId); + oneway void onLockedBootComplete(int newUserId); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index e8b0a36ffcfc..bc7ebce5c5c2 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -809,6 +809,15 @@ public class Notification implements Parcelable return false; } + private static boolean isStandardLayout(int layoutId) { + if (Flags.apiRichOngoing()) { + if (layoutId == R.layout.notification_template_material_progress) { + return true; + } + } + return STANDARD_LAYOUTS.contains(layoutId); + } + /** @hide */ @IntDef(flag = true, prefix = {"FLAG_"}, value = { FLAG_SHOW_LIGHTS, @@ -1637,16 +1646,16 @@ public class Notification implements Parcelable public static final String EXTRA_PROGRESS_SEGMENTS = "android.progressSegments"; /** - * {@link #extras} key: an arraylist of {@link android.app.Notification.ProgressStyle.Step} + * {@link #extras} key: an arraylist of {@link ProgressStyle.Point} * bundles provided by a * {@link android.app.Notification.ProgressStyle} notification as supplied to - * {@link ProgressStyle#setProgressSteps} - * or {@link ProgressStyle#addProgressStep(ProgressStyle.Step)}. + * {@link ProgressStyle#setProgressPoints} + * or {@link ProgressStyle#addProgressPoint(ProgressStyle.Point)}. * This extra is a parcelable array list of bundles. * @hide */ @FlaggedApi(Flags.FLAG_API_RICH_ONGOING) - public static final String EXTRA_PROGRESS_STEPS = "android.progressSteps"; + public static final String EXTRA_PROGRESS_POINTS = "android.progressPoints"; /** * {@link #extras} key: whether the progress bar should be styled by its progress as @@ -5983,9 +5992,9 @@ public class Notification implements Parcelable } } boolean contentViewUsesHeader = mN.contentView == null - || STANDARD_LAYOUTS.contains(mN.contentView.getLayoutId()); + || isStandardLayout(mN.contentView.getLayoutId()); boolean bigContentViewUsesHeader = mN.bigContentView == null - || STANDARD_LAYOUTS.contains(mN.bigContentView.getLayoutId()); + || isStandardLayout(mN.bigContentView.getLayoutId()); return contentViewUsesHeader && bigContentViewUsesHeader; } @@ -6781,7 +6790,7 @@ public class Notification implements Parcelable return false; } if (fullyCustomViewRequiresDecoration(false) - && STANDARD_LAYOUTS.contains(customContent.getLayoutId())) { + && isStandardLayout(customContent.getLayoutId())) { // If the app's custom views are objects returned from Builder.create*ContentView() // then the app is most likely attempting to spoof the user. Even if they are not, // the result would be broken (b/189189308) so we will ignore it. @@ -7679,6 +7688,10 @@ public class Notification implements Parcelable return R.layout.notification_template_material_conversation; } + private int getProgressLayoutResource() { + return R.layout.notification_template_material_progress; + } + private int getActionLayoutResource() { return R.layout.notification_material_action; } @@ -11159,7 +11172,7 @@ public class Notification implements Parcelable /** * A Notification Style used to to define a notification whose expanded state includes - * a highly customizable progress bar with segments, steps, a custom tracker icon, + * a highly customizable progress bar with segments, points, a custom tracker icon, * and custom icons at the start and end of the progress bar. * * This style is suggested for use cases where the app is showing a tracker to the @@ -11185,8 +11198,8 @@ public class Notification implements Parcelable * .addProgressSegment(new Segment(552).setColor(Color.YELLOW)) * .addProgressSegment(new Segment(253).setColor(Color.YELLOW)) * .addProgressSegment(new Segment(94).setColor(Color.BLUE)) - * .addProgressStep(new Step(60).setColor(Color.RED)) - * .addProgressStep(new Step(560).setColor(Color.YELLOW)) + * .addProgressPoint(new Point(60).setColor(Color.RED)) + * .addProgressPoint(new Point(560).setColor(Color.YELLOW)) * ) * </pre> * @@ -11199,17 +11212,17 @@ public class Notification implements Parcelable */ @FlaggedApi(Flags.FLAG_API_RICH_ONGOING) public static class ProgressStyle extends Notification.Style { - private static final String KEY_ELEMENT_STABLE_ID = "stableId"; + private static final String KEY_ELEMENT_ID = "id"; private static final String KEY_ELEMENT_COLOR = "colorInt"; private static final String KEY_SEGMENT_LENGTH = "length"; - private static final String KEY_STEP_POSITION = "position"; + private static final String KEY_POINT_POSITION = "position"; private static final int MAX_PROGRESS_SEGMENT_LIMIT = 15; - private static final int MAX_PROGRESS_STEP_LIMIT = 5; + private static final int MAX_PROGRESS_STOP_LIMIT = 5; private static final int DEFAULT_PROGRESS_MAX = 100; private List<Segment> mProgressSegments = new ArrayList<>(); - private List<Step> mProgressSteps = new ArrayList<>(); + private List<Point> mProgressPoints = new ArrayList<>(); private int mProgress = 0; @@ -11246,7 +11259,7 @@ public class Notification implements Parcelable nonIndeterminateCheckResult = !Objects.equals(mProgress, progressStyle.mProgress) || !Objects.equals(mIsStyledByProgress, progressStyle.mIsStyledByProgress) || !Objects.equals(mProgressSegments, progressStyle.mProgressSegments) - || !Objects.equals(mProgressSteps, progressStyle.mProgressSteps) + || !Objects.equals(mProgressPoints, progressStyle.mProgressPoints) || !Objects.equals(mTrackerIcon, progressStyle.mTrackerIcon); } @@ -11300,48 +11313,47 @@ public class Notification implements Parcelable } /** - * Gets the steps that are displayed on the progress bar. + * Gets the points that are displayed on the progress bar. *. - * @see #setProgressSteps - * @see #addProgressStep - * @see Step + * @see #setProgressPoints + * @see #addProgressPoint + * @see Point */ - public @NonNull List<Step> getProgressSteps() { - return mProgressSteps; + public @NonNull List<Point> getProgressPoints() { + return mProgressPoints; } /** - * Replaces all the progress steps. + * Replaces all the progress points. * - * Steps are designated points within a progressbar to visualize - * distinct stages or milestones. - * For example, you might use steps to mark stops in a multi-stop - * navigation journey, where each step represents a destination. - * @see Step + * Points within a progress bar are used to visualize distinct stages or milestones. + * For example, you might use points to mark stops in a multi-stop + * navigation journey, where each point represents a destination. + * @see Point */ - public @NonNull ProgressStyle setProgressSteps(@NonNull List<Step> steps) { - mProgressSteps = new ArrayList<>(steps); + public @NonNull ProgressStyle setProgressPoints(@NonNull List<Point> points) { + mProgressPoints = new ArrayList<>(points); return this; } /** - * Adds another step. + * Adds another point. * - * Steps are designated points within a progressbar to visualize - * distinct stages or milestones. - * For example, you might use steps to mark stops in a multi-stop - * navigation journey, where each step represents a destination. + * Points within a progress bar are used to visualize distinct stages or milestones. * - * Steps can be added in any order, as their + * For example, you might use points to mark stops in a multi-stop + * navigation journey, where each point represents a destination. + * + * Points can be added in any order, as their * position within the progress bar is determined by their individual - * {@link Step#getPosition()}. - * @see Step + * {@link Point#getPosition()}. + * @see Point */ - public @NonNull ProgressStyle addProgressStep(@NonNull Step step) { - if (mProgressSteps == null) { - mProgressSteps = new ArrayList<>(); + public @NonNull ProgressStyle addProgressPoint(@NonNull Point point) { + if (mProgressPoints == null) { + mProgressPoints = new ArrayList<>(); } - mProgressSteps.add(step); + mProgressPoints.add(point); return this; } @@ -11414,7 +11426,7 @@ public class Notification implements Parcelable * When specified, the following fields are ignored: * @see #setProgress * @see #setProgressSegments - * @see #setProgressSteps + * @see #setProgressPoints * @see #setProgressTrackerIcon * @see #setStyledByProgress * @@ -11435,7 +11447,7 @@ public class Notification implements Parcelable } /** - * Indicates whether the segments and steps will be styled differently + * Indicates whether the segments and points will be styled differently * based on whether they are behind or ahead of the current progress. * When true, segments appearing ahead of the current progress will be given a * slightly different appearance to indicate that it is part of the progress bar @@ -11558,8 +11570,8 @@ public class Notification implements Parcelable super.addExtras(extras); extras.putParcelableArrayList(EXTRA_PROGRESS_SEGMENTS, getProgressSegmentsAsBundleList(mProgressSegments)); - extras.putParcelableArrayList(EXTRA_PROGRESS_STEPS, - getProgressStepsAsBundleList(mProgressSteps)); + extras.putParcelableArrayList(EXTRA_PROGRESS_POINTS, + getProgressPointsAsBundleList(mProgressPoints)); extras.putInt(EXTRA_PROGRESS, mProgress); extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mIndeterminate); @@ -11599,8 +11611,8 @@ public class Notification implements Parcelable mTrackerIcon = extras.getParcelable(EXTRA_PROGRESS_TRACKER_ICON, Icon.class); mStartIcon = extras.getParcelable(EXTRA_PROGRESS_START_ICON, Icon.class); mEndIcon = extras.getParcelable(EXTRA_PROGRESS_END_ICON, Icon.class); - mProgressSteps = getProgressStepsFromBundleList( - extras.getParcelableArrayList(EXTRA_PROGRESS_STEPS, Bundle.class)); + mProgressPoints = getProgressPointsFromBundleList( + extras.getParcelableArrayList(EXTRA_PROGRESS_POINTS, Bundle.class)); } /** @@ -11613,6 +11625,61 @@ public class Notification implements Parcelable // actually be included. return true; } + /** + * @hide + */ + @Override + public RemoteViews makeContentView(boolean increasedHeight) { + final StandardTemplateParams p = mBuilder.mParams.reset() + .viewType(StandardTemplateParams.VIEW_TYPE_NORMAL) + .hideProgress(true) + .fillTextsFrom(mBuilder); + + return getStandardView(mBuilder.getBaseLayoutResource(), p, null /* result */); + } + /** + * @hide + */ + @Override + public RemoteViews makeHeadsUpContentView(boolean increasedHeight) { + final StandardTemplateParams p = mBuilder.mParams.reset() + .viewType(StandardTemplateParams.VIEW_TYPE_HEADS_UP) + .hideProgress(true) + .fillTextsFrom(mBuilder); + + return getStandardView(mBuilder.getHeadsUpBaseLayoutResource(), p, null /* result */); + } + /** + * @hide + */ + @Override + public RemoteViews makeBigContentView() { + StandardTemplateParams p = mBuilder.mParams.reset() + .viewType(StandardTemplateParams.VIEW_TYPE_BIG) + .allowTextWithProgress(true) + .fillTextsFrom(mBuilder); + + // Replace the text with the big text, but only if the big text is not empty. + RemoteViews contentView = getStandardView(mBuilder.getProgressLayoutResource(), p, + null /* result */); + + // Bind progress start and end icons. + if (mStartIcon != null) { + contentView.setViewVisibility(R.id.notification_progress_start_icon, View.VISIBLE); + contentView.setImageViewIcon(R.id.notification_progress_start_icon, mStartIcon); + } else { + contentView.setViewVisibility(R.id.notification_progress_start_icon, View.GONE); + } + + if (mEndIcon != null) { + contentView.setViewVisibility(R.id.notification_progress_end_icon, View.VISIBLE); + contentView.setImageViewIcon(R.id.notification_progress_end_icon, mEndIcon); + } else { + contentView.setViewVisibility(R.id.notification_progress_end_icon, View.GONE); + } + + return contentView; + } private static @NonNull ArrayList<Bundle> getProgressSegmentsAsBundleList( @Nullable List<Segment> progressSegments) { @@ -11626,7 +11693,7 @@ public class Notification implements Parcelable final Bundle bundle = new Bundle(); bundle.putInt(KEY_SEGMENT_LENGTH, segment.getLength()); - bundle.putInt(KEY_ELEMENT_STABLE_ID, segment.getStableId()); + bundle.putInt(KEY_ELEMENT_ID, segment.getId()); bundle.putInt(KEY_ELEMENT_COLOR, segment.getColor()); segments.add(bundle); @@ -11647,11 +11714,11 @@ public class Notification implements Parcelable continue; } - final int stableId = segmentBundle.getInt(KEY_ELEMENT_STABLE_ID); + final int id = segmentBundle.getInt(KEY_ELEMENT_ID); final int color = segmentBundle.getInt(KEY_ELEMENT_COLOR, Notification.COLOR_DEFAULT); final Segment segment = new Segment(length) - .setStableId(stableId).setColor(color); + .setId(id).setColor(color); segments.add(segment); } @@ -11660,48 +11727,48 @@ public class Notification implements Parcelable return segments; } - private static @NonNull ArrayList<Bundle> getProgressStepsAsBundleList( - @Nullable List<Step> progressSteps) { - final ArrayList<Bundle> steps = new ArrayList<>(); - if (progressSteps != null && !progressSteps.isEmpty()) { - for (int i = 0; i < progressSteps.size(); i++) { - final Step step = progressSteps.get(i); - if (step.getPosition() < 0) { + private static @NonNull ArrayList<Bundle> getProgressPointsAsBundleList( + @Nullable List<Point> progressPoints) { + final ArrayList<Bundle> points = new ArrayList<>(); + if (progressPoints != null && !progressPoints.isEmpty()) { + for (int i = 0; i < progressPoints.size(); i++) { + final Point point = progressPoints.get(i); + if (point.getPosition() < 0) { continue; } final Bundle bundle = new Bundle(); - bundle.putInt(KEY_STEP_POSITION, step.getPosition()); - bundle.putInt(KEY_ELEMENT_STABLE_ID, step.getStableId()); - bundle.putInt(KEY_ELEMENT_COLOR, step.getColor()); + bundle.putInt(KEY_POINT_POSITION, point.getPosition()); + bundle.putInt(KEY_ELEMENT_ID, point.getId()); + bundle.putInt(KEY_ELEMENT_COLOR, point.getColor()); - steps.add(bundle); + points.add(bundle); } } - return steps; + return points; } - private static @NonNull List<Step> getProgressStepsFromBundleList( - @Nullable List<Bundle> stepBundleList) { - final ArrayList<Step> steps = new ArrayList<>(); + private static @NonNull List<Point> getProgressPointsFromBundleList( + @Nullable List<Bundle> pointBundleList) { + final ArrayList<Point> points = new ArrayList<>(); - if (stepBundleList != null && !stepBundleList.isEmpty()) { - for (int i = 0; i < stepBundleList.size(); i++) { - final Bundle segmentBundle = stepBundleList.get(i); - final int position = segmentBundle.getInt(KEY_STEP_POSITION); + if (pointBundleList != null && !pointBundleList.isEmpty()) { + for (int i = 0; i < pointBundleList.size(); i++) { + final Bundle pointBundle = pointBundleList.get(i); + final int position = pointBundle.getInt(KEY_POINT_POSITION); if (position < 0) { continue; } - final int stableId = segmentBundle.getInt(KEY_ELEMENT_STABLE_ID); - final int color = segmentBundle.getInt(KEY_ELEMENT_COLOR, + final int id = pointBundle.getInt(KEY_ELEMENT_ID); + final int color = pointBundle.getInt(KEY_ELEMENT_COLOR, Notification.COLOR_DEFAULT); - final Step step = new Step(position).setStableId(stableId).setColor(color); - steps.add(step); + final Point point = new Point(position).setId(id).setColor(color); + points.add(point); } } - return steps; + return points; } /** @@ -11712,7 +11779,7 @@ public class Notification implements Parcelable */ public static final class Segment { private int mLength; - private int mStableId = 0; + private int mId = 0; @ColorInt private int mColor = Notification.COLOR_DEFAULT; @@ -11735,19 +11802,19 @@ public class Notification implements Parcelable } /** - * Gets the stable id of this Segment. + * Gets the id of this Segment. * - * @see #setStableId + * @see #setId */ - public int getStableId() { - return mStableId; + public int getId() { + return mId; } /** * Optional ID used to uniquely identify the element across updates. */ - public @NonNull Segment setStableId(int stableId) { - mStableId = stableId; + public @NonNull Segment setId(int id) { + mId = id; return this; } @@ -11776,45 +11843,44 @@ public class Notification implements Parcelable public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - Segment segment = (Segment) o; - return mLength == segment.mLength && mStableId == segment.mStableId + final Segment segment = (Segment) o; + return mLength == segment.mLength && mId == segment.mId && mColor == segment.mColor; } @Override public int hashCode() { - return Objects.hash(mLength, mStableId, mColor); + return Objects.hash(mLength, mId, mColor); } } /** - * A step within the progress bar, defining its position and color. - * Steps are designated points within a progressbar to visualize - * distinct stages or milestones. - * For example, you might use steps to mark stops in a multi-stop - * navigation journey, where each step represents a destination. + * A point within the progress bar, defining its position and color. + * Points within a progress bar are used to visualize distinct stages or milestones. + * For example, you might use points to mark stops in a multi-stop + * navigation journey, where each point represents a destination. */ - public static final class Step { + public static final class Point { private int mPosition; - private int mStableId; + private int mId; @ColorInt private int mColor = Notification.COLOR_DEFAULT; /** - * Create a step element. - * The position of this step on the progress bar + * Create a point element. + * The position of this point on the progress bar * relative to {@link ProgressStyle#getProgressMax} * @param position * See {@link #getPosition} */ - public Step(int position) { + public Point(int position) { mPosition = position; } /** - * Gets the position of this Step. - * The position of this step on the progress bar + * Gets the position of this Point. + * The position of this point on the progress bar * relative to {@link ProgressStyle#getProgressMax}. */ public int getPosition() { @@ -11823,17 +11889,17 @@ public class Notification implements Parcelable /** - * Optional ID used to uniqurely identify the element across updates. + * Optional ID used to uniquely identify the element across updates. */ - public int getStableId() { - return mStableId; + public int getId() { + return mId; } /** - * Optional ID used to uniqurely identify the element across updates. + * Optional ID used to uniquely identify the element across updates. */ - public @NonNull Step setStableId(int stableId) { - mStableId = stableId; + public @NonNull Point setId(int id) { + mId = id; return this; } @@ -11850,7 +11916,7 @@ public class Notification implements Parcelable /** * Optional color of this Segment */ - public @NonNull Step setColor(@ColorInt int color) { + public @NonNull Point setColor(@ColorInt int color) { mColor = color; return this; } @@ -11862,14 +11928,14 @@ public class Notification implements Parcelable public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - Step step = (Step) o; - return mPosition == step.mPosition && mStableId == step.mStableId - && mColor == step.mColor; + final Point point = (Point) o; + return mPosition == point.mPosition && mId == point.mId + && mColor == point.mColor; } @Override public int hashCode() { - return Objects.hash(mPosition, mStableId, mColor); + return Objects.hash(mPosition, mId, mColor); } } } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index dfed1f738e44..41abd68c9924 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -958,6 +958,9 @@ public class NotificationManager { * Returns whether the calling app's properly formatted notifications can appear in a promoted * format, which may result in higher ranking, appearances on additional surfaces, and richer * presentation. + * + * Apps can request this permission by sending the user to the activity that matches the system + * intent action {@link android.provider.Settings#ACTION_APP_NOTIFICATION_PROMOTION_SETTINGS}. */ @FlaggedApi(android.app.Flags.FLAG_API_RICH_ONGOING) public boolean canPostPromotedNotifications() { diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index 3714e5de23ca..393ec8c1d66d 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -1094,6 +1094,9 @@ public final class PendingIntent implements Parcelable { @Nullable String requiredPermission, @Nullable Bundle options) throws CanceledException { try { + if (intent != null) { + intent.collectExtraIntentKeys(); + } String resolvedType = intent != null ? intent.resolveTypeIfNeeded(context.getContentResolver()) : null; diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 84a4eb4acddc..a458b4e45796 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -431,16 +431,19 @@ public class ResourcesManager { } /** - * Protected so that tests can override and returns something a fixed value. + * public so that tests can access and override */ @VisibleForTesting - protected @NonNull DisplayMetrics getDisplayMetrics(int displayId, DisplayAdjustments da) { + public @NonNull DisplayMetrics getDisplayMetrics(int displayId, DisplayAdjustments da) { final DisplayManagerGlobal displayManagerGlobal = DisplayManagerGlobal.getInstance(); final DisplayMetrics dm = new DisplayMetrics(); final DisplayInfo displayInfo = displayManagerGlobal != null ? displayManagerGlobal.getDisplayInfo(displayId) : null; if (displayInfo != null) { - displayInfo.getAppMetrics(dm, da); + final Configuration dajConfig = da.getConfiguration(); + displayInfo.getAppMetrics(dm, da.getCompatibilityInfo(), + (mResDisplayId == displayId && Configuration.EMPTY.equals(dajConfig)) + ? mResConfiguration : dajConfig); } else { dm.setToDefaults(); } @@ -1977,6 +1980,7 @@ public class ResourcesManager { public void registerAllResourcesReference(@NonNull Resources resources) { if (android.content.res.Flags.registerResourcePaths()) { synchronized (mLock) { + cleanupReferences(mAllResourceReferences, mAllResourceReferencesQueue); mAllResourceReferences.add( new WeakReference<>(resources, mAllResourceReferencesQueue)); } diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java index af242dda9341..e882bb564db9 100644 --- a/core/java/android/app/TaskInfo.java +++ b/core/java/android/app/TaskInfo.java @@ -275,7 +275,10 @@ public class TaskInfo { public int parentTaskId; /** - * Whether this task is focused. + * Whether this task is focused on the display. This means the task receives input events that + * target the display. + * CAUTION: This can be true for multiple tasks especially when multiple displays are connected + * in the system. * @hide */ public boolean isFocused; diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java index 7903f1c0c5c3..2e6f3e1c7f0a 100644 --- a/core/java/android/app/UiModeManager.java +++ b/core/java/android/app/UiModeManager.java @@ -16,6 +16,7 @@ package android.app; +import static android.app.Flags.enableCurrentModeTypeBinderCache; import static android.app.Flags.enableNightModeBinderCache; import android.annotation.CallbackExecutor; @@ -682,6 +683,53 @@ public class UiModeManager { } } + private Integer getCurrentModeTypeFromServer() { + try { + if (sGlobals != null) { + return sGlobals.mService.getCurrentModeType(); + } + return Configuration.UI_MODE_TYPE_NORMAL; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + + /** + * Retrieve the current running mode type for the user. + */ + private final IpcDataCache.QueryHandler<Void, Integer> mCurrentModeTypeQuery = + new IpcDataCache.QueryHandler<>() { + + @Override + @NonNull + public Integer apply(Void query) { + return getCurrentModeTypeFromServer(); + } + }; + + private static final String CURRENT_MODE_TYPE_API = "getCurrentModeType"; + + /** + * Cache the current running mode type for a user. + */ + private final IpcDataCache<Void, Integer> mCurrentModeTypeCache = + new IpcDataCache<>(1, IpcDataCache.MODULE_SYSTEM, + CURRENT_MODE_TYPE_API, /* cacheName= */ "CurrentModeTypeCache", + mCurrentModeTypeQuery); + + /** + * Invalidate the current mode type cache. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_ENABLE_CURRENT_MODE_TYPE_BINDER_CACHE) + public static void invalidateCurrentModeTypeCache() { + IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, + CURRENT_MODE_TYPE_API); + } + + /** * Return the current running mode type. May be one of * {@link Configuration#UI_MODE_TYPE_NORMAL Configuration.UI_MODE_TYPE_NORMAL}, @@ -693,14 +741,11 @@ public class UiModeManager { * {@link Configuration#UI_MODE_TYPE_VR_HEADSET Configuration.UI_MODE_TYPE_VR_HEADSET}. */ public int getCurrentModeType() { - if (sGlobals != null) { - try { - return sGlobals.mService.getCurrentModeType(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + if (enableCurrentModeTypeBinderCache()) { + return mCurrentModeTypeCache.query(null); + } else { + return getCurrentModeTypeFromServer(); } - return Configuration.UI_MODE_TYPE_NORMAL; } /** diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java index beb93fd079d9..eb0ea1e6ef4f 100644 --- a/core/java/android/app/admin/SecurityLog.java +++ b/core/java/android/app/admin/SecurityLog.java @@ -16,7 +16,10 @@ package android.app.admin; +import static android.nfc.Flags.FLAG_NFC_STATE_CHANGE_SECURITY_LOG_EVENT_ENABLED; + import android.Manifest; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -100,6 +103,8 @@ public class SecurityLog { TAG_PACKAGE_UPDATED, TAG_PACKAGE_UNINSTALLED, TAG_BACKUP_SERVICE_TOGGLED, + TAG_NFC_ENABLED, + TAG_NFC_DISABLED, }) public @interface SecurityLogTag {} @@ -610,6 +615,18 @@ public class SecurityLog { */ public static final int TAG_BACKUP_SERVICE_TOGGLED = SecurityLogTags.SECURITY_BACKUP_SERVICE_TOGGLED; + + /** + * Indicates that NFC service is enabled. There is no extra payload in the log event. + */ + @FlaggedApi(FLAG_NFC_STATE_CHANGE_SECURITY_LOG_EVENT_ENABLED) + public static final int TAG_NFC_ENABLED = SecurityLogTags.SECURITY_NFC_ENABLED; + + /** + * Indicates that NFC service is disabled. There is no extra payload in the log event. + */ + @FlaggedApi(FLAG_NFC_STATE_CHANGE_SECURITY_LOG_EVENT_ENABLED) + public static final int TAG_NFC_DISABLED = SecurityLogTags.SECURITY_NFC_DISABLED; /** * Event severity level indicating that the event corresponds to normal workflow. */ diff --git a/core/java/android/app/admin/SecurityLogTags.logtags b/core/java/android/app/admin/SecurityLogTags.logtags index 7b3aa7b589b7..8f22c761d535 100644 --- a/core/java/android/app/admin/SecurityLogTags.logtags +++ b/core/java/android/app/admin/SecurityLogTags.logtags @@ -48,4 +48,6 @@ option java_package android.app.admin 210041 security_package_installed (package_name|3),(version_code|1),(user_id|1) 210042 security_package_updated (package_name|3),(version_code|1),(user_id|1) 210043 security_package_uninstalled (package_name|3),(version_code|1),(user_id|1) -210044 security_backup_service_toggled (package|3),(admin_user|1),(enabled|1)
\ No newline at end of file +210044 security_backup_service_toggled (package|3),(admin_user|1),(enabled|1) +210045 security_nfc_enabled +210046 security_nfc_disabled
\ No newline at end of file diff --git a/core/java/android/app/appfunctions/AppFunctionManagerHelper.java b/core/java/android/app/appfunctions/AppFunctionManagerHelper.java index fe2db49684fd..64dece99c5d1 100644 --- a/core/java/android/app/appfunctions/AppFunctionManagerHelper.java +++ b/core/java/android/app/appfunctions/AppFunctionManagerHelper.java @@ -16,6 +16,8 @@ package android.app.appfunctions; +import static android.app.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_DEFAULT; +import static android.app.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_ENABLED; import static android.app.appfunctions.AppFunctionRuntimeMetadata.PROPERTY_APP_FUNCTION_STATIC_METADATA_QUALIFIED_ID; import static android.app.appfunctions.AppFunctionRuntimeMetadata.PROPERTY_ENABLED; import static android.app.appfunctions.AppFunctionStaticMetadataHelper.APP_FUNCTION_INDEXER_PACKAGE; @@ -166,15 +168,18 @@ public class AppFunctionManagerHelper { if (runtimeMetadataResults.isEmpty()) { throw new IllegalArgumentException("App function not found."); } - boolean[] enabled = + long enabled = runtimeMetadataResults .getFirst() .getGenericDocument() - .getPropertyBooleanArray(PROPERTY_ENABLED); - if (enabled != null && enabled.length != 0) { - return enabled[0]; + .getPropertyLong(PROPERTY_ENABLED); + // If enabled is not equal to APP_FUNCTION_STATE_DEFAULT, it means it IS overridden and + // we should return the overridden value. + if (enabled != APP_FUNCTION_STATE_DEFAULT) { + return enabled == APP_FUNCTION_STATE_ENABLED; } - // Runtime metadata not found. Using the default value in the static metadata. + // Runtime metadata not found or enabled is equal to APP_FUNCTION_STATE_DEFAULT. + // Using the default value in the static metadata. return joinedStaticRuntimeResults .getFirst() .getGenericDocument() diff --git a/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java b/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java index 8b7f326ee816..08ecced234a9 100644 --- a/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java +++ b/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java @@ -16,11 +16,15 @@ package android.app.appfunctions; +import static android.app.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_DEFAULT; +import static android.app.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_DISABLED; +import static android.app.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_ENABLED; import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.appfunctions.AppFunctionManager.EnabledState; import android.app.appsearch.AppSearchSchema; import android.app.appsearch.GenericDocument; @@ -162,15 +166,13 @@ public class AppFunctionRuntimeMetadata extends GenericDocument { * Returns if the function is set to be enabled or not. If not set, the {@link * AppFunctionStaticMetadataHelper#STATIC_PROPERTY_ENABLED_BY_DEFAULT} value would be used. */ - @Nullable - public Boolean getEnabled() { - // We can't use getPropertyBoolean here. getPropertyBoolean returns false instead of null - // if the value is missing. - boolean[] enabled = getPropertyBooleanArray(PROPERTY_ENABLED); - if (enabled == null || enabled.length == 0) { - return null; - } - return enabled[0]; + @EnabledState + public int getEnabled() { + // getPropertyLong returns the first long associated with the given path or default value 0 + // if there is no such value or the value is of a different type. + // APP_FUNCTION_STATE_DEFAULT also equals 0 which means the returned value will be 0 when an + // app as either never changed the enabled bit at runtime or has reset it to the default. + return (int) getPropertyLong(PROPERTY_ENABLED); } /** Returns the qualified id linking to the static metadata of the app function. */ @@ -217,12 +219,14 @@ public class AppFunctionRuntimeMetadata extends GenericDocument { * TODO(369683073) Replace the tristate Boolean with IntDef EnabledState. */ @NonNull - public Builder setEnabled(@Nullable Boolean enabled) { - if (enabled == null) { - setPropertyBoolean(PROPERTY_ENABLED); - } else { - setPropertyBoolean(PROPERTY_ENABLED, enabled); + public Builder setEnabled(@EnabledState int enabledState) { + if (enabledState != APP_FUNCTION_STATE_DEFAULT + && enabledState != APP_FUNCTION_STATE_ENABLED + && enabledState != APP_FUNCTION_STATE_DISABLED) { + throw new IllegalArgumentException( + "Value of EnabledState is unsupported."); } + setPropertyLong(PROPERTY_ENABLED, enabledState); return this; } diff --git a/core/java/android/app/appfunctions/AppFunctionService.java b/core/java/android/app/appfunctions/AppFunctionService.java index 8e417737515e..7a68a656564b 100644 --- a/core/java/android/app/appfunctions/AppFunctionService.java +++ b/core/java/android/app/appfunctions/AppFunctionService.java @@ -35,6 +35,7 @@ import android.os.ICancellationSignal; import android.os.CancellationSignal; import android.os.RemoteCallback; import android.os.RemoteException; +import android.util.Log; import java.util.function.Consumer; @@ -166,9 +167,13 @@ public abstract class AppFunctionService extends Service { */ @MainThread @Deprecated - public abstract void onExecuteFunction( + public void onExecuteFunction( @NonNull ExecuteAppFunctionRequest request, - @NonNull Consumer<ExecuteAppFunctionResponse> callback); + @NonNull Consumer<ExecuteAppFunctionResponse> callback) { + Log.w( + "AppFunctionService", + "Calling deprecated default implementation of onExecuteFunction"); + } /** * Called by the system to execute a specific app function. diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java index 2851e92bd57f..a879b1ba6b5c 100644 --- a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java +++ b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java @@ -96,17 +96,14 @@ public final class ExecuteAppFunctionResponse implements Parcelable { */ public static final int RESULT_INVALID_ARGUMENT = 4; - /** The operation was timed out. */ - public static final int RESULT_TIMED_OUT = 5; - /** The caller tried to execute a disabled app function. */ - public static final int RESULT_DISABLED = 6; + public static final int RESULT_DISABLED = 5; /** * The operation was cancelled. Use this error code to report that a cancellation is done after * receiving a cancellation signal. */ - public static final int RESULT_CANCELLED = 7; + public static final int RESULT_CANCELLED = 6; /** The result code of the app function execution. */ @ResultCode private final int mResultCode; @@ -282,7 +279,6 @@ public final class ExecuteAppFunctionResponse implements Parcelable { RESULT_APP_UNKNOWN_ERROR, RESULT_INTERNAL_ERROR, RESULT_INVALID_ARGUMENT, - RESULT_TIMED_OUT, RESULT_DISABLED, RESULT_CANCELLED }) diff --git a/core/java/android/app/appfunctions/OWNERS b/core/java/android/app/appfunctions/OWNERS index c6827cc93222..6a69e15d00dd 100644 --- a/core/java/android/app/appfunctions/OWNERS +++ b/core/java/android/app/appfunctions/OWNERS @@ -4,3 +4,4 @@ toki@google.com tonymak@google.com mingweiliao@google.com anothermark@google.com +utkarshnigam@google.com diff --git a/core/java/android/app/appfunctions/TEST_MAPPING b/core/java/android/app/appfunctions/TEST_MAPPING index 91e82ec0e95b..27517c8a787b 100644 --- a/core/java/android/app/appfunctions/TEST_MAPPING +++ b/core/java/android/app/appfunctions/TEST_MAPPING @@ -1,10 +1,7 @@ { - "postsubmit": [ + "imports": [ { - "name": "FrameworksAppFunctionsTests" - }, - { - "name": "CtsAppFunctionTestCases" + "path": "frameworks/base/services/appfunctions/TEST_MAPPING" } ] }
\ No newline at end of file diff --git a/core/java/android/app/ui_mode_manager.aconfig b/core/java/android/app/ui_mode_manager.aconfig index 9f44a4d5ee01..05b46e02f9ad 100644 --- a/core/java/android/app/ui_mode_manager.aconfig +++ b/core/java/android/app/ui_mode_manager.aconfig @@ -9,4 +9,15 @@ flag { metadata { purpose: PURPOSE_BUGFIX } +} + +flag { + namespace: "systemui" + name: "enable_current_mode_type_binder_cache" + description: "Enables the use of binder caching for current running mode type." + bug: "362572732" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } }
\ No newline at end of file diff --git a/core/java/android/companion/virtual/IVirtualDevice.aidl b/core/java/android/companion/virtual/IVirtualDevice.aidl index 8916ce27cf68..40debe809fb7 100644 --- a/core/java/android/companion/virtual/IVirtualDevice.aidl +++ b/core/java/android/companion/virtual/IVirtualDevice.aidl @@ -31,6 +31,8 @@ import android.content.ComponentName; import android.content.IntentFilter; import android.graphics.Point; import android.graphics.PointF; +import android.hardware.display.IVirtualDisplayCallback; +import android.hardware.display.VirtualDisplayConfig; import android.hardware.input.VirtualDpadConfig; import android.hardware.input.VirtualKeyboardConfig; import android.hardware.input.VirtualKeyEvent; @@ -84,11 +86,28 @@ interface IVirtualDevice { int getDevicePolicy(int policyType); /** - * Returns whether the device has a valid microphone. - */ + * Returns whether the device has a valid microphone. + */ boolean hasCustomAudioInputSupport(); /** + * Returns whether this device is allowed to create mirror displays. + */ + boolean canCreateMirrorDisplays(); + + /* + * Turns off all trusted non-mirror displays of the virtual device. + */ + @EnforcePermission("CREATE_VIRTUAL_DEVICE") + void goToSleep(); + + /** + * Turns on all trusted non-mirror displays of the virtual device. + */ + @EnforcePermission("CREATE_VIRTUAL_DEVICE") + void wakeUp(); + + /** * Closes the virtual device and frees all associated resources. */ @EnforcePermission("CREATE_VIRTUAL_DEVICE") @@ -132,6 +151,13 @@ interface IVirtualDevice { void onAudioSessionEnded(); /** + * Creates a virtual display and registers it with the display framework. + */ + @EnforcePermission("CREATE_VIRTUAL_DEVICE") + int createVirtualDisplay(in VirtualDisplayConfig virtualDisplayConfig, + in IVirtualDisplayCallback callback); + + /** * Creates a new dpad and registers it with the input framework with the given token. */ @EnforcePermission("CREATE_VIRTUAL_DEVICE") @@ -184,6 +210,7 @@ interface IVirtualDevice { * Returns the ID of the device corresponding to the given token, as registered with the input * framework. */ + @EnforcePermission("CREATE_VIRTUAL_DEVICE") int getInputDeviceId(IBinder token); /** @@ -255,6 +282,7 @@ interface IVirtualDevice { /** * Launches a pending intent on the given display that is owned by this virtual device. */ + @EnforcePermission("CREATE_VIRTUAL_DEVICE") void launchPendingIntent(int displayId, in PendingIntent pendingIntent, in ResultReceiver resultReceiver); @@ -262,6 +290,7 @@ interface IVirtualDevice { * Returns the current cursor position of the mouse corresponding to the given token, in x and y * coordinates. */ + @EnforcePermission("CREATE_VIRTUAL_DEVICE") PointF getCursorPosition(IBinder token); /** Sets whether to show or hide the cursor while this virtual device is active. */ diff --git a/core/java/android/companion/virtual/IVirtualDeviceManager.aidl b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl index 83e18ec05599..c98238c1d7ba 100644 --- a/core/java/android/companion/virtual/IVirtualDeviceManager.aidl +++ b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl @@ -23,8 +23,6 @@ import android.companion.virtual.IVirtualDeviceSoundEffectListener; import android.companion.virtual.VirtualDevice; import android.companion.virtual.VirtualDeviceParams; import android.content.AttributionSource; -import android.hardware.display.IVirtualDisplayCallback; -import android.hardware.display.VirtualDisplayConfig; /** * Interface for communication between VirtualDeviceManager and VirtualDeviceManagerService. @@ -96,18 +94,6 @@ interface IVirtualDeviceManager { int getDevicePolicy(int deviceId, int policyType); /** - * Creates a virtual display owned by a particular virtual device. - * - * @param virtualDisplayConfig The configuration used in creating the display - * @param callback A callback that receives display lifecycle events - * @param virtualDevice The device that will own this display - * @param packageName The package name of the calling app - */ - int createVirtualDisplay(in VirtualDisplayConfig virtualDisplayConfig, - in IVirtualDisplayCallback callback, in IVirtualDevice virtualDevice, - String packageName); - - /** * Returns device-specific session id for playback, or AUDIO_SESSION_ID_GENERATE * if there's none. */ diff --git a/core/java/android/companion/virtual/VirtualDeviceInternal.java b/core/java/android/companion/virtual/VirtualDeviceInternal.java index de20a68e52cb..6708ccee1645 100644 --- a/core/java/android/companion/virtual/VirtualDeviceInternal.java +++ b/core/java/android/companion/virtual/VirtualDeviceInternal.java @@ -242,6 +242,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) @NonNull List<VirtualSensor> getVirtualSensorList() { try { @@ -251,6 +252,25 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) + void goToSleep() { + try { + mVirtualDevice.goToSleep(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) + void wakeUp() { + try { + mVirtualDevice.wakeUp(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) void launchPendingIntent( int displayId, @NonNull PendingIntent pendingIntent, @@ -272,6 +292,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) @Nullable VirtualDisplay createVirtualDisplay( @NonNull VirtualDisplayConfig config, @@ -281,16 +302,15 @@ public class VirtualDeviceInternal { new DisplayManagerGlobal.VirtualDisplayCallback(callback, executor); final int displayId; try { - displayId = mService.createVirtualDisplay(config, callbackWrapper, mVirtualDevice, - mContext.getPackageName()); + displayId = mVirtualDevice.createVirtualDisplay(config, callbackWrapper); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance(); - return displayManager.createVirtualDisplayWrapper(config, callbackWrapper, - displayId); + return displayManager.createVirtualDisplayWrapper(config, callbackWrapper, displayId); } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) void close() { try { // This also takes care of unregistering all virtual sensors. @@ -304,6 +324,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) void setDevicePolicy(@VirtualDeviceParams.DynamicPolicyType int policyType, @VirtualDeviceParams.DevicePolicy int devicePolicy) { switch (policyType) { @@ -323,6 +344,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) void addActivityPolicyExemption(@NonNull ActivityPolicyExemption exemption) { try { mVirtualDevice.addActivityPolicyExemption(exemption); @@ -331,6 +353,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) void removeActivityPolicyExemption(@NonNull ActivityPolicyExemption exemption) { try { mVirtualDevice.removeActivityPolicyExemption(exemption); @@ -339,6 +362,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) void setDevicePolicyForDisplay(int displayId, @VirtualDeviceParams.DynamicDisplayPolicyType int policyType, @VirtualDeviceParams.DevicePolicy int devicePolicy) { @@ -358,6 +382,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) @NonNull VirtualDpad createVirtualDpad(@NonNull VirtualDpadConfig config) { try { @@ -370,6 +395,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) @NonNull VirtualKeyboard createVirtualKeyboard(@NonNull VirtualKeyboardConfig config) { try { @@ -382,6 +408,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) @NonNull VirtualMouse createVirtualMouse(@NonNull VirtualMouseConfig config) { try { @@ -394,6 +421,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) @NonNull VirtualTouchscreen createVirtualTouchscreen( @NonNull VirtualTouchscreenConfig config) { @@ -433,6 +461,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) @NonNull VirtualNavigationTouchpad createVirtualNavigationTouchpad( @NonNull VirtualNavigationTouchpadConfig config) { @@ -447,6 +476,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) @NonNull VirtualAudioDevice createVirtualAudioDevice( @NonNull VirtualDisplay display, @@ -483,6 +513,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) void setShowPointerIcon(boolean showPointerIcon) { try { mVirtualDevice.setShowPointerIcon(showPointerIcon); @@ -491,6 +522,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) void setDisplayImePolicy(int displayId, @WindowManager.DisplayImePolicy int policy) { try { mVirtualDevice.setDisplayImePolicy(displayId, policy); @@ -532,6 +564,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) void registerIntentInterceptor( @NonNull IntentFilter interceptorFilter, @CallbackExecutor @NonNull Executor executor, @@ -551,6 +584,7 @@ public class VirtualDeviceInternal { } } + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) void unregisterIntentInterceptor( @NonNull VirtualDeviceManager.IntentInterceptorCallback interceptorCallback) { Objects.requireNonNull(interceptorCallback); diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java index 473ab27ee560..96700a9a3c18 100644 --- a/core/java/android/companion/virtual/VirtualDeviceManager.java +++ b/core/java/android/companion/virtual/VirtualDeviceManager.java @@ -614,12 +614,52 @@ public final class VirtualDeviceManager { * * @return A list of all sensors for this device, or an empty list if no sensors exist. */ + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) @NonNull public List<VirtualSensor> getVirtualSensorList() { return mVirtualDeviceInternal.getVirtualSensorList(); } /** + * Forces all trusted non-mirror displays of the virtual device to turn off. + * + * <p>After this action, if all displays across all devices, including the default one, are + * off, then the physical device will be put to sleep. If the displays of this virtual + * device are already off, then nothing will happen.</p> + * + * <p>Overrides all the wake locks that are held. This is equivalent to pressing a "virtual + * power key" to turn off the screen.</p> + * + * @see #wakeUp() + * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED + * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY + */ + @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) + public void goToSleep() { + mVirtualDeviceInternal.goToSleep(); + } + + /** + * Forces all trusted non-mirror displays of the virtual device to turn on. + * + * <p>If the displays of this virtual device are turned off, then they will be turned on. + * Additionally, if the device is asleep it will be awoken. If the displays of this virtual + * device are already on, then nothing will happen.</p> + * + * <p>This is equivalent to pressing a "virtual power key" to turn on the screen.</p> + * + * @see #goToSleep() + * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED + * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY + */ + @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) + public void wakeUp() { + mVirtualDeviceInternal.wakeUp(); + } + + /** * Launches a given pending intent on the give display ID. * * @param displayId The display to launch the pending intent on. This display must be @@ -637,6 +677,7 @@ public final class VirtualDeviceManager { * on the virtual display, or one of the {@code LAUNCH_FAILED} status explaining why it * failed. */ + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void launchPendingIntent( int displayId, @NonNull PendingIntent pendingIntent, @@ -677,6 +718,7 @@ public final class VirtualDeviceManager { * VirtualDisplay.Callback)} */ @Deprecated + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) @Nullable public VirtualDisplay createVirtualDisplay( @IntRange(from = 1) int width, @@ -714,6 +756,7 @@ public final class VirtualDeviceManager { * * @see DisplayManager#createVirtualDisplay */ + @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) @Nullable public VirtualDisplay createVirtualDisplay( @NonNull VirtualDisplayConfig config, diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig index e9fa3e15fe05..9eb6d5624f75 100644 --- a/core/java/android/companion/virtual/flags/flags.aconfig +++ b/core/java/android/companion/virtual/flags/flags.aconfig @@ -132,8 +132,16 @@ flag { } flag { - namespace: "virtual_devices" - name: "camera_timestamp_from_surface" - description: "Pass the surface timestamp to the capture result" - bug: "351341245" + namespace: "virtual_devices" + name: "camera_timestamp_from_surface" + description: "Pass the surface timestamp to the capture result" + bug: "351341245" +} + +flag { + namespace: "virtual_devices" + name: "enable_limited_vdm_role" + description: "New VDM role without trusted displays or input" + bug: "370657575" + is_exported: true } diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java index b42133939f28..ff0bb25bbccc 100644 --- a/core/java/android/content/ClipData.java +++ b/core/java/android/content/ClipData.java @@ -1149,7 +1149,7 @@ public class ClipData implements Parcelable { for (int i = 0; i < size; i++) { final Item item = mItems.get(i); if (item.mIntent != null) { - item.mIntent.prepareToLeaveProcess(leavingPackage); + item.mIntent.prepareToLeaveProcess(leavingPackage, false); } if (item.mUri != null && leavingPackage) { if (StrictMode.vmFileUriExposureEnabled()) { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 9a93ec4d3b40..0bb0027fb0c3 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -12221,6 +12221,8 @@ public class Intent implements Parcelable, Cloneable { /** * Collects keys in the extra bundle whose value are intents. + * With these keys collected on the client side, the system server would only unparcel values + * of these keys and create IntentCreatorToken for them. * @hide */ public void collectExtraIntentKeys() { @@ -12583,22 +12585,29 @@ public class Intent implements Parcelable, Cloneable { */ @android.ravenwood.annotation.RavenwoodThrow public void prepareToLeaveProcess(boolean leavingPackage) { + prepareToLeaveProcess(leavingPackage, true); + } + + /** + * @hide + */ + void prepareToLeaveProcess(boolean leavingPackage, boolean isTopLevel) { setAllowFds(false); if (mSelector != null) { - mSelector.prepareToLeaveProcess(leavingPackage); + mSelector.prepareToLeaveProcess(leavingPackage, false); } if (mClipData != null) { mClipData.prepareToLeaveProcess(leavingPackage, getFlags()); } if (mOriginalIntent != null) { - mOriginalIntent.prepareToLeaveProcess(leavingPackage); + mOriginalIntent.prepareToLeaveProcess(leavingPackage, false); } if (mExtras != null && !mExtras.isParcelled()) { final Object intent = mExtras.get(Intent.EXTRA_INTENT); if (intent instanceof Intent) { - ((Intent) intent).prepareToLeaveProcess(leavingPackage); + ((Intent) intent).prepareToLeaveProcess(leavingPackage, false); } } @@ -12672,6 +12681,10 @@ public class Intent implements Parcelable, Cloneable { StrictMode.onUnsafeIntentLaunch(this); } } + + if (isTopLevel) { + collectExtraIntentKeys(); + } } /** diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java index ca6d86ae2dd8..f406927b62a5 100644 --- a/core/java/android/content/IntentSender.java +++ b/core/java/android/content/IntentSender.java @@ -288,6 +288,9 @@ public class IntentSender implements Parcelable { @Nullable Executor executor, @Nullable OnFinished onFinished) throws SendIntentException { try { + if (intent != null) { + intent.collectExtraIntentKeys(); + } String resolvedType = intent != null ? intent.resolveTypeIfNeeded(context.getContentResolver()) : null; diff --git a/core/java/android/content/om/FabricatedOverlay.java b/core/java/android/content/om/FabricatedOverlay.java index 40ffb0ff5c80..64e9c339f2d6 100644 --- a/core/java/android/content/om/FabricatedOverlay.java +++ b/core/java/android/content/om/FabricatedOverlay.java @@ -476,6 +476,20 @@ public class FabricatedOverlay { return entry; } + @NonNull + private static FabricatedOverlayInternalEntry generateFabricatedOverlayInternalEntry( + @NonNull String resourceName, float dimensionValue, + @TypedValue.ComplexDimensionUnit int dimensionUnit, @Nullable String configuration) { + final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry(); + entry.resourceName = resourceName; + entry.dataType = TypedValue.TYPE_DIMENSION; + Preconditions.checkArgumentInRange(dimensionUnit, + TypedValue.COMPLEX_UNIT_PX, TypedValue.COMPLEX_UNIT_MM, "dimensionUnit"); + entry.data = TypedValue.createComplexDimension(dimensionValue, dimensionUnit); + entry.configuration = configuration; + return entry; + } + /** * Sets the resource value in the fabricated overlay for the integer-like types with the * configuration. @@ -586,4 +600,25 @@ public class FabricatedOverlay { mOverlay.entries.add( generateFabricatedOverlayInternalEntry(resourceName, value, configuration)); } + + /** + * Sets the resource value in the fabricated overlay for the dimension type with the + * configuration. + * + * @param resourceName name of the target resource to overlay (in the form + * [package]:type/entry) + * @param dimensionValue the float representing the dimension value + * @param dimensionUnit the integer representing the dimension unit + * @param configuration The string representation of the config this overlay is enabled for + */ + @FlaggedApi(android.content.res.Flags.FLAG_DIMENSION_FRRO) + public void setResourceValue( + @NonNull String resourceName, + float dimensionValue, + @TypedValue.ComplexDimensionUnit int dimensionUnit, + @Nullable String configuration) { + ensureValidResourceName(resourceName); + mOverlay.entries.add(generateFabricatedOverlayInternalEntry(resourceName, dimensionValue, + dimensionUnit, configuration)); + } } diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig index fd1a89692da2..fa26837a0429 100644 --- a/core/java/android/content/pm/multiuser.aconfig +++ b/core/java/android/content/pm/multiuser.aconfig @@ -68,6 +68,13 @@ flag { } flag { + name: "multiuser_widget" + namespace: "multiuser" + description: "Implement the Multiuser Widget" + bug: "365748524" +} + +flag { name: "enable_biometrics_to_unlock_private_space" is_exported: true namespace: "profile_experiences" @@ -201,6 +208,36 @@ flag { } flag { + name: "cache_profile_ids" + namespace: "multiuser" + description: "Cache getProfileIds to avoid unnecessary binder calls" + bug: "350421409" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "cache_profile_type" + namespace: "multiuser" + description: "Cache getProfileType to avoid unnecessary binder calls" + bug: "350417403" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "cache_profiles" + namespace: "multiuser" + description: "Cache getProfiles to avoid unnecessary binder calls" + bug: "350419395" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +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" @@ -449,7 +486,6 @@ flag { } } - flag { name: "caching_development_improvements" namespace: "multiuser" @@ -457,3 +493,13 @@ flag { bug: "364947162" is_fixed_read_only: true } + +flag { + name: "show_custom_unlock_title_inside_private_profile" + namespace: "profile_experiences" + description: "When private space is unlocked show dynamic title in unlock factor screens based on lock factor set for the profile" + bug: "323835257" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/android/content/res/flags.aconfig b/core/java/android/content/res/flags.aconfig index a5f8199c9a07..0af2f2576137 100644 --- a/core/java/android/content/res/flags.aconfig +++ b/core/java/android/content/res/flags.aconfig @@ -66,3 +66,11 @@ flag { # This flag is read at boot time. is_fixed_read_only: true } + +flag { + name: "dimension_frro" + is_exported: true + namespace: "resource_manager" + description: "Feature flag for passing a dimension to create an frro" + bug: "369672322" +} diff --git a/core/java/android/hardware/DisplayLuts.java b/core/java/android/hardware/DisplayLuts.java new file mode 100644 index 000000000000..b162ad6e2d15 --- /dev/null +++ b/core/java/android/hardware/DisplayLuts.java @@ -0,0 +1,131 @@ +/* + * 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.hardware; + +import android.annotation.NonNull; +import android.util.IntArray; + +import java.util.ArrayList; +import java.util.List; + +/** + * @hide + */ +public final class DisplayLuts { + private IntArray mOffsets; + private int mTotalLength; + + private List<float[]> mLutBuffers; + private IntArray mLutDimensions; + private IntArray mLutSizes; + private IntArray mLutSamplingKeys; + private static final int LUT_LENGTH_LIMIT = 100000; + + public DisplayLuts() { + mOffsets = new IntArray(); + mTotalLength = 0; + + mLutBuffers = new ArrayList<>(); + mLutDimensions = new IntArray(); + mLutSizes = new IntArray(); + mLutSamplingKeys = new IntArray(); + } + + /** + * Add the lut to be applied. + * + * @param buffer + * @param dimension either 1D or 3D + * @param size + * @param samplingKey + */ + public void addLut(@NonNull float[] buffer, @LutProperties.Dimension int dimension, + int size, @LutProperties.SamplingKey int samplingKey) { + + int lutLength = 0; + if (dimension == LutProperties.ONE_DIMENSION) { + lutLength = size; + } else if (dimension == LutProperties.THREE_DIMENSION) { + lutLength = size * size * size; + } else { + clear(); + throw new IllegalArgumentException("The dimension is either 1D or 3D!"); + } + + if (lutLength >= LUT_LENGTH_LIMIT) { + clear(); + throw new IllegalArgumentException("The lut length is too big to handle!"); + } + + mOffsets.add(mTotalLength); + mTotalLength += lutLength; + + mLutBuffers.add(buffer); + mLutDimensions.add(dimension); + mLutSizes.add(size); + mLutSamplingKeys.add(samplingKey); + } + + private void clear() { + mTotalLength = 0; + mOffsets.clear(); + mLutBuffers.clear(); + mLutDimensions.clear(); + mLutSamplingKeys.clear(); + } + + /** + * @return the array of Lut buffers + */ + public float[] getLutBuffers() { + float[] buffer = new float[mTotalLength]; + + for (int i = 0; i < mLutBuffers.size(); i++) { + float[] lutBuffer = mLutBuffers.get(i); + System.arraycopy(lutBuffer, 0, buffer, mOffsets.get(i), lutBuffer.length); + } + return buffer; + } + + /** + * @return the starting point of each lut memory region of the lut buffer + */ + public int[] getOffsets() { + return mOffsets.toArray(); + } + + /** + * @return the array of Lut size + */ + public int[] getLutSizes() { + return mLutSizes.toArray(); + } + + /** + * @return the array of Lut dimension + */ + public int[] getLutDimensions() { + return mLutDimensions.toArray(); + } + + /** + * @return the array of sampling key + */ + public int[] getLutSamplingKeys() { + return mLutSamplingKeys.toArray(); + } +} diff --git a/core/java/android/hardware/LutProperties.java b/core/java/android/hardware/LutProperties.java new file mode 100644 index 000000000000..57f8a4ece304 --- /dev/null +++ b/core/java/android/hardware/LutProperties.java @@ -0,0 +1,94 @@ +/* + * 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.hardware; + +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Lut properties class. + * + * A Lut (Look-Up Table) is a pre-calculated table for color transformation. + * + * @hide + */ +public final class LutProperties { + private final @Dimension int mDimension; + private final long mSize; + private final @SamplingKey int[] mSamplingKeys; + + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"SAMPLING_KEY_"}, value = { + SAMPLING_KEY_RGB, + SAMPLING_KEY_MAX_RGB + }) + public @interface SamplingKey { + } + + /** use r,g,b channel as the gain value of a Lut */ + public static final int SAMPLING_KEY_RGB = 0; + + /** use max of r,g,b channel as the gain value of a Lut */ + public static final int SAMPLING_KEY_MAX_RGB = 1; + + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + ONE_DIMENSION, + THREE_DIMENSION + }) + public @interface Dimension { + } + + /** The Lut is one dimensional */ + public static final int ONE_DIMENSION = 1; + + /** The Lut is three dimensional */ + public static final int THREE_DIMENSION = 3; + + public @Dimension int getDimension() { + return mDimension; + } + + /** + * @return the size of the Lut. + */ + public long getSize() { + return mSize; + } + + /** + * @return the list of sampling keys + */ + public @SamplingKey int[] getSamplingKeys() { + if (mSamplingKeys.length == 0) { + throw new IllegalStateException("no sampling key!"); + } + return mSamplingKeys; + } + + /* use in the native code */ + private LutProperties(@Dimension int dimension, long size, @SamplingKey int[] samplingKeys) { + if (dimension != ONE_DIMENSION || dimension != THREE_DIMENSION) { + throw new IllegalArgumentException("The dimension is either 1 or 3!"); + } + mDimension = dimension; + mSize = size; + mSamplingKeys = samplingKeys; + } +} diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS index 43d3f5466ccf..f11625ed9d61 100644 --- a/core/java/android/hardware/OWNERS +++ b/core/java/android/hardware/OWNERS @@ -19,3 +19,6 @@ per-file DataSpace* = file:/graphics/java/android/graphics/OWNERS # OverlayProperties per-file OverlayProperties* = file:/graphics/java/android/graphics/OWNERS + +# Lut related files +per-file *Lut* = file:/graphics/java/android/graphics/OWNERS
\ No newline at end of file diff --git a/core/java/android/hardware/OverlayProperties.java b/core/java/android/hardware/OverlayProperties.java index 7b452a8e0857..24cfc1b53e00 100644 --- a/core/java/android/hardware/OverlayProperties.java +++ b/core/java/android/hardware/OverlayProperties.java @@ -50,6 +50,8 @@ public final class OverlayProperties implements Parcelable { // Invoked on destruction private Runnable mCloser; + private LutProperties[] mLutProperties; + private OverlayProperties(long nativeObject) { if (nativeObject != 0) { mCloser = sRegistry.registerNativeAllocation(this, nativeObject); @@ -70,6 +72,20 @@ public final class OverlayProperties implements Parcelable { } /** + * Gets the lut properties of the display. + * @hide + */ + public LutProperties[] getLutProperties() { + if (mNativeObject == 0) { + return null; + } + if (mLutProperties == null) { + mLutProperties = nGetLutProperties(mNativeObject); + } + return mLutProperties; + } + + /** * Indicates that hardware composition of a buffer encoded with the provided {@link DataSpace} * and {@link HardwareBuffer.Format} is supported on the device. * @@ -140,4 +156,5 @@ public final class OverlayProperties implements Parcelable { long nativeObject, int dataspace, int format); private static native void nWriteOverlayPropertiesToParcel(long nativeObject, Parcel dest); private static native long nReadOverlayPropertiesFromParcel(Parcel in); -} + private static native LutProperties[] nGetLutProperties(long nativeObject); +}
\ No newline at end of file diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java index b11961cc2b21..e3fdd267623e 100644 --- a/core/java/android/hardware/biometrics/BiometricPrompt.java +++ b/core/java/android/hardware/biometrics/BiometricPrompt.java @@ -139,6 +139,13 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan public static final int DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS = 8; /** + * Dialog dismissal due to the system being unable to retrieve a WindowManager instance required + * to show the dialog. + * @hide + */ + public static final int DISMISSED_REASON_ERROR_NO_WM = 9; + + /** * @hide */ @IntDef({DISMISSED_REASON_BIOMETRIC_CONFIRMED, @@ -148,7 +155,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan DISMISSED_REASON_ERROR, DISMISSED_REASON_SERVER_REQUESTED, DISMISSED_REASON_CREDENTIAL_CONFIRMED, - DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS}) + DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS, + DISMISSED_REASON_ERROR_NO_WM}) @Retention(RetentionPolicy.SOURCE) public @interface DismissedReason {} diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 9e3a9b389b05..b7856303fc05 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -19,6 +19,7 @@ package android.hardware.camera2; import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT; import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CAMERA; import static android.content.Context.DEVICE_ID_DEFAULT; +import static android.content.Context.DEVICE_ID_INVALID; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; @@ -36,6 +37,7 @@ import android.companion.virtual.VirtualDeviceManager; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.compat.annotation.Overridable; +import android.content.AttributionSource; import android.content.AttributionSourceState; import android.content.Context; import android.content.pm.PackageManager; @@ -676,8 +678,8 @@ public final class CameraManager { } try { for (String physicalCameraId : physicalCameraIds) { - AttributionSourceState clientAttribution = getClientAttribution(); - clientAttribution.deviceId = DEVICE_ID_DEFAULT; + AttributionSourceState clientAttribution = getClientAttribution(DEVICE_ID_DEFAULT, + /* useContextAttributionSource= */ false); CameraMetadataNative physicalCameraInfo = cameraService.getCameraCharacteristics( physicalCameraId, @@ -974,27 +976,58 @@ public final class CameraManager { } /** - * Constructs an AttributionSourceState with only the uid, pid, and deviceId fields set + * Retrieves the AttributionSourceState to pass to the CameraService. * - * <p>This method is a temporary stopgap in the transition to using AttributionSource. Currently - * AttributionSourceState is only used as a vehicle for passing deviceId, uid, and pid - * arguments.</p> + * @param deviceIdOverride An override of the AttributionSource's deviceId, if not equal to + * DEVICE_ID_INVALID + * @param useContextAttributionSource Whether to return the full attribution source provided by + * the Context. + * + * @hide + */ + public AttributionSourceState getClientAttribution(int deviceIdOverride, + boolean useContextAttributionSource) { + AttributionSource contextAttributionSource = mContext.getAttributionSource(); + if (deviceIdOverride != DEVICE_ID_INVALID) { + contextAttributionSource = contextAttributionSource.withDeviceId(deviceIdOverride); + } + AttributionSourceState contextAttributionSourceState = + contextAttributionSource.asState(); + + if (Flags.useContextAttributionSource() && useContextAttributionSource) { + return contextAttributionSourceState; + } else { + AttributionSourceState clientAttribution = + new AttributionSourceState(); + clientAttribution.uid = USE_CALLING_UID; + clientAttribution.pid = USE_CALLING_PID; + clientAttribution.deviceId = contextAttributionSourceState.deviceId; + clientAttribution.packageName = mContext.getOpPackageName(); + clientAttribution.attributionTag = mContext.getAttributionTag(); + clientAttribution.next = new AttributionSourceState[0]; + return clientAttribution; + } + } + + /** + * Retrieves the AttributionSourceState to pass to the CameraService. + * + * @param useContextAttributionSource Whether to return the full attribution source provided by + * the Context. + * + * @hide + */ + public AttributionSourceState getClientAttribution(boolean useContextAttributionSource) { + return getClientAttribution(DEVICE_ID_INVALID, useContextAttributionSource); + } + + /** + * Retrieves the AttributionSourceState to pass to the CameraService. * * @hide */ public AttributionSourceState getClientAttribution() { - // TODO: Send the full contextAttribution over aidl, remove USE_CALLING_* - AttributionSourceState contextAttribution = - mContext.getAttributionSource().asState(); - AttributionSourceState clientAttribution = - new AttributionSourceState(); - clientAttribution.uid = USE_CALLING_UID; - clientAttribution.pid = USE_CALLING_PID; - clientAttribution.deviceId = contextAttribution.deviceId; - clientAttribution.packageName = mContext.getOpPackageName(); - clientAttribution.attributionTag = mContext.getAttributionTag(); - clientAttribution.next = new AttributionSourceState[0]; - return clientAttribution; + return getClientAttribution(DEVICE_ID_INVALID, /* useContextAttributionSource= */ false); } /** @@ -1049,7 +1082,7 @@ public final class CameraManager { } AttributionSourceState clientAttribution = - getClientAttribution(); + getClientAttribution(/* useContextAttributionSource= */ true); cameraUser = cameraService.connectDevice( callbacks, diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index b9eba9c1d541..ce8661e90978 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -1028,6 +1028,9 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession // Camera is already closed, so nothing left to do if (DEBUG) Log.v(TAG, mIdString + "Camera was already closed or busy, skipping unconfigure"); + } catch (SecurityException e) { + // UID state change revoked camera permission + Log.e(TAG, mIdString + "Exception while unconfiguring outputs: ", e); } } } diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index 7185719abdd5..6affd123bfde 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -792,7 +792,6 @@ public final class DisplayManagerGlobal { public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) { try { mDm.setVirtualDisplaySurface(token, surface); - setVirtualDisplayState(token, surface != null); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } @@ -815,14 +814,6 @@ public final class DisplayManagerGlobal { } } - void setVirtualDisplayState(IVirtualDisplayCallback token, boolean isOn) { - try { - mDm.setVirtualDisplayState(token, isOn); - } catch (RemoteException ex) { - throw ex.rethrowFromSystemServer(); - } - } - void setVirtualDisplayRotation(IVirtualDisplayCallback token, @Surface.Rotation int rotation) { try { mDm.setVirtualDisplayRotation(token, rotation); diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index e5980972d590..6c1aa90c831b 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -92,9 +92,10 @@ public abstract class DisplayManagerInternal { boolean waitForNegativeProximity); /** - * Returns {@code true} if the proximity sensor screen-off function is available. + * Returns {@code true} if the proximity sensor screen-off function is available for the given + * display. */ - public abstract boolean isProximitySensorAvailable(); + public abstract boolean isProximitySensorAvailable(int displayId); /** * Registers a display group listener which will be informed of the addition, removal, or change @@ -455,6 +456,11 @@ public abstract class DisplayManagerInternal { public abstract void onPresentation(int displayId, boolean isShown); /** + * Called upon the usage of stylus. + */ + public abstract void stylusGestureStarted(long eventTime); + + /** * Describes the requested power state of the display. * * This object is intended to describe the general characteristics of the diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index aa1539f69722..b612bca5671e 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -115,9 +115,6 @@ interface IDisplayManager { void releaseVirtualDisplay(in IVirtualDisplayCallback token); // No permissions required but must be same Uid as the creator. - void setVirtualDisplayState(in IVirtualDisplayCallback token, boolean isOn); - - // No permissions required but must be same Uid as the creator. void setVirtualDisplayRotation(in IVirtualDisplayCallback token, int rotation); // Get a stable metric for the device's display size. No permissions required. diff --git a/core/java/android/hardware/display/VirtualDisplay.java b/core/java/android/hardware/display/VirtualDisplay.java index 6cc938f5e6f8..32b640583734 100644 --- a/core/java/android/hardware/display/VirtualDisplay.java +++ b/core/java/android/hardware/display/VirtualDisplay.java @@ -112,18 +112,6 @@ public final class VirtualDisplay { } /** - * Sets the on/off state for a virtual display. - * - * @param isOn Whether the display should be on or off. - * @hide - */ - public void setDisplayState(boolean isOn) { - if (mToken != null) { - mGlobal.setVirtualDisplayState(mToken, isOn); - } - } - - /** * Sets the rotation of the virtual display. * * @param rotation the new rotation of the display. May be one of {@link Surface#ROTATION_0}, diff --git a/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig b/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig index 51024ba64bd9..6a39365567e5 100644 --- a/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig +++ b/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig @@ -43,3 +43,10 @@ flag { description: "Enable usb state update based on udc sysfs" bug: "339241080" } + +flag { + name: "enable_usb_data_signal_staking_internal" + namespace: "preload_safety" + description: "Enables signal API with staking for internal local service callers" + bug: "369382558" +}
\ No newline at end of file diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index b9b5295f89b6..c41e626444c9 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -3088,8 +3088,9 @@ public abstract class BatteryStats { public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn", - "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", "Etw", - "Esw", "Ewa", "Elw", "Eec", "Esc", "Eds" + "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", + "Etw", "Esw", "Ewa", "Elw", "Esc", + "Eds" }; @FunctionalInterface diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java index 80546cd6770f..3b5a99ed089a 100644 --- a/core/java/android/os/BinderProxy.java +++ b/core/java/android/os/BinderProxy.java @@ -493,6 +493,11 @@ public final class BinderProxy implements IBinder { public native boolean pingBinder(); /** + * Check to see if the process that the binder is in is still alive. + * + * Note, this only reflects the last known death state, if the object + * is linked to death or has made a transactions since the death occurs. + * * @return false if the hosting process is gone */ public native boolean isBinderAlive(); diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index a8267d1c9d8c..479aa98f80de 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SuppressAutoDoc; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.ActivityThread; @@ -401,33 +402,42 @@ public class Build { * device. This value never changes while a device is booted, but it may * increase when the hardware manufacturer provides an OTA update. * <p> - * Together with {@link SDK_MINOR_INT}, this constant defines the - * <pre>major.minor</pre> version of Android. <pre>SDK_INT</pre> is - * increased and <pre>SDK_MINOR_INT</pre> is set to 0 on new Android - * dessert releases. Between these, Android may also release so called - * minor releases where <pre>SDK_INT</pre> remains unchanged and - * <pre>SDK_MINOR_INT</pre> is increased. Minor releases can add new - * APIs, and have stricter guarantees around backwards compatibility - * (e.g. no changes gated by <pre>targetSdkVersion</pre>) compared to - * major releases. + * This constant records the major version of Android. Use {@link + * SDK_INT_FULL} if you need to consider the minor version of Android + * as well. * <p> * Possible values are defined in {@link Build.VERSION_CODES}. + * @see #SDK_INT_FULL */ public static final int SDK_INT = SystemProperties.getInt( "ro.build.version.sdk", 0); /** - * The minor SDK version of the software currently running on this hardware - * device. This value never changes while a device is booted, but it may - * increase when the hardware manufacturer provides an OTA update. + * The major and minor SDK version of the software currently running on + * this hardware device. This value never changes while a device is + * booted, but it may increase when the hardware manufacturer provides + * an OTA update. + * <p> + * <code>SDK_INT</code> is increased on new Android dessert releases, + * also called major releases. Between these, Android may also release + * minor releases where <code>SDK_INT</code> remains unchanged. Minor + * releases can add new APIs, and have stricter guarantees around + * backwards compatibility (e.g. no changes gated by + * <code>targetSdkVersion</code>) compared to major releases. * <p> - * Together with {@link SDK_INT}, this constant defines the - * <pre>major.minor</pre> version of Android. See {@link SDK_INT} for - * more information. + * <code>SDK_INT_FULL</code> is increased on every release. + * <p> + * Possible values are defined in {@link + * android.os.Build.VERSION_CODES_FULL}. */ @FlaggedApi(Flags.FLAG_MAJOR_MINOR_VERSIONING_SCHEME) - public static final int SDK_MINOR_INT = SystemProperties.getInt( - "ro.build.version.sdk_minor", 0); + public static final int SDK_INT_FULL; + + static { + SDK_INT_FULL = VERSION_CODES_FULL.SDK_INT_MULTIPLIER + * SystemProperties.getInt("ro.build.version.sdk", 0) + + SystemProperties.getInt("ro.build.version.sdk_minor", 0); + } /** * The SDK version of the software that <em>initially</em> shipped on @@ -1264,6 +1274,25 @@ public class Build { } /** + * Enumeration of the currently known SDK major and minor version codes. + * The numbers increase for every release, and are guaranteed to be ordered + * by the release date of each release. The actual values should be + * considered an implementation detail, and the current encoding scheme may + * change in the future. + * + * @see android.os.Build.VERSION#SDK_INT_FULL + */ + @FlaggedApi(Flags.FLAG_MAJOR_MINOR_VERSIONING_SCHEME) + @SuppressLint("AcronymName") + public static class VERSION_CODES_FULL { + private VERSION_CODES_FULL() {} + + // Use the last 5 digits for the minor version. This allows the + // minor version to be set to CUR_DEVELOPMENT. + private static final int SDK_INT_MULTIPLIER = 100000; + } + + /** * The vendor API for 2024 Q2 * * <p>For Android 14-QPR3 and later, the vendor API level is completely decoupled from the SDK diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index beb9a935a6ee..2d3dd1b9383b 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -598,6 +598,11 @@ public class GraphicsEnvironment { final String abi = chooseAbi(angleInfo); // Build a path that includes installed native libs and APK + // TODO (b/370113081): If the native libraries are not found in this path, + // the system libraries will be loaded instead. + // This can happen if the ANGLE APK is present, + // but accidentally packaged without native libraries. + // TBD if this should fail instead of falling back to the system version. final String paths = angleInfo.nativeLibraryDir + File.pathSeparator + angleInfo.sourceDir diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 5f62b8be45a3..e85e58039828 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -42,7 +42,9 @@ interface IPowerManager void updateWakeLockWorkSource(IBinder lock, in WorkSource ws, String historyTag); void updateWakeLockCallback(IBinder lock, IWakeLockCallback callback); + @UnsupportedAppUsage boolean isWakeLockLevelSupported(int level); + boolean isWakeLockLevelSupportedWithDisplayId(int level, int displayId); void userActivity(int displayId, long time, int event, int flags); void wakeUp(long time, int reason, String details, String opPackageName); diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index b9bae5b9f737..32db3bea7686 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -1344,6 +1344,9 @@ public final class PowerManager { * @see #ON_AFTER_RELEASE */ public WakeLock newWakeLock(int levelAndFlags, String tag) { + if (android.companion.virtualdevice.flags.Flags.displayPowerManagerApis()) { + return newWakeLock(levelAndFlags, tag, mContext.getDisplayId()); + } validateWakeLockParameters(levelAndFlags, tag); return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName(), Display.INVALID_DISPLAY); @@ -1734,6 +1737,10 @@ public final class PowerManager { */ public boolean isWakeLockLevelSupported(int level) { try { + if (android.companion.virtualdevice.flags.Flags.displayPowerManagerApis()) { + return mService.isWakeLockLevelSupportedWithDisplayId( + level, mContext.getDisplayId()); + } return mService.isWakeLockLevelSupported(level); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1797,6 +1804,9 @@ public final class PowerManager { * @see android.content.Intent#ACTION_SCREEN_OFF */ public boolean isInteractive() { + if (android.companion.virtualdevice.flags.Flags.displayPowerManagerApis()) { + return isInteractive(mContext.getDisplayId()); + } return mInteractiveCache.query(null); } diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java index 2cb86f753078..769cbdd9886d 100644 --- a/core/java/android/os/RemoteCallbackList.java +++ b/core/java/android/os/RemoteCallbackList.java @@ -92,9 +92,9 @@ public class RemoteCallbackList<E extends IInterface> { /** * Add a new callback to the list. This callback will remain in the list * until a corresponding call to {@link #unregister} or its hosting process - * goes away. If the callback was already registered (determined by + * goes away. If the callback was already registered (determined by * checking to see if the {@link IInterface#asBinder callback.asBinder()} - * object is already in the list), then it will be left as-is. + * object is already in the list), then it will be replaced with the new callback. * Registrations are not counted; a single call to {@link #unregister} * will remove a callback after any number calls to register it. * @@ -106,7 +106,7 @@ public class RemoteCallbackList<E extends IInterface> { * * @param cookie Optional additional data to be associated with this * callback. - * + * * @return Returns true if the callback was successfully added to the list. * Returns false if it was not added, either because {@link #kill} had * previously been called or the callback's process has gone away. diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 461f1e00c415..3ae951170759 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -69,6 +69,8 @@ import android.util.Log; import android.view.WindowManager.LayoutParams; import com.android.internal.R; +import com.android.internal.annotations.CachedProperty; +import com.android.internal.annotations.CachedPropertyDefaults; import java.io.IOException; import java.lang.annotation.Retention; @@ -90,6 +92,7 @@ import java.util.Set; */ @SystemService(Context.USER_SERVICE) @android.ravenwood.annotation.RavenwoodKeepPartialClass +@CachedPropertyDefaults() public class UserManager { private static final String TAG = "UserManager"; @@ -108,6 +111,9 @@ public class UserManager { /** Whether the device is in headless system user mode; null until cached. */ private static Boolean sIsHeadlessSystemUser = null; + /** Generated class containing IpcDataCaches. */ + private final Object mIpcDataCache = new UserManagerCache(); + /** Maximum length of username. * @hide */ @@ -3766,62 +3772,18 @@ public class UserManager { return isUserUnlocked(user.getIdentifier()); } - private static final String CACHE_KEY_IS_USER_UNLOCKED_PROPERTY = - PropertyInvalidatedCache.createPropertyName( - PropertyInvalidatedCache.MODULE_SYSTEM, "is_user_unlocked"); - - private final PropertyInvalidatedCache<Integer, Boolean> mIsUserUnlockedCache = - new PropertyInvalidatedCache<Integer, Boolean>( - 32, CACHE_KEY_IS_USER_UNLOCKED_PROPERTY) { - @Override - public Boolean recompute(Integer query) { - try { - return mService.isUserUnlocked(query); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - } - @Override - public boolean bypass(Integer query) { - return query < 0; - } - }; - - // Uses IS_USER_UNLOCKED_PROPERTY for invalidation as the APIs have the same dependencies. - private final PropertyInvalidatedCache<Integer, Boolean> mIsUserUnlockingOrUnlockedCache = - new PropertyInvalidatedCache<Integer, Boolean>( - 32, CACHE_KEY_IS_USER_UNLOCKED_PROPERTY) { - @Override - public Boolean recompute(Integer query) { - try { - return mService.isUserUnlockingOrUnlocked(query); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - } - @Override - public boolean bypass(Integer query) { - return query < 0; - } - }; - /** @hide */ @UnsupportedAppUsage @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS, Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true) + @CachedProperty(modsFlagOnOrNone = {}, api = "is_user_unlocked") public boolean isUserUnlocked(@UserIdInt int userId) { - return mIsUserUnlockedCache.query(userId); - } - - /** @hide */ - public void disableIsUserUnlockedCache() { - mIsUserUnlockedCache.disableLocal(); - mIsUserUnlockingOrUnlockedCache.disableLocal(); + return ((UserManagerCache) mIpcDataCache).isUserUnlocked(mService::isUserUnlocked, userId); } /** @hide */ public static final void invalidateIsUserUnlockedCache() { - PropertyInvalidatedCache.invalidateCache(CACHE_KEY_IS_USER_UNLOCKED_PROPERTY); + UserManagerCache.invalidateUserUnlocked(); } /** @@ -3852,8 +3814,10 @@ public class UserManager { /** @hide */ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS, Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true) + @CachedProperty(modsFlagOnOrNone = {}, api = "is_user_unlocked") public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) { - return mIsUserUnlockingOrUnlockedCache.query(userId); + return ((UserManagerCache) mIpcDataCache) + .isUserUnlockingOrUnlocked(mService::isUserUnlockingOrUnlocked, userId); } /** @@ -5686,31 +5650,9 @@ public class UserManager { } } - private static final String CACHE_KEY_QUIET_MODE_ENABLED_PROPERTY = - PropertyInvalidatedCache.createPropertyName( - PropertyInvalidatedCache.MODULE_SYSTEM, "quiet_mode_enabled"); - - private final PropertyInvalidatedCache<Integer, Boolean> mQuietModeEnabledCache = - new PropertyInvalidatedCache<Integer, Boolean>( - 32, CACHE_KEY_QUIET_MODE_ENABLED_PROPERTY) { - @Override - public Boolean recompute(Integer query) { - try { - return mService.isQuietModeEnabled(query); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - } - @Override - public boolean bypass(Integer query) { - return query < 0; - } - }; - - /** @hide */ public static final void invalidateQuietModeEnabledCache() { - PropertyInvalidatedCache.invalidateCache(CACHE_KEY_QUIET_MODE_ENABLED_PROPERTY); + UserManagerCache.invalidateQuietModeEnabled(); } /** @@ -5719,13 +5661,15 @@ public class UserManager { * @param userHandle The user handle of the profile to be queried. * @return true if the profile is in quiet mode, false otherwise. */ + @CachedProperty(modsFlagOnOrNone = {}) public boolean isQuietModeEnabled(UserHandle userHandle) { - if (android.multiuser.Flags.cacheQuietModeState()){ + if (android.multiuser.Flags.cacheQuietModeState()) { final int userId = userHandle.getIdentifier(); if (userId < 0) { return false; } - return mQuietModeEnabledCache.query(userId); + return ((UserManagerCache) mIpcDataCache).isQuietModeEnabled( + (UserHandle uh) -> mService.isQuietModeEnabled(uh.getIdentifier()), userHandle); } try { return mService.isQuietModeEnabled(userHandle.getIdentifier()); @@ -6424,41 +6368,21 @@ public class UserManager { Settings.Global.DEVICE_DEMO_MODE, 0) > 0; } - private static final String CACHE_KEY_USER_SERIAL_NUMBER_PROPERTY = - PropertyInvalidatedCache.createPropertyName( - PropertyInvalidatedCache.MODULE_SYSTEM, "user_serial_number"); - - private final PropertyInvalidatedCache<Integer, Integer> mUserSerialNumberCache = - new PropertyInvalidatedCache<Integer, Integer>( - 32, CACHE_KEY_USER_SERIAL_NUMBER_PROPERTY) { - @Override - public Integer recompute(Integer query) { - try { - return mService.getUserSerialNumber(query); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - } - @Override - public boolean bypass(Integer query) { - return query <= 0; - } - }; - - /** @hide */ public static final void invalidateUserSerialNumberCache() { - PropertyInvalidatedCache.invalidateCache(CACHE_KEY_USER_SERIAL_NUMBER_PROPERTY); + UserManagerCache.invalidateUserSerialNumber(); } /** * Returns a serial number on this device for a given userId. User handles can be recycled - * when deleting and creating users, but serial numbers are not reused until the device is wiped. + * when deleting and creating users, but serial numbers are not reused until the device is + * wiped. * @param userId * @return a serial number associated with that user, or -1 if the userId is not valid. * @hide */ @UnsupportedAppUsage + @CachedProperty(modsFlagOnOrNone = {}) public int getUserSerialNumber(@UserIdInt int userId) { // Read only flag should is to fix early access to this API // cacheUserSerialNumber to be removed after the @@ -6470,7 +6394,8 @@ public class UserManager { if (userId == UserHandle.USER_SYSTEM) { return UserHandle.USER_SERIAL_SYSTEM; } - return mUserSerialNumberCache.query(userId); + return ((UserManagerCache) mIpcDataCache).getUserSerialNumber( + mService::getUserSerialNumber, userId); } try { return mService.getUserSerialNumber(userId); diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index 64a2dbcb6a83..ffc58c537f2a 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -40,6 +40,7 @@ import android.os.vibrator.PrimitiveSegment; import android.os.vibrator.RampSegment; import android.os.vibrator.StepSegment; import android.os.vibrator.VibrationEffectSegment; +import android.os.vibrator.VibratorFrequencyProfileLegacy; import android.util.MathUtils; import com.android.internal.util.Preconditions; @@ -1761,7 +1762,7 @@ public abstract class VibrationEffect implements Parcelable { * new value as fast as possible. * * <p>Vibration parameter values will be truncated to conform to the device capabilities - * according to the {@link android.os.vibrator.VibratorFrequencyProfile}. + * according to the {@link VibratorFrequencyProfileLegacy}. * * @param duration The length of time this transition should take. Value must be * non-negative and will be truncated to milliseconds. @@ -1792,7 +1793,7 @@ public abstract class VibrationEffect implements Parcelable { * new values as fast as possible. * * <p>Vibration parameters values will be truncated to conform to the device capabilities - * according to the {@link android.os.vibrator.VibratorFrequencyProfile}. + * according to the {@link VibratorFrequencyProfileLegacy}. * * @param duration The length of time this transition should take. Value must be * non-negative and will be truncated to milliseconds. diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java index 84325b7c2874..7327630bca39 100644 --- a/core/java/android/os/Vibrator.java +++ b/core/java/android/os/Vibrator.java @@ -22,6 +22,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; @@ -33,7 +34,7 @@ import android.hardware.vibrator.IVibrator; import android.media.AudioAttributes; import android.os.vibrator.Flags; import android.os.vibrator.VibrationConfig; -import android.os.vibrator.VibratorFrequencyProfile; +import android.os.vibrator.VibratorFrequencyProfileLegacy; import android.util.Log; import android.view.HapticFeedbackConstants; @@ -290,13 +291,15 @@ public abstract class Vibrator { * @hide */ @TestApi + @SuppressLint("UnflaggedApi") @Nullable - public VibratorFrequencyProfile getFrequencyProfile() { - VibratorInfo.FrequencyProfile frequencyProfile = getInfo().getFrequencyProfile(); + public VibratorFrequencyProfileLegacy getFrequencyProfileLegacy() { + VibratorInfo.FrequencyProfileLegacy frequencyProfile = + getInfo().getFrequencyProfileLegacy(); if (frequencyProfile.isEmpty()) { return null; } - return new VibratorFrequencyProfile(frequencyProfile); + return new VibratorFrequencyProfileLegacy(frequencyProfile); } /** diff --git a/core/java/android/os/VibratorInfo.java b/core/java/android/os/VibratorInfo.java index 5378295e3720..f7fff391147b 100644 --- a/core/java/android/os/VibratorInfo.java +++ b/core/java/android/os/VibratorInfo.java @@ -59,7 +59,7 @@ public class VibratorInfo implements Parcelable { private final int mPwlePrimitiveDurationMax; private final int mPwleSizeMax; private final float mQFactor; - private final FrequencyProfile mFrequencyProfile; + private final FrequencyProfileLegacy mFrequencyProfileLegacy; private final int mMaxEnvelopeEffectSize; private final int mMinEnvelopeEffectControlPointDurationMillis; private final int mMaxEnvelopeEffectControlPointDurationMillis; @@ -75,7 +75,7 @@ public class VibratorInfo implements Parcelable { mPwlePrimitiveDurationMax = in.readInt(); mPwleSizeMax = in.readInt(); mQFactor = in.readFloat(); - mFrequencyProfile = FrequencyProfile.CREATOR.createFromParcel(in); + mFrequencyProfileLegacy = FrequencyProfileLegacy.CREATOR.createFromParcel(in); mMaxEnvelopeEffectSize = in.readInt(); mMinEnvelopeEffectControlPointDurationMillis = in.readInt(); mMaxEnvelopeEffectControlPointDurationMillis = in.readInt(); @@ -86,7 +86,7 @@ public class VibratorInfo implements Parcelable { baseVibratorInfo.mSupportedBraking, baseVibratorInfo.mSupportedPrimitives, baseVibratorInfo.mPrimitiveDelayMax, baseVibratorInfo.mCompositionSizeMax, baseVibratorInfo.mPwlePrimitiveDurationMax, baseVibratorInfo.mPwleSizeMax, - baseVibratorInfo.mQFactor, baseVibratorInfo.mFrequencyProfile, + baseVibratorInfo.mQFactor, baseVibratorInfo.mFrequencyProfileLegacy, baseVibratorInfo.mMaxEnvelopeEffectSize, baseVibratorInfo.mMinEnvelopeEffectControlPointDurationMillis, baseVibratorInfo.mMaxEnvelopeEffectControlPointDurationMillis); @@ -112,7 +112,7 @@ public class VibratorInfo implements Parcelable { * @param pwleSizeMax The maximum number of primitives supported by a PWLE * composition. * @param qFactor The vibrator quality factor. - * @param frequencyProfile The description of the vibrator supported frequencies and max + * @param frequencyProfileLegacy The description of the vibrator supported frequencies and max * amplitude mappings. * @hide */ @@ -120,11 +120,11 @@ public class VibratorInfo implements Parcelable { @Nullable SparseBooleanArray supportedBraking, @NonNull SparseIntArray supportedPrimitives, int primitiveDelayMax, int compositionSizeMax, int pwlePrimitiveDurationMax, int pwleSizeMax, - float qFactor, @NonNull FrequencyProfile frequencyProfile, + float qFactor, @NonNull FrequencyProfileLegacy frequencyProfileLegacy, int maxEnvelopeEffectSize, int minEnvelopeEffectControlPointDurationMillis, int maxEnvelopeEffectControlPointDurationMillis) { Preconditions.checkNotNull(supportedPrimitives); - Preconditions.checkNotNull(frequencyProfile); + Preconditions.checkNotNull(frequencyProfileLegacy); mId = id; mCapabilities = capabilities; mSupportedEffects = supportedEffects == null ? null : supportedEffects.clone(); @@ -135,7 +135,7 @@ public class VibratorInfo implements Parcelable { mPwlePrimitiveDurationMax = pwlePrimitiveDurationMax; mPwleSizeMax = pwleSizeMax; mQFactor = qFactor; - mFrequencyProfile = frequencyProfile; + mFrequencyProfileLegacy = frequencyProfileLegacy; mMaxEnvelopeEffectSize = maxEnvelopeEffectSize; mMinEnvelopeEffectControlPointDurationMillis = minEnvelopeEffectControlPointDurationMillis; @@ -155,7 +155,7 @@ public class VibratorInfo implements Parcelable { dest.writeInt(mPwlePrimitiveDurationMax); dest.writeInt(mPwleSizeMax); dest.writeFloat(mQFactor); - mFrequencyProfile.writeToParcel(dest, flags); + mFrequencyProfileLegacy.writeToParcel(dest, flags); dest.writeInt(mMaxEnvelopeEffectSize); dest.writeInt(mMinEnvelopeEffectControlPointDurationMillis); dest.writeInt(mMaxEnvelopeEffectControlPointDurationMillis); @@ -205,7 +205,7 @@ public class VibratorInfo implements Parcelable { && Objects.equals(mSupportedEffects, that.mSupportedEffects) && Objects.equals(mSupportedBraking, that.mSupportedBraking) && Objects.equals(mQFactor, that.mQFactor) - && Objects.equals(mFrequencyProfile, that.mFrequencyProfile) + && Objects.equals(mFrequencyProfileLegacy, that.mFrequencyProfileLegacy) && mMaxEnvelopeEffectSize == that.mMaxEnvelopeEffectSize && mMinEnvelopeEffectControlPointDurationMillis == that.mMinEnvelopeEffectControlPointDurationMillis @@ -216,7 +216,7 @@ public class VibratorInfo implements Parcelable { @Override public int hashCode() { int hashCode = Objects.hash(mId, mCapabilities, mSupportedEffects, mSupportedBraking, - mQFactor, mFrequencyProfile); + mQFactor, mFrequencyProfileLegacy); for (int i = 0; i < mSupportedPrimitives.size(); i++) { hashCode = 31 * hashCode + mSupportedPrimitives.keyAt(i); hashCode = 31 * hashCode + mSupportedPrimitives.valueAt(i); @@ -238,7 +238,7 @@ public class VibratorInfo implements Parcelable { + ", mPwlePrimitiveDurationMax=" + mPwlePrimitiveDurationMax + ", mPwleSizeMax=" + mPwleSizeMax + ", mQFactor=" + mQFactor - + ", mFrequencyProfile=" + mFrequencyProfile + + ", mFrequencyProfileLegacy=" + mFrequencyProfileLegacy + ", mMaxEnvelopeEffectSize=" + mMaxEnvelopeEffectSize + ", mMinEnvelopeEffectControlPointDurationMillis=" + mMinEnvelopeEffectControlPointDurationMillis @@ -262,7 +262,7 @@ public class VibratorInfo implements Parcelable { pw.println("pwlePrimitiveDurationMax = " + mPwlePrimitiveDurationMax); pw.println("pwleSizeMax = " + mPwleSizeMax); pw.println("q-factor = " + mQFactor); - pw.println("frequencyProfile = " + mFrequencyProfile); + pw.println("frequencyProfileLegacy = " + mFrequencyProfileLegacy); pw.println("mMaxEnvelopeEffectSize = " + mMaxEnvelopeEffectSize); pw.println("mMinEnvelopeEffectControlPointDurationMillis = " + mMinEnvelopeEffectControlPointDurationMillis); @@ -517,7 +517,7 @@ public class VibratorInfo implements Parcelable { * this vibrator is a composite of multiple physical devices. */ public float getResonantFrequencyHz() { - return mFrequencyProfile.mResonantFrequencyHz; + return mFrequencyProfileLegacy.mResonantFrequencyHz; } /** @@ -537,8 +537,8 @@ public class VibratorInfo implements Parcelable { * <p>If the devices does not have frequency control then the profile should be empty. */ @NonNull - public FrequencyProfile getFrequencyProfile() { - return mFrequencyProfile; + public FrequencyProfileLegacy getFrequencyProfileLegacy() { + return mFrequencyProfileLegacy; } /** Returns a single int representing all the capabilities of the vibrator. */ @@ -640,7 +640,7 @@ public class VibratorInfo implements Parcelable { * * @hide */ - public static final class FrequencyProfile implements Parcelable { + public static final class FrequencyProfileLegacy implements Parcelable { @Nullable private final Range<Float> mFrequencyRangeHz; private final float mMinFrequencyHz; @@ -648,7 +648,7 @@ public class VibratorInfo implements Parcelable { private final float mFrequencyResolutionHz; private final float[] mMaxAmplitudes; - FrequencyProfile(Parcel in) { + FrequencyProfileLegacy(Parcel in) { this(in.readFloat(), in.readFloat(), in.readFloat(), in.createFloatArray()); } @@ -664,7 +664,7 @@ public class VibratorInfo implements Parcelable { * resolution. * @hide */ - public FrequencyProfile(float resonantFrequencyHz, float minFrequencyHz, + public FrequencyProfileLegacy(float resonantFrequencyHz, float minFrequencyHz, float frequencyResolutionHz, float[] maxAmplitudes) { mMinFrequencyHz = minFrequencyHz; mResonantFrequencyHz = resonantFrequencyHz; @@ -776,10 +776,10 @@ public class VibratorInfo implements Parcelable { if (this == o) { return true; } - if (!(o instanceof FrequencyProfile)) { + if (!(o instanceof FrequencyProfileLegacy)) { return false; } - FrequencyProfile that = (FrequencyProfile) o; + FrequencyProfileLegacy that = (FrequencyProfileLegacy) o; return Float.compare(mMinFrequencyHz, that.mMinFrequencyHz) == 0 && Float.compare(mResonantFrequencyHz, that.mResonantFrequencyHz) == 0 && Float.compare(mFrequencyResolutionHz, that.mFrequencyResolutionHz) == 0 @@ -796,7 +796,7 @@ public class VibratorInfo implements Parcelable { @Override public String toString() { - return "FrequencyProfile{" + return "FrequencyProfileLegacy{" + "mFrequencyRange=" + mFrequencyRangeHz + ", mMinFrequency=" + mMinFrequencyHz + ", mResonantFrequency=" + mResonantFrequencyHz @@ -806,16 +806,16 @@ public class VibratorInfo implements Parcelable { } @NonNull - public static final Creator<FrequencyProfile> CREATOR = - new Creator<FrequencyProfile>() { + public static final Creator<FrequencyProfileLegacy> CREATOR = + new Creator<FrequencyProfileLegacy>() { @Override - public FrequencyProfile createFromParcel(Parcel in) { - return new FrequencyProfile(in); + public FrequencyProfileLegacy createFromParcel(Parcel in) { + return new FrequencyProfileLegacy(in); } @Override - public FrequencyProfile[] newArray(int size) { - return new FrequencyProfile[size]; + public FrequencyProfileLegacy[] newArray(int size) { + return new FrequencyProfileLegacy[size]; } }; } @@ -832,8 +832,8 @@ public class VibratorInfo implements Parcelable { private int mPwlePrimitiveDurationMax; private int mPwleSizeMax; private float mQFactor = Float.NaN; - private FrequencyProfile mFrequencyProfile = - new FrequencyProfile(Float.NaN, Float.NaN, Float.NaN, null); + private FrequencyProfileLegacy mFrequencyProfileLegacy = + new FrequencyProfileLegacy(Float.NaN, Float.NaN, Float.NaN, null); private int mMaxEnvelopeEffectSize; private int mMinEnvelopeEffectControlPointDurationMillis; private int mMaxEnvelopeEffectControlPointDurationMillis; @@ -908,8 +908,8 @@ public class VibratorInfo implements Parcelable { /** Configure the vibrator frequency information like resonant frequency and bandwidth. */ @NonNull - public Builder setFrequencyProfile(@NonNull FrequencyProfile frequencyProfile) { - mFrequencyProfile = frequencyProfile; + public Builder setFrequencyProfileLegacy(@NonNull FrequencyProfileLegacy frequencyProfile) { + mFrequencyProfileLegacy = frequencyProfile; return this; } @@ -950,7 +950,7 @@ public class VibratorInfo implements Parcelable { public VibratorInfo build() { return new VibratorInfo(mId, mCapabilities, mSupportedEffects, mSupportedBraking, mSupportedPrimitives, mPrimitiveDelayMax, mCompositionSizeMax, - mPwlePrimitiveDurationMax, mPwleSizeMax, mQFactor, mFrequencyProfile, + mPwlePrimitiveDurationMax, mPwleSizeMax, mQFactor, mFrequencyProfileLegacy, mMaxEnvelopeEffectSize, mMinEnvelopeEffectControlPointDurationMillis, mMaxEnvelopeEffectControlPointDurationMillis); } diff --git a/core/java/android/os/vibrator/MultiVibratorInfo.java b/core/java/android/os/vibrator/MultiVibratorInfo.java index 9c2b9782ffb3..37dae56abc6d 100644 --- a/core/java/android/os/vibrator/MultiVibratorInfo.java +++ b/core/java/android/os/vibrator/MultiVibratorInfo.java @@ -48,7 +48,7 @@ public final class MultiVibratorInfo extends VibratorInfo { } private MultiVibratorInfo( - int id, VibratorInfo[] vibrators, VibratorInfo.FrequencyProfile mergedProfile) { + int id, VibratorInfo[] vibrators, FrequencyProfileLegacy mergedProfile) { super(id, capabilitiesIntersection(vibrators, mergedProfile.isEmpty()), supportedEffectsIntersection(vibrators), @@ -209,15 +209,15 @@ public final class MultiVibratorInfo extends VibratorInfo { } @NonNull - private static FrequencyProfile frequencyProfileIntersection(VibratorInfo[] infos) { + private static FrequencyProfileLegacy frequencyProfileIntersection(VibratorInfo[] infos) { float freqResolution = floatPropertyIntersection(infos, - info -> info.getFrequencyProfile().getFrequencyResolutionHz()); + info -> info.getFrequencyProfileLegacy().getFrequencyResolutionHz()); float resonantFreq = floatPropertyIntersection(infos, VibratorInfo::getResonantFrequencyHz); Range<Float> freqRange = frequencyRangeIntersection(infos, freqResolution); if ((freqRange == null) || Float.isNaN(freqResolution)) { - return new FrequencyProfile(resonantFreq, Float.NaN, freqResolution, null); + return new FrequencyProfileLegacy(resonantFreq, Float.NaN, freqResolution, null); } int amplitudeCount = @@ -230,8 +230,8 @@ public final class MultiVibratorInfo extends VibratorInfo { Arrays.fill(maxAmplitudes, Float.MAX_VALUE); for (VibratorInfo info : infos) { - Range<Float> vibratorFreqRange = info.getFrequencyProfile().getFrequencyRangeHz(); - float[] vibratorMaxAmplitudes = info.getFrequencyProfile().getMaxAmplitudes(); + Range<Float> vibratorFreqRange = info.getFrequencyProfileLegacy().getFrequencyRangeHz(); + float[] vibratorMaxAmplitudes = info.getFrequencyProfileLegacy().getMaxAmplitudes(); int vibratorStartIdx = Math.round( (freqRange.getLower() - vibratorFreqRange.getLower()) / freqResolution); int vibratorEndIdx = vibratorStartIdx + maxAmplitudes.length - 1; @@ -240,7 +240,7 @@ public final class MultiVibratorInfo extends VibratorInfo { Slog.w(TAG, "Error calculating the intersection of vibrator frequency" + " profiles: attempted to fetch from vibrator " + info.getId() + " max amplitude with bad index " + vibratorStartIdx); - return new FrequencyProfile(resonantFreq, Float.NaN, Float.NaN, null); + return new FrequencyProfileLegacy(resonantFreq, Float.NaN, Float.NaN, null); } for (int i = 0; i < maxAmplitudes.length; i++) { @@ -249,14 +249,14 @@ public final class MultiVibratorInfo extends VibratorInfo { } } - return new FrequencyProfile(resonantFreq, freqRange.getLower(), + return new FrequencyProfileLegacy(resonantFreq, freqRange.getLower(), freqResolution, maxAmplitudes); } @Nullable private static Range<Float> frequencyRangeIntersection(VibratorInfo[] infos, float frequencyResolution) { - Range<Float> firstRange = infos[0].getFrequencyProfile().getFrequencyRangeHz(); + Range<Float> firstRange = infos[0].getFrequencyProfileLegacy().getFrequencyRangeHz(); if (firstRange == null) { // If one vibrator is undefined then the intersection is undefined. return null; @@ -268,7 +268,7 @@ public final class MultiVibratorInfo extends VibratorInfo { // min supported frequencies are aligned w.r.t. the frequency resolution. for (int i = 1; i < infos.length; i++) { - Range<Float> vibratorRange = infos[i].getFrequencyProfile().getFrequencyRangeHz(); + Range<Float> vibratorRange = infos[i].getFrequencyProfileLegacy().getFrequencyRangeHz(); if (vibratorRange == null) { // If one vibrator is undefined then the intersection is undefined. return null; diff --git a/core/java/android/os/vibrator/VibratorFrequencyProfile.java b/core/java/android/os/vibrator/VibratorFrequencyProfileLegacy.java index 8392940010e3..5c3e785550d3 100644 --- a/core/java/android/os/vibrator/VibratorFrequencyProfile.java +++ b/core/java/android/os/vibrator/VibratorFrequencyProfileLegacy.java @@ -18,6 +18,7 @@ package android.os.vibrator; import android.annotation.FloatRange; import android.annotation.NonNull; +import android.annotation.SuppressLint; import android.annotation.TestApi; import android.os.VibratorInfo; @@ -42,12 +43,14 @@ import com.android.internal.util.Preconditions; * @hide */ @TestApi -public final class VibratorFrequencyProfile { +@SuppressLint("UnflaggedApi") +public final class VibratorFrequencyProfileLegacy { - private final VibratorInfo.FrequencyProfile mFrequencyProfile; + private final VibratorInfo.FrequencyProfileLegacy mFrequencyProfile; /** @hide */ - public VibratorFrequencyProfile(@NonNull VibratorInfo.FrequencyProfile frequencyProfile) { + public VibratorFrequencyProfileLegacy( + @NonNull VibratorInfo.FrequencyProfileLegacy frequencyProfile) { Preconditions.checkArgument(!frequencyProfile.isEmpty(), "Frequency profile must have a non-empty frequency range"); mFrequencyProfile = frequencyProfile; @@ -68,6 +71,7 @@ public final class VibratorFrequencyProfile { * @hide */ @TestApi + @SuppressLint("UnflaggedApi") @NonNull @FloatRange(from = 0, to = 1) public float[] getMaxAmplitudeMeasurements() { @@ -82,6 +86,7 @@ public final class VibratorFrequencyProfile { * @hide */ @TestApi + @SuppressLint("UnflaggedApi") public float getMaxAmplitudeMeasurementInterval() { return mFrequencyProfile.getFrequencyResolutionHz(); } @@ -93,6 +98,7 @@ public final class VibratorFrequencyProfile { * @hide */ @TestApi + @SuppressLint("UnflaggedApi") public float getMinFrequency() { return mFrequencyProfile.getFrequencyRangeHz().getLower(); } @@ -104,6 +110,7 @@ public final class VibratorFrequencyProfile { * @hide */ @TestApi + @SuppressLint("UnflaggedApi") public float getMaxFrequency() { return mFrequencyProfile.getFrequencyRangeHz().getUpper(); } diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 27b1dfbd9b18..98d58d0c991f 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -3027,6 +3027,48 @@ public final class ContactsContract { */ @FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED) public static final class DefaultAccount { + /** + * no public constructor since this is a utility class + */ + private DefaultAccount() { + + } + + /** + * Key in the outgoing Bundle for the default account list. + * + * @hide + */ + public static final String KEY_ELIGIBLE_DEFAULT_ACCOUNTS = + "key_eligible_default_accounts"; + /** + * The method to invoke in order to query eligiblie default accounts. + * + * @hide + */ + public static final String QUERY_ELIGIBLE_DEFAULT_ACCOUNTS_METHOD = + "queryEligibleDefaultAccounts"; + /** + * Key in the Bundle for the default account state. + * + * @hide + */ + public static final String KEY_DEFAULT_ACCOUNT_STATE = + "key_default_account_state"; + /** + * The method to invoke in order to set the default account. + * + * @hide + */ + public static final String SET_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD = + "setDefaultAccountForNewContacts"; + /** + * The method to invoke in order to query the default account. + * + * @hide + */ + public static final String QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD = + "queryDefaultAccountForNewContacts"; /** * Represents the state of the default account, and the actual {@link Account} if it's @@ -3228,6 +3270,276 @@ public final class ContactsContract { public @interface DefaultAccountState { } } + + /** + * Get the account that is set as the default account for new contacts, which should be + * initially selected when creating a new contact on contact management apps. + * + * @param resolver the ContentResolver to query. + * + * @return the default account state for new contacts. + * @throws RuntimeException if failed to look up the default account. + * @throws IllegalStateException if the default account is in an invalid state. + */ + @FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED) + public static @NonNull DefaultAccountAndState getDefaultAccountForNewContacts( + @NonNull ContentResolver resolver) { + Bundle response = nullSafeCall(resolver, ContactsContract.AUTHORITY_URI, + QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD, null, null); + + int defaultContactsAccountState = response.getInt(KEY_DEFAULT_ACCOUNT_STATE, -1); + if (defaultContactsAccountState + == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD) { + String accountName = response.getString(Settings.ACCOUNT_NAME); + String accountType = response.getString(Settings.ACCOUNT_TYPE); + if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) { + throw new IllegalStateException( + "account name and type cannot be null or empty"); + } + return new DefaultAccountAndState( + DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD, + new Account(accountName, accountType)); + } else if (defaultContactsAccountState + == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_LOCAL + || defaultContactsAccountState + == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_NOT_SET) { + return new DefaultAccountAndState(defaultContactsAccountState, /*cloudAccount=*/ + null); + } else { + throw new IllegalStateException("Invalid default account state"); + } + } + + /** + * Sets the default account that should be initially selected when creating a new + * contact on + * contact management apps. Apps can only set one of + * The following accounts as the default account: + * <ol> + * <li> local account + * <li> cloud account that are eligible to be set as default account. + * </ol> + * + * @param resolver the ContentResolver to query. + * @param defaultAccountAndState the default account and state to be set. To set the + * local + * account as the + * default account, this parameter should be + * {@link DefaultAccountAndState#ofLocal()}. To set the a + * cloud + * account as the default account, this parameter should + * be + * {@link DefaultAccountAndState#ofCloud(Account)}. To + * set + * the + * default account to a "not set" state, this parameter + * should + * be {@link DefaultAccountAndState#ofNotSet()}. + * + * @throws RuntimeException if it fails to set the default account. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS) + @FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED) + @SystemApi + public static void setDefaultAccountForNewContacts(@NonNull ContentResolver resolver, + @NonNull DefaultAccountAndState defaultAccountAndState) { + Bundle extras = new Bundle(); + + extras.putInt(KEY_DEFAULT_ACCOUNT_STATE, defaultAccountAndState.getState()); + if (defaultAccountAndState.getState() + == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD) { + Account cloudAccount = defaultAccountAndState.getAccount(); + assert cloudAccount != null; + extras.putString(Settings.ACCOUNT_NAME, cloudAccount.name); + extras.putString(Settings.ACCOUNT_TYPE, cloudAccount.type); + } + nullSafeCall(resolver, ContactsContract.AUTHORITY_URI, + SET_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD, null, extras); + } + + /** + * Get a list of cloud accounts that is eligible to set as default account with state of + * {@link DefaultAccountAndState#DEFAULT_ACCOUNT_STATE_CLOUD}. May be empty but never + * null. + * + * @param resolver content resolver to query. + * @return a of cloud accounts that is eligible to set as default account with state of + * {@link DefaultAccountAndState#DEFAULT_ACCOUNT_STATE_CLOUD}. + * @throws RuntimeException if the query fails. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS) + @FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED) + @SystemApi + public static @NonNull List<Account> getEligibleCloudAccounts( + @NonNull ContentResolver resolver) { + Bundle response = nullSafeCall(resolver, ContactsContract.AUTHORITY_URI, + QUERY_ELIGIBLE_DEFAULT_ACCOUNTS_METHOD, null, null); + List<Account> result = response.getParcelableArrayList( + KEY_ELIGIBLE_DEFAULT_ACCOUNTS, Account.class); + if (result == null) { + return new ArrayList<>(); + } + return result; + } + + + + /** + * The method to invoke to move local {@link RawContacts} and {@link Groups} from local + * account(s) to the Cloud Default Account (if any). + * + * @hide + */ + public static final String MOVE_LOCAL_CONTACTS_TO_CLOUD_DEFAULT_ACCOUNT_METHOD = + "moveLocalContactsToCloudDefaultAccount"; + + /** + * Move {@link RawContacts} and {@link Groups} (if any) from the local account to the + * Cloud Default Account (if any). + * @param resolver the ContentResolver to query. + * @throws RuntimeException if it fails to move contacts to the default account. + * + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED) + @RequiresPermission(allOf = {android.Manifest.permission.WRITE_CONTACTS, + android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS}) + public static void moveLocalContactsToCloudDefaultAccount( + @NonNull ContentResolver resolver) { + + Bundle extras = new Bundle(); + Bundle result = nullSafeCall( + resolver, + ContactsContract.AUTHORITY_URI, + MOVE_LOCAL_CONTACTS_TO_CLOUD_DEFAULT_ACCOUNT_METHOD, + null, + extras); + } + + /** + * The method to invoke to move {@link RawContacts} and {@link Groups} from SIM + * account(s) to the Cloud Default Account (if any). + * + * @hide + */ + public static final String MOVE_SIM_CONTACTS_TO_CLOUD_DEFAULT_ACCOUNT_METHOD = + "moveSimContactsToCloudDefaultAccount"; + + /** + * Move {@link RawContacts} and {@link Groups} (if any) from the local account to the + * Cloud Default Account (if any). + * @param resolver the ContentResolver to query. + * @throws RuntimeException if it fails to move contacts to the default account. + * + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED) + @RequiresPermission(allOf = {android.Manifest.permission.WRITE_CONTACTS, + android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS}) + public static void moveSimContactsToCloudDefaultAccount( + @NonNull ContentResolver resolver) { + Bundle result = nullSafeCall( + resolver, + ContactsContract.AUTHORITY_URI, + MOVE_SIM_CONTACTS_TO_CLOUD_DEFAULT_ACCOUNT_METHOD, + /* arg= */ null, + /* extras= */ null); + } + + /** + * The method to invoke to get the number of {@link RawContacts} that are in local + * account(s) and movable to the Cloud Default Account (if any). + * + * @hide + */ + public static final String GET_NUMBER_OF_MOVABLE_LOCAL_CONTACTS_METHOD = + "getNumberOfMovableLocalContacts"; + + /** + * The result key for moving local {@link RawContacts} and {@link Groups} from SIM + * account(s) to the Cloud Default Account (if any). + * + * @hide + */ + public static final String KEY_NUMBER_OF_MOVABLE_LOCAL_CONTACTS = + "key_number_of_movable_local_contacts"; + + /** + * Gets the number of {@link RawContacts} in the local account(s) which may be moved + * using {@link DefaultAccount#moveLocalContactsToCloudDefaultAccount} (if any). + * @param resolver the ContentResolver to query. + * @return the number of {@link RawContacts} in the local account(s), or 0 if there is + * no Cloud Default Account. + * @throws RuntimeException if it fails get the number of movable local contacts. + * + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED) + @RequiresPermission(allOf = {android.Manifest.permission.READ_CONTACTS, + android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS}) + public static int getNumberOfMovableLocalContacts( + @NonNull ContentResolver resolver) { + Bundle result = nullSafeCall( + resolver, + ContactsContract.AUTHORITY_URI, + GET_NUMBER_OF_MOVABLE_LOCAL_CONTACTS_METHOD, + /* arg= */ null, + /* extras= */ null); + return result.getInt(KEY_NUMBER_OF_MOVABLE_LOCAL_CONTACTS, + /* defaultValue= */ 0); + } + + /** + * The method to invoke to get the number of {@link RawContacts} that are in SIM + * account(s) and movable to the Cloud Default Account (if any). + * + * @hide + */ + public static final String GET_NUMBER_OF_MOVABLE_SIM_CONTACTS_METHOD = + "getNumberOfMovableSimContacts"; + + /** + * The result key for moving local {@link RawContacts} and {@link Groups} from SIM + * account(s) to the Cloud Default Account (if any). + * + * @hide + */ + public static final String KEY_NUMBER_OF_MOVABLE_SIM_CONTACTS = + "key_number_of_movable_sim_contacts"; + + /** + * Gets the number of {@link RawContacts} in the SIM account(s) which may be moved using + * {@link DefaultAccount#moveSimContactsToCloudDefaultAccount} (if any). + * @param resolver the ContentResolver to query. + * @return the number of {@link RawContacts} in the SIM account(s), or 0 if there is + * no Cloud Default Account. + * @throws RuntimeException if it fails get the number of movable sim contacts. + * + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED) + @RequiresPermission(allOf = {android.Manifest.permission.READ_CONTACTS, + android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS}) + public static int getNumberOfMovableSimContacts( + @NonNull ContentResolver resolver) { + Bundle result = nullSafeCall( + resolver, + ContactsContract.AUTHORITY_URI, + GET_NUMBER_OF_MOVABLE_SIM_CONTACTS_METHOD, + /* arg= */ null, + /* extras= */ null); + return result.getInt(KEY_NUMBER_OF_MOVABLE_SIM_CONTACTS, + /* defaultValue= */ 0); + } + } /** @@ -9055,30 +9367,6 @@ public final class ContactsContract { public static final String KEY_DEFAULT_ACCOUNT = "key_default_account"; /** - * Key in the Bundle for the default account state. - * - * @hide - */ - public static final String KEY_DEFAULT_ACCOUNT_STATE = - "key_default_contacts_account_state"; - - /** - * The method to invoke in order to set the default account. - * - * @hide - */ - public static final String SET_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD = - "setDefaultAccountForNewContacts"; - - /** - * The method to invoke in order to query the default account. - * - * @hide - */ - public static final String QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD = - "queryDefaultAccountForNewContacts"; - - /** * Get the account that is set as the default account for new contacts, which should be * initially selected when creating a new contact on contact management apps. * If the setting has not been set by any app, it will return null. Once the setting diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index d82af55e2771..1a15d09c0a50 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2092,23 +2092,6 @@ public final class Settings { public static final String ACTION_ZEN_MODE_SETTINGS = "android.settings.ZEN_MODE_SETTINGS"; /** - * Activity Action: Show Zen Mode visual effects configuration settings. - * - * @hide - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ZEN_MODE_BLOCKED_EFFECTS_SETTINGS = - "android.settings.ZEN_MODE_BLOCKED_EFFECTS_SETTINGS"; - - /** - * Activity Action: Show Zen Mode onboarding activity. - * - * @hide - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ZEN_MODE_ONBOARDING = "android.settings.ZEN_MODE_ONBOARDING"; - - /** * Activity Action: Show Zen Mode (aka Do Not Disturb) priority configuration settings. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) @@ -2367,6 +2350,21 @@ public final class Settings { "android.settings.ALL_APPS_NOTIFICATION_SETTINGS_FOR_REVIEW"; /** + * Activity Action: Show the permission screen for allowing apps to post promoted notifications. + * <p> + * Input: {@link #EXTRA_APP_PACKAGE}, the package to display. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Output: Nothing. + */ + @FlaggedApi(android.app.Flags.FLAG_API_RICH_ONGOING) + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_APP_NOTIFICATION_PROMOTION_SETTINGS + = "android.settings.APP_NOTIFICATION_PROMOTION_SETTINGS"; + + /** * Activity Action: Show notification settings for a single app. * <p> * Input: {@link #EXTRA_APP_PACKAGE}, the package to display. @@ -8748,35 +8746,6 @@ public final class Settings { /** @hide */ public static final int ZEN_DURATION_FOREVER = 0; /** - * If nonzero, will show the zen upgrade notification when the user toggles DND on/off. - * @hide - */ - @Readable - public static final String SHOW_ZEN_UPGRADE_NOTIFICATION = "show_zen_upgrade_notification"; - - /** - * If nonzero, will show the zen update settings suggestion. - * @hide - */ - @Readable - public static final String SHOW_ZEN_SETTINGS_SUGGESTION = "show_zen_settings_suggestion"; - - /** - * If nonzero, zen has not been updated to reflect new changes. - * @hide - */ - @Readable - public static final String ZEN_SETTINGS_UPDATED = "zen_settings_updated"; - - /** - * If nonzero, zen setting suggestion has been viewed by user - * @hide - */ - @Readable - public static final String ZEN_SETTINGS_SUGGESTION_VIEWED = - "zen_settings_suggestion_viewed"; - - /** * Whether the in call notification is enabled to play sound during calls. The value is * boolean (1 or 0). * @hide @@ -17844,12 +17813,6 @@ public final class Settings { public static final String FORCE_NON_DEBUGGABLE_FINAL_BUILD_FOR_COMPAT = "force_non_debuggable_final_build_for_compat"; - /** - * Flag to enable the use of ApplicationInfo for getting not-launched status. - * - * @hide - */ - public static final String ENABLE_USE_APP_INFO_NOT_LAUNCHED = "use_app_info_not_launched"; /** * Current version of signed configuration applied. @@ -18072,10 +18035,6 @@ public final class Settings { MOVED_TO_SECURE = new HashSet<>(8); MOVED_TO_SECURE.add(Global.INSTALL_NON_MARKET_APPS); MOVED_TO_SECURE.add(Global.ZEN_DURATION); - MOVED_TO_SECURE.add(Global.SHOW_ZEN_UPGRADE_NOTIFICATION); - MOVED_TO_SECURE.add(Global.SHOW_ZEN_SETTINGS_SUGGESTION); - MOVED_TO_SECURE.add(Global.ZEN_SETTINGS_UPDATED); - MOVED_TO_SECURE.add(Global.ZEN_SETTINGS_SUGGESTION_VIEWED); MOVED_TO_SECURE.add(Global.CHARGING_SOUNDS_ENABLED); MOVED_TO_SECURE.add(Global.CHARGING_VIBRATION_ENABLED); MOVED_TO_SECURE.add(Global.NOTIFICATION_BUBBLES); @@ -18910,40 +18869,6 @@ public final class Settings { @Readable public static final String SHOW_MUTE_IN_CRASH_DIALOG = "show_mute_in_crash_dialog"; - - /** - * If nonzero, will show the zen upgrade notification when the user toggles DND on/off. - * @hide - * @deprecated - Use {@link android.provider.Settings.Secure#SHOW_ZEN_UPGRADE_NOTIFICATION} - */ - @Deprecated - public static final String SHOW_ZEN_UPGRADE_NOTIFICATION = "show_zen_upgrade_notification"; - - /** - * If nonzero, will show the zen update settings suggestion. - * @hide - * @deprecated - Use {@link android.provider.Settings.Secure#SHOW_ZEN_SETTINGS_SUGGESTION} - */ - @Deprecated - public static final String SHOW_ZEN_SETTINGS_SUGGESTION = "show_zen_settings_suggestion"; - - /** - * If nonzero, zen has not been updated to reflect new changes. - * @deprecated - Use {@link android.provider.Settings.Secure#ZEN_SETTINGS_UPDATED} - * @hide - */ - @Deprecated - public static final String ZEN_SETTINGS_UPDATED = "zen_settings_updated"; - - /** - * If nonzero, zen setting suggestion has been viewed by user - * @hide - * @deprecated - Use {@link android.provider.Settings.Secure#ZEN_SETTINGS_SUGGESTION_VIEWED} - */ - @Deprecated - public static final String ZEN_SETTINGS_SUGGESTION_VIEWED = - "zen_settings_suggestion_viewed"; - /** * Backup and restore agent timeout parameters. * These parameters are represented by a comma-delimited key-value list. @@ -20233,6 +20158,12 @@ public final class Settings { public static final int PHONE_SWITCHING_STATUS_IN_PROGRESS_MIGRATION_SUCCESS = 11; /** + * Phone switching has finished account match step. + * @hide + */ + public static final int PHONE_SWITCHING_STATUS_ACCOUNTS_MATCHED = 12; + + /** * Phone switching request source * @hide */ diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index a86c961e6785..aedf8e097e67 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -106,3 +106,10 @@ flag { description: "Clear StrongAuth on add credential" bug: "320817991" } + +flag { + name: "afl_api" + namespace: "platform_security" + description: "AFL feature" + bug: "365994454" +} diff --git a/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java b/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java index de2c6f778fcd..afff8fec3872 100644 --- a/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java +++ b/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java @@ -20,6 +20,7 @@ import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -28,8 +29,10 @@ import android.net.Uri; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; +import android.os.UserHandle; import android.telephony.SmsMessage; +import com.android.internal.telephony.flags.Flags; import com.android.internal.util.Preconditions; import java.util.List; @@ -91,8 +94,12 @@ public final class CarrierMessagingServiceWrapper implements AutoCloseable { mOnServiceReadyCallback = onServiceReadyCallback; mServiceReadyCallbackExecutor = executor; mContext = context; - return context.bindService(intent, mCarrierMessagingServiceConnection, - Context.BIND_AUTO_CREATE); + return Flags.supportCarrierServicesForHsum() + ? context.bindServiceAsUser(intent, mCarrierMessagingServiceConnection, + Context.BIND_AUTO_CREATE, + UserHandle.of(ActivityManager.getCurrentUser())) + : context.bindService(intent, mCarrierMessagingServiceConnection, + Context.BIND_AUTO_CREATE); } /** diff --git a/core/java/android/service/ondeviceintelligence/OnDeviceSandboxedInferenceService.java b/core/java/android/service/ondeviceintelligence/OnDeviceSandboxedInferenceService.java index f123a962def9..3181556eded7 100644 --- a/core/java/android/service/ondeviceintelligence/OnDeviceSandboxedInferenceService.java +++ b/core/java/android/service/ondeviceintelligence/OnDeviceSandboxedInferenceService.java @@ -129,6 +129,16 @@ public abstract class OnDeviceSandboxedInferenceService extends Service { * @hide */ public static final String MODEL_UNLOADED_BUNDLE_KEY = "model_unloaded"; + /** + * @hide + */ + public static final String MODEL_LOADED_BROADCAST_INTENT = + "android.service.ondeviceintelligence.MODEL_LOADED"; + /** + * @hide + */ + public static final String MODEL_UNLOADED_BROADCAST_INTENT = + "android.service.ondeviceintelligence.MODEL_UNLOADED"; /** * @hide diff --git a/core/java/android/tracing/TEST_MAPPING b/core/java/android/tracing/TEST_MAPPING new file mode 100644 index 000000000000..b51d19da97a5 --- /dev/null +++ b/core/java/android/tracing/TEST_MAPPING @@ -0,0 +1,10 @@ +{ + "postsubmit": [ + { + "name": "TracingTests" + }, + { + "name": "ProtologPerfTests" + } + ] +} diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 53935e810913..8a8022c0206a 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -449,6 +449,13 @@ public final class Display { public static final int TYPE_VIRTUAL = 5; /** + * The maximum display type value. + * Helpful to get all possible display values. + * @hide + */ + public static final int TYPE_MAX = TYPE_VIRTUAL; + + /** * Display state: The display state is unknown. * * @see #getState diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 90ceb440ea5e..19e244aa5981 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -49,6 +49,7 @@ import android.gui.DropInputMode; import android.gui.StalledTransactionInfo; import android.gui.TrustedOverlay; import android.hardware.DataSpace; +import android.hardware.DisplayLuts; import android.hardware.HardwareBuffer; import android.hardware.OverlayProperties; import android.hardware.SyncFence; @@ -152,6 +153,8 @@ public final class SurfaceControl implements Parcelable { long nativeObject, int priority); private static native void nativeSetWindowCrop(long transactionObj, long nativeObject, int l, int t, int r, int b); + private static native void nativeSetCrop(long transactionObj, long nativeObject, + float l, float t, float r, float b); private static native void nativeSetCornerRadius(long transactionObj, long nativeObject, float cornerRadius); private static native void nativeSetBackgroundBlurRadius(long transactionObj, long nativeObject, @@ -305,9 +308,9 @@ public final class SurfaceControl implements Parcelable { private static native StalledTransactionInfo nativeGetStalledTransactionInfo(int pid); private static native void nativeSetDesiredPresentTimeNanos(long transactionObj, long desiredPresentTimeNanos); - private static native void nativeSetFrameTimeline(long transactionObj, - long vsyncId); private static native void nativeNotifyShutdown(); + private static native void nativeSetLuts(long transactionObj, long nativeObject, + float[] buffers, int[] slots, int[] dimensions, int[] sizes, int[] samplingKeys); /** * Transforms that can be applied to buffers as they are displayed to a window. @@ -3452,6 +3455,29 @@ public final class SurfaceControl implements Parcelable { } /** + * Bounds the surface and its children to the bounds specified. Size of the surface will be + * ignored and only the crop and buffer size will be used to determine the bounds of the + * surface. If no crop is specified and the surface has no buffer, the surface bounds is + * only constrained by the size of its parent bounds. + * + * @param sc SurfaceControl to set crop of. + * @param crop Bounds of the crop to apply. + * @return this This transaction for chaining + * @hide + */ + public @NonNull Transaction setCrop(@NonNull SurfaceControl sc, float top, float left, + float bottom, float right) { + checkPreconditions(sc); + if (SurfaceControlRegistry.sCallStackDebuggingEnabled) { + SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging( + "setCrop", this, sc, "crop={" + top + ", " + left + ", " + + bottom + ", " + right + "}"); + } + nativeSetCrop(mNativeObject, sc.mNativeObject, top, left, bottom, right); + return this; + } + + /** * Sets the corner radius of a {@link SurfaceControl}. * @param sc SurfaceControl * @param cornerRadius Corner radius in pixels. @@ -4374,6 +4400,17 @@ public final class SurfaceControl implements Parcelable { return this; } + /** @hide */ + public @NonNull Transaction setLuts(@NonNull SurfaceControl sc, + @NonNull DisplayLuts displayLuts) { + checkPreconditions(sc); + + nativeSetLuts(mNativeObject, sc.mNativeObject, displayLuts.getLutBuffers(), + displayLuts.getOffsets(), displayLuts.getLutDimensions(), + displayLuts.getLutSizes(), displayLuts.getLutSamplingKeys()); + return this; + } + /** * Sets the caching hint for the layer. By default, the caching hint is * {@link CACHING_ENABLED}. diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 40a75fdcaa06..0ca442d66e6f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -238,7 +238,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener; -import android.view.accessibility.AccessibilityManager.HighTextContrastChangeListener; +import android.view.accessibility.AccessibilityManager.HighContrastTextStateChangeListener; import android.view.accessibility.AccessibilityNodeIdManager; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; @@ -1800,8 +1800,8 @@ public final class ViewRootImpl implements ViewParent, } mAccessibilityManager.addAccessibilityStateChangeListener( mAccessibilityInteractionConnectionManager, mHandler); - mAccessibilityManager.addHighTextContrastStateChangeListener( - mHighContrastTextManager, mHandler); + mAccessibilityManager.addHighContrastTextStateChangeListener( + mExecutor, mHighContrastTextManager); DisplayManagerGlobal .getInstance() .registerDisplayListener( @@ -1838,7 +1838,7 @@ public final class ViewRootImpl implements ViewParent, private void unregisterListeners() { mAccessibilityManager.removeAccessibilityStateChangeListener( mAccessibilityInteractionConnectionManager); - mAccessibilityManager.removeHighTextContrastStateChangeListener( + mAccessibilityManager.removeHighContrastTextStateChangeListener( mHighContrastTextManager); DisplayManagerGlobal .getInstance() @@ -7531,6 +7531,7 @@ public final class ViewRootImpl implements ViewParent, if (keyEvent.isCanceled()) { animationCallback.onBackCancelled(); } else { + dispatcher.tryInvokeSystemNavigationObserverCallback(); topCallback.onBackInvoked(); } break; @@ -7538,6 +7539,7 @@ public final class ViewRootImpl implements ViewParent, } else if (topCallback != null) { if (keyEvent.getAction() == KeyEvent.ACTION_UP) { if (!keyEvent.isCanceled()) { + dispatcher.tryInvokeSystemNavigationObserverCallback(); topCallback.onBackInvoked(); } else { Log.d(mTag, "Skip onBackInvoked(), reason: keyEvent.isCanceled=true"); @@ -11907,12 +11909,12 @@ public final class ViewRootImpl implements ViewParent, } } - final class HighContrastTextManager implements HighTextContrastChangeListener { + final class HighContrastTextManager implements HighContrastTextStateChangeListener { HighContrastTextManager() { - ThreadedRenderer.setHighContrastText(mAccessibilityManager.isHighTextContrastEnabled()); + ThreadedRenderer.setHighContrastText(mAccessibilityManager.isHighContrastTextEnabled()); } @Override - public void onHighTextContrastStateChanged(boolean enabled) { + public void onHighContrastTextStateChanged(boolean enabled) { ThreadedRenderer.setHighContrastText(enabled); destroyAndInvalidate(); diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 0582afe6655d..381006c8a21b 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -1345,7 +1345,7 @@ public abstract class Window { } /** - * <p>Sets the desired about of HDR headroom to be used when rendering as a ratio of + * <p>Sets the desired amount of HDR headroom to be used when rendering as a ratio of * targetHdrPeakBrightnessInNits / targetSdrWhitePointInNits. Only applies when * {@link #setColorMode(int)} is {@link ActivityInfo#COLOR_MODE_HDR}</p> * diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 2b7cf427a562..fd57aec4180b 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -253,7 +253,7 @@ public final class AccessibilityManager { boolean mIsTouchExplorationEnabled; @UnsupportedAppUsage(trackingBug = 123768939L) - boolean mIsHighTextContrastEnabled; + boolean mIsHighContrastTextEnabled; boolean mIsAudioDescriptionByDefaultRequested; @@ -276,8 +276,8 @@ public final class AccessibilityManager { private final ArrayMap<TouchExplorationStateChangeListener, Handler> mTouchExplorationStateChangeListeners = new ArrayMap<>(); - private final ArrayMap<HighTextContrastChangeListener, Handler> - mHighTextContrastStateChangeListeners = new ArrayMap<>(); + private final ArrayMap<HighContrastTextStateChangeListener, Executor> + mHighContrastTextStateChangeListeners = new ArrayMap<>(); private final ArrayMap<AccessibilityServicesStateChangeListener, Executor> mServicesStateChangeListeners = new ArrayMap<>(); @@ -356,21 +356,20 @@ public final class AccessibilityManager { } /** - * Listener for the system high text contrast state. To listen for changes to - * the high text contrast state on the device, implement this interface and + * Listener for the system high contrast text state. To listen for changes to + * the high contrast text state on the device, implement this interface and * register it with the system by calling - * {@link #addHighTextContrastStateChangeListener}. - * - * @hide + * {@link #addHighContrastTextStateChangeListener}. */ - public interface HighTextContrastChangeListener { + @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT) + public interface HighContrastTextStateChangeListener { /** - * Called when the high text contrast enabled state changes. + * Called when the high contrast text enabled state changes. * - * @param enabled Whether high text contrast is enabled. + * @param enabled Whether high contrast text is enabled. */ - void onHighTextContrastStateChanged(boolean enabled); + void onHighContrastTextStateChanged(boolean enabled); } /** @@ -655,24 +654,23 @@ public final class AccessibilityManager { } /** - * Returns if the high text contrast in the system is enabled. + * Returns if high contrast text in the system is enabled. * <p> * <strong>Note:</strong> You need to query this only if you application is * doing its own rendering and does not rely on the platform rendering pipeline. * </p> * - * @return True if high text contrast is enabled, false otherwise. + * @return True if high contrast text is enabled, false otherwise. * - * @hide */ - @UnsupportedAppUsage - public boolean isHighTextContrastEnabled() { + @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT) + public boolean isHighContrastTextEnabled() { synchronized (mLock) { IAccessibilityManager service = getServiceLocked(); if (service == null) { return false; } - return mIsHighTextContrastEnabled; + return mIsHighContrastTextEnabled; } } @@ -1303,32 +1301,32 @@ public final class AccessibilityManager { } /** - * Registers a {@link HighTextContrastChangeListener} for changes in - * the global high text contrast state of the system. + * Registers a {@link HighContrastTextStateChangeListener} for changes in + * the global high contrast text state of the system. * - * @param listener The listener. - * - * @hide + * @param executor a executor to call the listener from + * @param listener The listener to be called */ - public void addHighTextContrastStateChangeListener( - @NonNull HighTextContrastChangeListener listener, @Nullable Handler handler) { + @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT) + public void addHighContrastTextStateChangeListener( + @NonNull @CallbackExecutor Executor executor, + @NonNull HighContrastTextStateChangeListener listener + ) { synchronized (mLock) { - mHighTextContrastStateChangeListeners - .put(listener, (handler == null) ? mHandler : handler); + mHighContrastTextStateChangeListeners.put(listener, executor); } } /** - * Unregisters a {@link HighTextContrastChangeListener}. + * Unregisters a {@link HighContrastTextStateChangeListener}. * * @param listener The listener. - * - * @hide */ - public void removeHighTextContrastStateChangeListener( - @NonNull HighTextContrastChangeListener listener) { + @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_HIGH_CONTRAST_TEXT_SMALL_TEXT_RECT) + public void removeHighContrastTextStateChangeListener( + @NonNull HighContrastTextStateChangeListener listener) { synchronized (mLock) { - mHighTextContrastStateChangeListeners.remove(listener); + mHighContrastTextStateChangeListeners.remove(listener); } } @@ -1505,13 +1503,13 @@ public final class AccessibilityManager { final boolean wasEnabled = isEnabled(); final boolean wasTouchExplorationEnabled = mIsTouchExplorationEnabled; - final boolean wasHighTextContrastEnabled = mIsHighTextContrastEnabled; + final boolean wasHighTextContrastEnabled = mIsHighContrastTextEnabled; final boolean wasAudioDescriptionByDefaultRequested = mIsAudioDescriptionByDefaultRequested; // Ensure listeners get current state from isZzzEnabled() calls. mIsEnabled = enabled; mIsTouchExplorationEnabled = touchExplorationEnabled; - mIsHighTextContrastEnabled = highTextContrastEnabled; + mIsHighContrastTextEnabled = highTextContrastEnabled; mIsAudioDescriptionByDefaultRequested = audioDescriptionEnabled; if (wasEnabled != isEnabled()) { @@ -1523,7 +1521,7 @@ public final class AccessibilityManager { } if (wasHighTextContrastEnabled != highTextContrastEnabled) { - notifyHighTextContrastStateChanged(); + notifyHighContrastTextStateChanged(); } if (wasAudioDescriptionByDefaultRequested @@ -2397,24 +2395,24 @@ public final class AccessibilityManager { } /** - * Notifies the registered {@link HighTextContrastChangeListener}s. + * Notifies the registered {@link HighContrastTextStateChangeListener}s. */ - private void notifyHighTextContrastStateChanged() { + private void notifyHighContrastTextStateChanged() { final boolean isHighTextContrastEnabled; - final ArrayMap<HighTextContrastChangeListener, Handler> listeners; + final ArrayMap<HighContrastTextStateChangeListener, Executor> listeners; synchronized (mLock) { - if (mHighTextContrastStateChangeListeners.isEmpty()) { + if (mHighContrastTextStateChangeListeners.isEmpty()) { return; } - isHighTextContrastEnabled = mIsHighTextContrastEnabled; - listeners = new ArrayMap<>(mHighTextContrastStateChangeListeners); + isHighTextContrastEnabled = mIsHighContrastTextEnabled; + listeners = new ArrayMap<>(mHighContrastTextStateChangeListeners); } final int numListeners = listeners.size(); for (int i = 0; i < numListeners; i++) { - final HighTextContrastChangeListener listener = listeners.keyAt(i); - listeners.valueAt(i).post(() -> - listener.onHighTextContrastStateChanged(isHighTextContrastEnabled)); + final HighContrastTextStateChangeListener listener = listeners.keyAt(i); + listeners.valueAt(i).execute(() -> + listener.onHighContrastTextStateChanged(isHighTextContrastEnabled)); } } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 79ecfe1e9141..1a45939f65b6 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -117,6 +117,8 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import sun.misc.Cleaner; @@ -4914,7 +4916,22 @@ public final class AutofillManager { && (root.getWindowFlags() & WindowManager.LayoutParams.FLAG_SECURE) == 0) { ViewNodeBuilder viewStructure = new ViewNodeBuilder(); viewStructure.setAutofillId(view.getAutofillId()); - view.onProvideAutofillStructure(viewStructure, /* flags= */ 0); + + // Post onProvideAutofillStructure to the UI thread + final CountDownLatch latch = new CountDownLatch(1); + afm.post( + () -> { + view.onProvideAutofillStructure(viewStructure, /* flags= */ 0); + latch.countDown(); + } + ); + try { + latch.await(5000, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return null; + } + // TODO(b/141703532): We don't call View#onProvideAutofillVirtualStructure for // efficiency reason. But this also means we will return null for virtual views // for now. We will add a new API to fetch the view node info of the virtual diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java index 806a59334689..0a83bdc35b1f 100644 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ b/core/java/android/view/inputmethod/InputMethodInfo.java @@ -860,7 +860,7 @@ public final class InputMethodInfo implements Parcelable { * <p>e.g.<pre><code>startActivity(createStylusHandwritingSettingsActivityIntent());</code> * </pre></p> * - * @attr ref R.styleable#InputMethod_stylusHandwritingSettingsActivity + * @attr ref android.R.styleable#InputMethod_stylusHandwritingSettingsActivity * @see #getSettingsActivity() * @see #supportsStylusHandwriting() */ @@ -888,8 +888,8 @@ public final class InputMethodInfo implements Parcelable { * the IME language settings activity.</p> * <p>e.g.<pre><code>startActivity(createImeLanguageSettingsActivityIntent());</code></pre></p> * - * @attr ref R.styleable#InputMethod_languageSettingsActivity - * @attr ref R.styleable#InputMethod_settingsActivity + * @attr ref android.R.styleable#InputMethod_languageSettingsActivity + * @attr ref android.R.styleable#InputMethod_settingsActivity */ @FlaggedApi(android.view.inputmethod.Flags.FLAG_IME_SWITCHER_REVAMP_API) @Nullable diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 510a92d1b2ca..3f611c7efbdd 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -3636,7 +3636,7 @@ public class ListView extends AbsListView { * Returns the drawable that will be drawn between each item in the list. * * @return the current drawable drawn between list elements - * @attr ref R.styleable#ListView_divider + * @attr ref android.R.styleable#ListView_divider */ @InspectableProperty @Nullable @@ -3651,7 +3651,7 @@ public class ListView extends AbsListView { * height, you should also call {@link #setDividerHeight(int)}. * * @param divider the drawable to use - * @attr ref R.styleable#ListView_divider + * @attr ref android.R.styleable#ListView_divider */ public void setDivider(@Nullable Drawable divider) { if (divider != null) { diff --git a/core/java/android/window/BackMotionEvent.java b/core/java/android/window/BackMotionEvent.java index 7cda3a36da95..8ac68abd8d8e 100644 --- a/core/java/android/window/BackMotionEvent.java +++ b/core/java/android/window/BackMotionEvent.java @@ -34,8 +34,6 @@ public final class BackMotionEvent implements Parcelable { private final float mTouchX; private final float mTouchY; private final float mProgress; - private final float mVelocityX; - private final float mVelocityY; private final boolean mTriggerBack; @BackEvent.SwipeEdge @@ -51,10 +49,6 @@ public final class BackMotionEvent implements Parcelable { * @param touchX Absolute X location of the touch point of this event. * @param touchY Absolute Y location of the touch point of this event. * @param progress Value between 0 and 1 on how far along the back gesture is. - * @param velocityX X velocity computed from the touch point of this event. - * Value in pixels/second. {@link Float#NaN} if was not computed. - * @param velocityY Y velocity computed from the touch point of this event. - * Value in pixels/second. {@link Float#NaN} if was not computed. * @param triggerBack Indicates whether the back arrow is in the triggered state or not * @param swipeEdge Indicates which edge the swipe starts from. * @param departingAnimationTarget The remote animation target of the departing @@ -64,16 +58,12 @@ public final class BackMotionEvent implements Parcelable { float touchX, float touchY, float progress, - float velocityX, - float velocityY, boolean triggerBack, @BackEvent.SwipeEdge int swipeEdge, @Nullable RemoteAnimationTarget departingAnimationTarget) { mTouchX = touchX; mTouchY = touchY; mProgress = progress; - mVelocityX = velocityX; - mVelocityY = velocityY; mTriggerBack = triggerBack; mSwipeEdge = swipeEdge; mDepartingAnimationTarget = departingAnimationTarget; @@ -83,8 +73,6 @@ public final class BackMotionEvent implements Parcelable { mTouchX = in.readFloat(); mTouchY = in.readFloat(); mProgress = in.readFloat(); - mVelocityX = in.readFloat(); - mVelocityY = in.readFloat(); mTriggerBack = in.readBoolean(); mSwipeEdge = in.readInt(); mDepartingAnimationTarget = in.readTypedObject(RemoteAnimationTarget.CREATOR); @@ -113,8 +101,6 @@ public final class BackMotionEvent implements Parcelable { dest.writeFloat(mTouchX); dest.writeFloat(mTouchY); dest.writeFloat(mProgress); - dest.writeFloat(mVelocityX); - dest.writeFloat(mVelocityY); dest.writeBoolean(mTriggerBack); dest.writeInt(mSwipeEdge); dest.writeTypedObject(mDepartingAnimationTarget, flags); @@ -145,24 +131,6 @@ public final class BackMotionEvent implements Parcelable { } /** - * Returns the X velocity computed from the touch point. - * - * @return value in pixels/second or {@link Float#NaN} if was not computed. - */ - public float getVelocityX() { - return mVelocityX; - } - - /** - * Returns the Y velocity computed from the touch point. - * - * @return value in pixels/second or {@link Float#NaN} if was not computed. - */ - public float getVelocityY() { - return mVelocityY; - } - - /** * Returns whether the back arrow is in the triggered state or not * * @return boolean indicating whether the back arrow is in the triggered state or not @@ -195,8 +163,6 @@ public final class BackMotionEvent implements Parcelable { + "mTouchX=" + mTouchX + ", mTouchY=" + mTouchY + ", mProgress=" + mProgress - + ", mVelocityX=" + mVelocityX - + ", mVelocityY=" + mVelocityY + ", mTriggerBack=" + mTriggerBack + ", mSwipeEdge" + mSwipeEdge + ", mDepartingAnimationTarget" + mDepartingAnimationTarget diff --git a/core/java/android/window/BackTouchTracker.java b/core/java/android/window/BackTouchTracker.java index eb23af27a24d..290c494b1bff 100644 --- a/core/java/android/window/BackTouchTracker.java +++ b/core/java/android/window/BackTouchTracker.java @@ -48,8 +48,6 @@ public class BackTouchTracker { */ private float mInitTouchX; private float mInitTouchY; - private float mLatestVelocityX; - private float mLatestVelocityY; private float mStartThresholdX; private int mSwipeEdge; private boolean mShouldUpdateStartLocation = false; @@ -58,7 +56,7 @@ public class BackTouchTracker { /** * Updates the tracker with a new motion event. */ - public void update(float touchX, float touchY, float velocityX, float velocityY) { + public void update(float touchX, float touchY) { /** * If back was previously cancelled but the user has started swiping in the forward * direction again, restart back. @@ -73,8 +71,6 @@ public class BackTouchTracker { } mLatestTouchX = touchX; mLatestTouchY = touchY; - mLatestVelocityX = velocityX; - mLatestVelocityY = velocityY; } /** Sets whether the back gesture is past the trigger threshold. */ @@ -156,8 +152,6 @@ public class BackTouchTracker { /* touchX = */ mInitTouchX, /* touchY = */ mInitTouchY, /* progress = */ 0, - /* velocityX = */ 0, - /* velocityY = */ 0, /* triggerBack = */ mTriggerBack, /* swipeEdge = */ mSwipeEdge, /* departingAnimationTarget = */ target); @@ -242,8 +236,6 @@ public class BackTouchTracker { /* touchX = */ mLatestTouchX, /* touchY = */ mLatestTouchY, /* progress = */ progress, - /* velocityX = */ mLatestVelocityX, - /* velocityY = */ mLatestVelocityY, /* triggerBack = */ mTriggerBack, /* swipeEdge = */ mSwipeEdge, /* departingAnimationTarget = */ null); diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java index 771dc7a99c0e..66c35e2fe837 100644 --- a/core/java/android/window/ImeOnBackInvokedDispatcher.java +++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java @@ -237,7 +237,7 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc try { mIOnBackInvokedCallback.onBackStarted( new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(), - backEvent.getProgress(), 0f, 0f, false, backEvent.getSwipeEdge(), + backEvent.getProgress(), false, backEvent.getSwipeEdge(), null)); } catch (RemoteException e) { Log.e(TAG, "Exception when invoking forwarded callback. e: ", e); @@ -249,7 +249,7 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc try { mIOnBackInvokedCallback.onBackProgressed( new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(), - backEvent.getProgress(), 0f, 0f, false, backEvent.getSwipeEdge(), + backEvent.getProgress(), false, backEvent.getSwipeEdge(), null)); } catch (RemoteException e) { Log.e(TAG, "Exception when invoking forwarded callback. e: ", e); diff --git a/core/java/android/window/OnBackInvokedDispatcher.java b/core/java/android/window/OnBackInvokedDispatcher.java index 0632a37a5dfb..02ed57d4be22 100644 --- a/core/java/android/window/OnBackInvokedDispatcher.java +++ b/core/java/android/window/OnBackInvokedDispatcher.java @@ -16,11 +16,14 @@ package android.window; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.SuppressLint; +import com.android.window.flags.Flags; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -43,6 +46,7 @@ public interface OnBackInvokedDispatcher { @IntDef({ PRIORITY_DEFAULT, PRIORITY_OVERLAY, + PRIORITY_SYSTEM_NAVIGATION_OBSERVER, }) @Retention(RetentionPolicy.SOURCE) @interface Priority{} @@ -67,6 +71,20 @@ public interface OnBackInvokedDispatcher { int PRIORITY_SYSTEM = -1; /** + * Priority level of {@link OnBackInvokedCallback}s designed to observe system-level back + * handling. + * + * <p>Callbacks registered with this priority do not consume back events. They receive back + * events whenever the system handles a back navigation and have no impact on the normal back + * navigation flow. Useful for logging or analytics. + * + * <p>Only one callback with {@link #PRIORITY_SYSTEM_NAVIGATION_OBSERVER} can be registered at a + * time. + */ + @FlaggedApi(Flags.FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER) + int PRIORITY_SYSTEM_NAVIGATION_OBSERVER = -2; + + /** * Registers a {@link OnBackInvokedCallback}. * * Within the same priority level, callbacks are invoked in the reverse order in which diff --git a/core/java/android/window/ProxyOnBackInvokedDispatcher.java b/core/java/android/window/ProxyOnBackInvokedDispatcher.java index 56c05b2766ec..dfc4a589f92e 100644 --- a/core/java/android/window/ProxyOnBackInvokedDispatcher.java +++ b/core/java/android/window/ProxyOnBackInvokedDispatcher.java @@ -16,6 +16,8 @@ package android.window; +import static com.android.window.flags.Flags.predictiveBackPrioritySystemNavigationObserver; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -95,7 +97,7 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { synchronized (mLock) { mCallbacks.add(Pair.create(callback, priority)); if (mActualDispatcher != null) { - if (priority <= PRIORITY_SYSTEM) { + if (priority == PRIORITY_SYSTEM) { mActualDispatcher.registerSystemOnBackInvokedCallback(callback); } else { mActualDispatcher.registerOnBackInvokedCallback(priority, callback); @@ -123,10 +125,19 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } for (Pair<OnBackInvokedCallback, Integer> callbackPair : mCallbacks) { int priority = callbackPair.second; - if (priority >= PRIORITY_DEFAULT) { - mActualDispatcher.registerOnBackInvokedCallback(priority, callbackPair.first); + if (predictiveBackPrioritySystemNavigationObserver()) { + if (priority >= PRIORITY_DEFAULT + || priority == PRIORITY_SYSTEM_NAVIGATION_OBSERVER) { + mActualDispatcher.registerOnBackInvokedCallback(priority, callbackPair.first); + } else { + mActualDispatcher.registerSystemOnBackInvokedCallback(callbackPair.first); + } } else { - mActualDispatcher.registerSystemOnBackInvokedCallback(callbackPair.first); + if (priority >= PRIORITY_DEFAULT) { + mActualDispatcher.registerOnBackInvokedCallback(priority, callbackPair.first); + } else { + mActualDispatcher.registerSystemOnBackInvokedCallback(callbackPair.first); + } } } mCallbacks.clear(); diff --git a/core/java/android/window/TaskConstants.java b/core/java/android/window/TaskConstants.java index 44bb33db6347..46bc30e2bb2d 100644 --- a/core/java/android/window/TaskConstants.java +++ b/core/java/android/window/TaskConstants.java @@ -53,25 +53,30 @@ public class TaskConstants { */ public static final int TASK_CHILD_LAYER_COMPAT_UI = TASK_CHILD_LAYER_REGION_SIZE; + /** + * Settings dialogs belonging to the task (e.g. Open by default settings dialog) + * @hide + */ + public static final int TASK_CHILD_LAYER_SETTINGS_DIALOG = 2 * TASK_CHILD_LAYER_REGION_SIZE; /** * Captions, window frames and resize handlers around task windows. * @hide */ - public static final int TASK_CHILD_LAYER_WINDOW_DECORATIONS = 2 * TASK_CHILD_LAYER_REGION_SIZE; + public static final int TASK_CHILD_LAYER_WINDOW_DECORATIONS = 3 * TASK_CHILD_LAYER_REGION_SIZE; /** * Overlays the task when going into PIP w/ gesture navigation. * @hide */ public static final int TASK_CHILD_LAYER_RECENTS_ANIMATION_PIP_OVERLAY = - 3 * TASK_CHILD_LAYER_REGION_SIZE; + 4 * TASK_CHILD_LAYER_REGION_SIZE; /** * Allows other apps to add overlays on the task (i.e. game dashboard) * @hide */ - public static final int TASK_CHILD_LAYER_TASK_OVERLAY = 4 * TASK_CHILD_LAYER_REGION_SIZE; + public static final int TASK_CHILD_LAYER_TASK_OVERLAY = 5 * TASK_CHILD_LAYER_REGION_SIZE; /** @@ -95,6 +100,7 @@ public class TaskConstants { TASK_CHILD_LAYER_TASK_BACKGROUND, TASK_CHILD_LAYER_LETTERBOX_BACKGROUND, TASK_CHILD_LAYER_COMPAT_UI, + TASK_CHILD_LAYER_SETTINGS_DIALOG, TASK_CHILD_LAYER_WINDOW_DECORATIONS, TASK_CHILD_LAYER_RECENTS_ANIMATION_PIP_OVERLAY, TASK_CHILD_LAYER_TASK_OVERLAY, diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java index 314bf8985cb4..0dc9263e990d 100644 --- a/core/java/android/window/WindowContainerTransaction.java +++ b/core/java/android/window/WindowContainerTransaction.java @@ -28,6 +28,7 @@ import static android.window.TaskFragmentOperation.OP_TYPE_START_ACTIVITY_IN_TAS import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.TestApi; import android.app.PendingIntent; import android.app.WindowConfiguration; @@ -44,6 +45,7 @@ import android.util.ArrayMap; import android.view.InsetsFrameProvider; import android.view.InsetsSource; import android.view.SurfaceControl; +import android.view.WindowInsets; import android.view.WindowInsets.Type.InsetsType; import com.android.window.flags.Flags; @@ -267,6 +269,23 @@ public final class WindowContainerTransaction implements Parcelable { } /** + * Sets whether the IME insets should be excluded by {@link com.android.server.wm.InsetsPolicy}. + * @hide + */ + @SuppressLint("UnflaggedApi") + @NonNull + public WindowContainerTransaction setExcludeImeInsets( + @NonNull WindowContainerToken container, boolean exclude) { + final HierarchyOp hierarchyOp = + new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES) + .setContainer(container.asBinder()) + .setExcludeInsetsTypes(exclude ? WindowInsets.Type.ime() : 0) + .build(); + mHierarchyOps.add(hierarchyOp); + return this; + } + + /** * Sets whether a container or its children should be hidden. When {@code false}, the existing * visibility of the container applies, but when {@code true} the container will be forced * to be hidden. @@ -1449,6 +1468,7 @@ public final class WindowContainerTransaction implements Parcelable { public static final int HIERARCHY_OP_TYPE_MOVE_PIP_ACTIVITY_TO_PINNED_TASK = 18; public static final int HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE = 19; public static final int HIERARCHY_OP_TYPE_RESTORE_BACK_NAVIGATION = 20; + public static final int HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES = 21; // The following key(s) are for use with mLaunchOptions: // When launching a task (eg. from recents), this is the taskId to be launched. @@ -1512,6 +1532,8 @@ public final class WindowContainerTransaction implements Parcelable { private boolean mIsTrimmableFromRecents; + private @InsetsType int mExcludeInsetsTypes; + public static HierarchyOp createForReparent( @NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) { return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REPARENT) @@ -1649,6 +1671,7 @@ public final class WindowContainerTransaction implements Parcelable { mAlwaysOnTop = copy.mAlwaysOnTop; mReparentLeafTaskIfRelaunch = copy.mReparentLeafTaskIfRelaunch; mIsTrimmableFromRecents = copy.mIsTrimmableFromRecents; + mExcludeInsetsTypes = copy.mExcludeInsetsTypes; } protected HierarchyOp(Parcel in) { @@ -1671,6 +1694,7 @@ public final class WindowContainerTransaction implements Parcelable { mAlwaysOnTop = in.readBoolean(); mReparentLeafTaskIfRelaunch = in.readBoolean(); mIsTrimmableFromRecents = in.readBoolean(); + mExcludeInsetsTypes = in.readInt(); } public int getType() { @@ -1772,6 +1796,10 @@ public final class WindowContainerTransaction implements Parcelable { return mIsTrimmableFromRecents; } + public @InsetsType int getExcludeInsetsTypes() { + return mExcludeInsetsTypes; + } + /** Gets a string representation of a hierarchy-op type. */ public static String hopToString(int type) { switch (type) { @@ -1795,6 +1823,7 @@ public final class WindowContainerTransaction implements Parcelable { return "setReparentLeafTaskIfRelaunch"; case HIERARCHY_OP_TYPE_ADD_TASK_FRAGMENT_OPERATION: return "addTaskFragmentOperation"; + case HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES: return "setExcludeInsetsTypes"; default: return "HOP(" + type + ")"; } } @@ -1868,6 +1897,11 @@ public final class WindowContainerTransaction implements Parcelable { sb.append("fragmentToken= ").append(mContainer) .append(" operation= ").append(mTaskFragmentOperation); break; + case HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES: + sb.append("container= ").append(mContainer) + .append(" mExcludeInsetsTypes= ") + .append(WindowInsets.Type.toString(mExcludeInsetsTypes)); + break; case HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE: sb.append("container= ").append(mContainer) .append(" isTrimmable= ") @@ -1903,6 +1937,7 @@ public final class WindowContainerTransaction implements Parcelable { dest.writeBoolean(mAlwaysOnTop); dest.writeBoolean(mReparentLeafTaskIfRelaunch); dest.writeBoolean(mIsTrimmableFromRecents); + dest.writeInt(mExcludeInsetsTypes); } @Override @@ -1974,6 +2009,8 @@ public final class WindowContainerTransaction implements Parcelable { private boolean mIsTrimmableFromRecents; + private @InsetsType int mExcludeInsetsTypes; + Builder(int type) { mType = type; } @@ -2069,6 +2106,11 @@ public final class WindowContainerTransaction implements Parcelable { return this; } + Builder setExcludeInsetsTypes(@InsetsType int excludeInsetsTypes) { + mExcludeInsetsTypes = excludeInsetsTypes; + return this; + } + HierarchyOp build() { final HierarchyOp hierarchyOp = new HierarchyOp(mType); hierarchyOp.mContainer = mContainer; @@ -2093,6 +2135,7 @@ public final class WindowContainerTransaction implements Parcelable { hierarchyOp.mIncludingParents = mIncludingParents; hierarchyOp.mReparentLeafTaskIfRelaunch = mReparentLeafTaskIfRelaunch; hierarchyOp.mIsTrimmableFromRecents = mIsTrimmableFromRecents; + hierarchyOp.mExcludeInsetsTypes = mExcludeInsetsTypes; return hierarchyOp; } diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java index bb89a2499838..44a374fb7c20 100644 --- a/core/java/android/window/WindowOnBackInvokedDispatcher.java +++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java @@ -16,6 +16,8 @@ package android.window; +import static com.android.window.flags.Flags.predictiveBackPrioritySystemNavigationObserver; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; @@ -103,6 +105,9 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { public final TreeMap<Integer, ArrayList<OnBackInvokedCallback>> mOnBackInvokedCallbacks = new TreeMap<>(); + @VisibleForTesting + public OnBackInvokedCallback mSystemNavigationObserverCallback = null; + private Checker mChecker; private final Object mLock = new Object(); // The threshold for back swipe full progress. @@ -119,7 +124,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { if (!isBackGestureInProgress() || ev == null || ev.getAction() != MotionEvent.ACTION_MOVE) { return; } - mTouchTracker.update(ev.getX(), ev.getY(), Float.NaN, Float.NaN); + mTouchTracker.update(ev.getX(), ev.getY()); if (mTouchTracker.shouldUpdateStartLocation()) { // Reset the start location on the first event after starting back, so that // the beginning of the animation feels smooth. @@ -170,6 +175,20 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } } + private void registerSystemNavigationObserverCallback(@NonNull OnBackInvokedCallback callback) { + synchronized (mLock) { + // If callback has already been added as regular callback, remove it. + if (mAllCallbacks.containsKey(callback)) { + if (DEBUG) { + Log.i(TAG, "Callback already added. Removing and re-adding it as " + + "system-navigation-observer-callback."); + } + removeCallbackInternal(callback); + } + mSystemNavigationObserverCallback = callback; + } + } + /** * Register a callback bypassing platform checks. This is used to register compatibility * callbacks. @@ -181,6 +200,12 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { mImeDispatcher.registerOnBackInvokedCallback(priority, callback); return; } + if (predictiveBackPrioritySystemNavigationObserver()) { + if (priority == PRIORITY_SYSTEM_NAVIGATION_OBSERVER) { + registerSystemNavigationObserverCallback(callback); + return; + } + } if (callback instanceof ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback) { if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback && mImeBackAnimationController != null) { @@ -202,6 +227,13 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { Integer prevPriority = mAllCallbacks.get(callback); mOnBackInvokedCallbacks.get(prevPriority).remove(callback); } + if (mSystemNavigationObserverCallback == callback) { + mSystemNavigationObserverCallback = null; + if (DEBUG) { + Log.i(TAG, "Callback already registered (as system-navigation-observer " + + "callback). Removing and re-adding it."); + } + } OnBackInvokedCallback previousTopCallback = getTopCallback(); callbacks.add(callback); @@ -221,6 +253,10 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { mImeDispatcher.unregisterOnBackInvokedCallback(callback); return; } + if (mSystemNavigationObserverCallback == callback) { + mSystemNavigationObserverCallback = null; + return; + } if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback) { callback = mImeBackAnimationController; } @@ -230,25 +266,29 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } return; } - OnBackInvokedCallback previousTopCallback = getTopCallback(); - Integer priority = mAllCallbacks.get(callback); - ArrayList<OnBackInvokedCallback> callbacks = mOnBackInvokedCallbacks.get(priority); - callbacks.remove(callback); - if (callbacks.isEmpty()) { - mOnBackInvokedCallbacks.remove(priority); - } - mAllCallbacks.remove(callback); - // Re-populate the top callback to WM if the removed callback was previously the top - // one. - if (previousTopCallback == callback) { - // We should call onBackCancelled() when an active callback is removed from - // dispatcher. - mProgressAnimator.removeOnBackCancelledFinishCallback(); - mProgressAnimator.removeOnBackInvokedFinishCallback(); - sendCancelledIfInProgress(callback); - mHandler.post(mProgressAnimator::reset); - setTopOnBackInvokedCallback(getTopCallback()); - } + removeCallbackInternal(callback); + } + } + + private void removeCallbackInternal(@NonNull OnBackInvokedCallback callback) { + OnBackInvokedCallback previousTopCallback = getTopCallback(); + Integer priority = mAllCallbacks.get(callback); + ArrayList<OnBackInvokedCallback> callbacks = mOnBackInvokedCallbacks.get(priority); + callbacks.remove(callback); + if (callbacks.isEmpty()) { + mOnBackInvokedCallbacks.remove(priority); + } + mAllCallbacks.remove(callback); + // Re-populate the top callback to WM if the removed callback was previously the top + // one. + if (previousTopCallback == callback) { + // We should call onBackCancelled() when an active callback is removed from + // dispatcher. + mProgressAnimator.removeOnBackCancelledFinishCallback(); + mProgressAnimator.removeOnBackInvokedFinishCallback(); + sendCancelledIfInProgress(callback); + mHandler.post(mProgressAnimator::reset); + setTopOnBackInvokedCallback(getTopCallback()); } } @@ -304,6 +344,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { mHandler.post(mProgressAnimator::reset); mAllCallbacks.clear(); mOnBackInvokedCallbacks.clear(); + mSystemNavigationObserverCallback = null; } } @@ -315,6 +356,25 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } } + /** + * Tries to call {@link OnBackInvokedCallback#onBackInvoked} on the system navigation observer + * callback (if one is set and if the top-most regular callback has + * {@link OnBackInvokedDispatcher#PRIORITY_SYSTEM}) + */ + public void tryInvokeSystemNavigationObserverCallback() { + OnBackInvokedCallback topCallback = getTopCallback(); + Integer callbackPriority = mAllCallbacks.getOrDefault(topCallback, null); + if (callbackPriority != null && callbackPriority == PRIORITY_SYSTEM) { + invokeSystemNavigationObserverCallback(); + } + } + + private void invokeSystemNavigationObserverCallback() { + if (mSystemNavigationObserverCallback != null) { + mSystemNavigationObserverCallback.onBackInvoked(); + } + } + private void setTopOnBackInvokedCallback(@Nullable OnBackInvokedCallback callback) { if (mWindowSession == null || mWindow == null) { return; @@ -324,7 +384,9 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { if (callback != null) { int priority = mAllCallbacks.get(callback); final IOnBackInvokedCallback iCallback = new OnBackInvokedCallbackWrapper(callback, - mTouchTracker, mProgressAnimator, mHandler, this::callOnKeyPreIme); + mTouchTracker, mProgressAnimator, mHandler, this::callOnKeyPreIme, + this::invokeSystemNavigationObserverCallback, + /*isSystemCallback*/ priority == PRIORITY_SYSTEM); callbackInfo = new OnBackInvokedCallbackInfo( iCallback, priority, @@ -416,18 +478,26 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { private final Handler mHandler; @NonNull private final BooleanSupplier mOnKeyPreIme; + @NonNull + private final Runnable mSystemNavigationObserverCallbackRunnable; + private final boolean mIsSystemCallback; OnBackInvokedCallbackWrapper( @NonNull OnBackInvokedCallback callback, @NonNull BackTouchTracker touchTracker, @NonNull BackProgressAnimator progressAnimator, @NonNull Handler handler, - @NonNull BooleanSupplier onKeyPreIme) { + @NonNull BooleanSupplier onKeyPreIme, + @NonNull Runnable systemNavigationObserverCallbackRunnable, + boolean isSystemCallback + ) { mCallback = new WeakReference<>(callback); mTouchTracker = touchTracker; mProgressAnimator = progressAnimator; mHandler = handler; mOnKeyPreIme = onKeyPreIme; + mSystemNavigationObserverCallbackRunnable = systemNavigationObserverCallbackRunnable; + mIsSystemCallback = isSystemCallback; } @Override @@ -494,9 +564,17 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { OnBackAnimationCallback animationCallback = getBackAnimationCallback(); if (animationCallback != null && !(callback instanceof ImeBackAnimationController)) { - mProgressAnimator.onBackInvoked(callback::onBackInvoked); + mProgressAnimator.onBackInvoked(() -> { + if (mIsSystemCallback) { + mSystemNavigationObserverCallbackRunnable.run(); + } + callback.onBackInvoked(); + }); } else { mProgressAnimator.reset(); + if (mIsSystemCallback) { + mSystemNavigationObserverCallbackRunnable.run(); + } callback.onBackInvoked(); } }); @@ -597,9 +675,18 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { + " application manifest."); return false; } - if (priority < 0) { - throw new IllegalArgumentException("Application registered OnBackInvokedCallback " - + "cannot have negative priority. Priority: " + priority); + if (predictiveBackPrioritySystemNavigationObserver()) { + if (priority < 0 && priority != PRIORITY_SYSTEM_NAVIGATION_OBSERVER) { + throw new IllegalArgumentException("Application registered " + + "OnBackInvokedCallback cannot have negative priority. Priority: " + + priority); + } + } else { + if (priority < 0) { + throw new IllegalArgumentException("Application registered " + + "OnBackInvokedCallback cannot have negative priority. Priority: " + + priority); + } } Objects.requireNonNull(callback); return true; diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig index 70ac12f07a23..b22aa222d1de 100644 --- a/core/java/android/window/flags/lse_desktop_experience.aconfig +++ b/core/java/android/window/flags/lse_desktop_experience.aconfig @@ -162,6 +162,13 @@ flag { } flag { + name: "enable_a11y_metrics" + namespace: "lse_desktop_experience" + description: "Whether to enable log collection for a11y actions in desktop windowing mode" + bug: "341319597" +} + +flag { name: "enable_caption_compat_inset_force_consumption" namespace: "lse_desktop_experience" description: "Enables force-consumption of caption bar insets for immersive apps in freeform" diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig index 086063f3887c..c9b93c95e0c1 100644 --- a/core/java/android/window/flags/windowing_frontend.aconfig +++ b/core/java/android/window/flags/windowing_frontend.aconfig @@ -307,3 +307,11 @@ flag { bug: "364930619" is_fixed_read_only: true } + +flag { + name: "predictive_back_priority_system_navigation_observer" + namespace: "systemui" + description: "PRIORITY_SYSTEM_NAVIGATION_OBSERVER predictive back API extension" + is_fixed_read_only: true + bug: "362938401" +} diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java index fef5e83cecca..4aebde536dcf 100644 --- a/core/java/com/android/internal/notification/SystemNotificationChannels.java +++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java @@ -26,6 +26,7 @@ import android.media.AudioAttributes; import android.os.RemoteException; import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Arrays; @@ -37,38 +38,40 @@ public class SystemNotificationChannels { * @deprecated Legacy system channel, which is no longer used, */ @Deprecated public static String VIRTUAL_KEYBOARD = "VIRTUAL_KEYBOARD"; - public static String PHYSICAL_KEYBOARD = "PHYSICAL_KEYBOARD"; - public static String SECURITY = "SECURITY"; - public static String CAR_MODE = "CAR_MODE"; - public static String ACCOUNT = "ACCOUNT"; - public static String DEVELOPER = "DEVELOPER"; - public static String DEVELOPER_IMPORTANT = "DEVELOPER_IMPORTANT"; - public static String UPDATES = "UPDATES"; - public static String NETWORK_STATUS = "NETWORK_STATUS"; - public static String NETWORK_ALERTS = "NETWORK_ALERTS"; - public static String NETWORK_AVAILABLE = "NETWORK_AVAILABLE"; - public static String VPN = "VPN"; + public static final String PHYSICAL_KEYBOARD = "PHYSICAL_KEYBOARD"; + public static final String SECURITY = "SECURITY"; + public static final String CAR_MODE = "CAR_MODE"; + public static final String ACCOUNT = "ACCOUNT"; + public static final String DEVELOPER = "DEVELOPER"; + public static final String DEVELOPER_IMPORTANT = "DEVELOPER_IMPORTANT"; + public static final String UPDATES = "UPDATES"; + public static final String NETWORK_STATUS = "NETWORK_STATUS"; + public static final String NETWORK_ALERTS = "NETWORK_ALERTS"; + public static final String NETWORK_AVAILABLE = "NETWORK_AVAILABLE"; + public static final String VPN = "VPN"; /** * @deprecated Legacy device admin channel with low importance which is no longer used, * Use the high importance {@link #DEVICE_ADMIN} channel instead. */ - @Deprecated public static String DEVICE_ADMIN_DEPRECATED = "DEVICE_ADMIN"; - public static String DEVICE_ADMIN = "DEVICE_ADMIN_ALERTS"; - public static String ALERTS = "ALERTS"; - public static String RETAIL_MODE = "RETAIL_MODE"; - public static String USB = "USB"; - public static String FOREGROUND_SERVICE = "FOREGROUND_SERVICE"; - public static String HEAVY_WEIGHT_APP = "HEAVY_WEIGHT_APP"; + @Deprecated public static final String DEVICE_ADMIN_DEPRECATED = "DEVICE_ADMIN"; + public static final String DEVICE_ADMIN = "DEVICE_ADMIN_ALERTS"; + public static final String ALERTS = "ALERTS"; + public static final String RETAIL_MODE = "RETAIL_MODE"; + public static final String USB = "USB"; + public static final String FOREGROUND_SERVICE = "FOREGROUND_SERVICE"; + public static final String HEAVY_WEIGHT_APP = "HEAVY_WEIGHT_APP"; /** * @deprecated Legacy system changes channel with low importance which is no longer used, * Use the default importance {@link #SYSTEM_CHANGES} channel instead. */ - @Deprecated public static String SYSTEM_CHANGES_DEPRECATED = "SYSTEM_CHANGES"; - public static String SYSTEM_CHANGES = "SYSTEM_CHANGES_ALERTS"; - public static String DO_NOT_DISTURB = "DO_NOT_DISTURB"; - public static String ACCESSIBILITY_MAGNIFICATION = "ACCESSIBILITY_MAGNIFICATION"; - public static String ACCESSIBILITY_SECURITY_POLICY = "ACCESSIBILITY_SECURITY_POLICY"; - public static String ABUSIVE_BACKGROUND_APPS = "ABUSIVE_BACKGROUND_APPS"; + @Deprecated public static final String SYSTEM_CHANGES_DEPRECATED = "SYSTEM_CHANGES"; + public static final String SYSTEM_CHANGES = "SYSTEM_CHANGES_ALERTS"; + public static final String ACCESSIBILITY_MAGNIFICATION = "ACCESSIBILITY_MAGNIFICATION"; + public static final String ACCESSIBILITY_SECURITY_POLICY = "ACCESSIBILITY_SECURITY_POLICY"; + public static final String ABUSIVE_BACKGROUND_APPS = "ABUSIVE_BACKGROUND_APPS"; + + @VisibleForTesting + static final String OBSOLETE_DO_NOT_DISTURB = "DO_NOT_DISTURB"; public static void createAll(Context context) { final NotificationManager nm = context.getSystemService(NotificationManager.class); @@ -193,11 +196,6 @@ public class SystemNotificationChannels { .build()); channelsList.add(systemChanges); - NotificationChannel dndChanges = new NotificationChannel(DO_NOT_DISTURB, - context.getString(R.string.notification_channel_do_not_disturb), - NotificationManager.IMPORTANCE_LOW); - channelsList.add(dndChanges); - final NotificationChannel newFeaturePrompt = new NotificationChannel( ACCESSIBILITY_MAGNIFICATION, context.getString(R.string.notification_channel_accessibility_magnification), @@ -218,6 +216,9 @@ public class SystemNotificationChannels { channelsList.add(abusiveBackgroundAppsChannel); nm.createNotificationChannels(channelsList); + + // Delete channels created by previous Android versions that are no longer used. + nm.deleteNotificationChannel(OBSOLETE_DO_NOT_DISTURB); } private static String getDeviceAdminNotificationChannelName(Context context) { diff --git a/core/java/com/android/internal/protolog/TEST_MAPPING b/core/java/com/android/internal/protolog/TEST_MAPPING index 37d57eed8cf4..b51d19da97a5 100644 --- a/core/java/com/android/internal/protolog/TEST_MAPPING +++ b/core/java/com/android/internal/protolog/TEST_MAPPING @@ -1,6 +1,9 @@ { "postsubmit": [ { + "name": "TracingTests" + }, + { "name": "ProtologPerfTests" } ] diff --git a/core/java/com/android/internal/widget/NotificationProgressDrawable.java b/core/java/com/android/internal/widget/NotificationProgressDrawable.java new file mode 100644 index 000000000000..4d88546a1bd8 --- /dev/null +++ b/core/java/com/android/internal/widget/NotificationProgressDrawable.java @@ -0,0 +1,722 @@ +/* + * 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; + +import android.content.pm.ActivityInfo.Config; +import android.content.res.Resources; +import android.content.res.Resources.Theme; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.DashPathEffect; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.Log; + +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.internal.R; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; + +/** + * This is used by NotificationProgressBar for displaying a custom background. It composes of + * segments, which have non-zero length, and points, which have zero length. + * + * @see Segment + * @see Point + */ +public final class NotificationProgressDrawable extends Drawable { + private static final String TAG = "NotifProgressDrawable"; + + private State mState; + private boolean mMutated; + + private final ArrayList<Part> mParts = new ArrayList<>(); + + private final Rect mPointRect = new Rect(); + private final RectF mPointRectF = new RectF(); + + private final Paint mStrokePaint = new Paint(); + private final Paint mDashedStrokePaint = new Paint(); + private final Paint mFillPaint = new Paint(); + + { + mStrokePaint.setStyle(Paint.Style.STROKE); + mStrokePaint.setStrokeCap(Paint.Cap.ROUND); + + mDashedStrokePaint.setStyle(Paint.Style.STROKE); + + mFillPaint.setStyle(Paint.Style.FILL); + } + + private int mAlpha; + + public NotificationProgressDrawable() { + this(new State(), null); + } + + /** + * <p>Set the stroke width and default color for the drawable.</p> + * <p>Note: changing this property will affect all instances of a drawable loaded from a + * resource. It is recommended to invoke + * {@link #mutate()} before changing this property.</p> + * + * @param width The width in pixels of the stroke + * @param color The color of the stroke + * @see #mutate() + * @see #setStroke(int, int, float, float) + */ + public void setStroke(int width, @ColorInt int color) { + setStroke(width, color, 0, 0); + } + + /** + * <p>Set the stroke width and default color for the drawable. This method can also be used + * to dash the stroke for the dashed segments.</p> + * <p>Note: changing this property will affect all instances of a drawable loaded from a + * resource. It is recommended to invoke {@link #mutate()} before changing this property.</p> + * + * @param width The width in pixels of the stroke + * @param color The color of the stroke + * @param dashWidth The length in pixels of the dashes, set to 0 to disable dashes + * @param dashGap The gap in pixels between dashes + * @see #mutate() + * @see #setStroke(int, int) + */ + public void setStroke(int width, @ColorInt int color, float dashWidth, float dashGap) { + mState.setStroke(width, color, dashWidth, dashGap); + setStrokeInternal(width, dashWidth, dashGap); + } + + /** + * <p>Set the stroke default color for the drawable.</p> + * <p>Note: changing this property will affect all instances of a drawable loaded from a + * resource. It is recommended to invoke {@link #mutate()} before changing this property.</p> + * + * @param color The color of the stroke + * @see #mutate() + * @see #setStroke(int, int, float, float) + */ + public void setStrokeDefaultColor(@ColorInt int color) { + mState.mStrokeColor = color; + } + + /** + * <p>Set the point rect default color for the drawable.</p> + * <p>Note: changing this property will affect all instances of a drawable loaded from a + * resource. It is recommended to invoke {@link #mutate()} before changing this property.</p> + * + * @param color The color of the point rect + * @see #mutate() + */ + public void setPointRectDefaultColor(@ColorInt int color) { + mState.mPointRectColor = color; + } + + private void setStrokeInternal(int width, float dashWidth, float dashGap) { + mStrokePaint.setStrokeWidth(width); + + mDashedStrokePaint.setStrokeWidth(width); + DashPathEffect e = null; + if (dashWidth > 0) { + e = new DashPathEffect(new float[] { dashWidth, dashGap }, 0); + } + mDashedStrokePaint.setPathEffect(e); + + invalidateSelf(); + } + + /** + * + */ + public void setParts(@NonNull Part... parts) { + mParts.clear(); + mParts.addAll(Arrays.asList(parts)); + } + + @Override + public void draw(@NonNull Canvas canvas) { + final float pointRadius = + mState.mPointRadius; // how big the point icon will be, halved + + // generally, we will start drawing at (x, y) and end at (x+w, y) + float x = (float) getBounds().left; + final float centerY = (float) getBounds().centerY(); + final float totalWidth = (float) getBounds().width(); + + final int numParts = mParts.size(); + for (int iPart = 0; iPart < numParts; iPart++) { + final Part part = mParts.get(iPart); + final Part prevPart = iPart == 0 ? null : mParts.get(iPart - 1); + final Part nextPart = iPart + 1 == numParts ? null : mParts.get(iPart + 1); + if (part instanceof Segment segment) { + final float segWidth = segment.mFraction * totalWidth; + // Advance the start position to account for a point immediately prior. + final float startOffset = getSegStartOffset(prevPart, pointRadius, + mState.mSegPointGap); + final float start = x + startOffset; + // Retract the end position to account for the padding and a point immediately + // after. + final float endOffset = getSegEndOffset(nextPart, pointRadius, mState.mSegPointGap, + mState.mSegSegGap); + final float end = x + segWidth - endOffset; + + // Transparent is not allowed (and also is the default in the data), so use that + // as a sentinel to be replaced by default + mStrokePaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor + : mState.mStrokeColor); + mDashedStrokePaint.setColor(segment.mColor != Color.TRANSPARENT ? segment.mColor + : mState.mStrokeColor); + + // Leave space for the rounded line cap which extends beyond start/end. + final float capWidth = mStrokePaint.getStrokeWidth() / 2F; + + canvas.drawLine(start + capWidth, centerY, end - capWidth, centerY, + segment.mDashed ? mDashedStrokePaint : mStrokePaint); + + // Advance the current position to account for the segment's fraction of the total + // width (ignoring offset and padding) + x += segWidth; + } else if (part instanceof Point point) { + mPointRect.set((int) (x - pointRadius), (int) (centerY - pointRadius), + (int) (x + pointRadius), (int) (centerY + pointRadius)); + if (point.mIcon != null) { + point.mIcon.setBounds(mPointRect); + point.mIcon.draw(canvas); + } else { + // TODO: b/367804171 - actually use a vector asset for the default point + // rather than drawing it as a box? + mPointRectF.set(mPointRect); + final float inset = mState.mPointRectInset; + final float cornerRadius = mState.mPointRectCornerRadius; + mPointRectF.inset(inset, inset); + + mFillPaint.setColor(point.mColor != Color.TRANSPARENT ? point.mColor + : mState.mPointRectColor); + + canvas.drawRoundRect(mPointRectF, cornerRadius, cornerRadius, mFillPaint); + } + } + } + } + + private static float getSegStartOffset(Part prevPart, float pointRadius, float segPointGap) { + return (prevPart instanceof Point) ? pointRadius + segPointGap : 0F; + } + + private static float getSegEndOffset(Part nextPart, float pointRadius, float segPointGap, + float segSegGap) { + if (nextPart == null) return 0F; + return (nextPart instanceof Point) ? segPointGap + pointRadius : segSegGap; + } + + @Override + public @Config int getChangingConfigurations() { + return super.getChangingConfigurations() | mState.getChangingConfigurations(); + } + + @Override + public void setAlpha(int alpha) { + if (mAlpha != alpha) { + mAlpha = alpha; + invalidateSelf(); + } + } + + @Override + public int getAlpha() { + return mAlpha; + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + // NO-OP + } + + @Override + public int getOpacity() { + // This method is deprecated. Hence we return UNKNOWN. + return PixelFormat.UNKNOWN; + } + + @Override + public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser, + @NonNull AttributeSet attrs, @Nullable Resources.Theme theme) + throws XmlPullParserException, IOException { + super.inflate(r, parser, attrs, theme); + + mState.setDensity(resolveDensity(r, 0)); + + final TypedArray a = obtainAttributes(r, theme, attrs, + R.styleable.NotificationProgressDrawable); + updateStateFromTypedArray(a); + a.recycle(); + + inflateChildElements(r, parser, attrs, theme); + + updateLocalState(); + } + + @Override + public void applyTheme(@NonNull Theme t) { + super.applyTheme(t); + + final State state = mState; + if (state == null) { + return; + } + + state.setDensity(resolveDensity(t.getResources(), 0)); + + if (state.mThemeAttrs != null) { + final TypedArray a = t.resolveAttributes( + state.mThemeAttrs, R.styleable.NotificationProgressDrawable); + updateStateFromTypedArray(a); + a.recycle(); + } + + applyThemeChildElements(t); + + updateLocalState(); + } + + @Override + public boolean canApplyTheme() { + return (mState.canApplyTheme()) || super.canApplyTheme(); + } + + private void updateStateFromTypedArray(TypedArray a) { + final State state = mState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mThemeAttrs = a.extractThemeAttrs(); + + state.mSegSegGap = a.getDimension(R.styleable.NotificationProgressDrawable_segSegGap, + state.mSegSegGap); + state.mSegPointGap = a.getDimension(R.styleable.NotificationProgressDrawable_segPointGap, + state.mSegPointGap); + } + + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { + TypedArray a; + int type; + + final int innerDepth = parser.getDepth() + 1; + int depth; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && ((depth = parser.getDepth()) >= innerDepth + || type != XmlPullParser.END_TAG)) { + if (type != XmlPullParser.START_TAG) { + continue; + } + + if (depth > innerDepth) { + continue; + } + + String name = parser.getName(); + + if (name.equals("segments")) { + a = obtainAttributes(r, theme, attrs, + R.styleable.NotificationProgressDrawableSegments); + updateSegmentsFromTypedArray(a); + a.recycle(); + } else if (name.equals("points")) { + a = obtainAttributes(r, theme, attrs, + R.styleable.NotificationProgressDrawablePoints); + updatePointsFromTypedArray(a); + a.recycle(); + } else { + Log.w(TAG, "Bad element under NotificationProgressDrawable: " + name); + } + } + } + + private void applyThemeChildElements(Theme t) { + final State state = mState; + + if (state.mThemeAttrsSegments != null) { + final TypedArray a = t.resolveAttributes( + state.mThemeAttrsSegments, R.styleable.NotificationProgressDrawableSegments); + updateSegmentsFromTypedArray(a); + a.recycle(); + } + + if (state.mThemeAttrsPoints != null) { + final TypedArray a = t.resolveAttributes( + state.mThemeAttrsPoints, R.styleable.NotificationProgressDrawablePoints); + updateSegmentsFromTypedArray(a); + a.recycle(); + } + } + + private void updateSegmentsFromTypedArray(TypedArray a) { + final State state = mState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mThemeAttrsSegments = a.extractThemeAttrs(); + + final int width = a.getDimensionPixelSize( + R.styleable.NotificationProgressDrawableSegments_width, state.mStrokeWidth); + final float dashWidth = a.getDimension( + R.styleable.NotificationProgressDrawableSegments_dashWidth, state.mStrokeDashWidth); + + final int color = a.getColor(R.styleable.NotificationProgressDrawableSegments_color, + state.mStrokeColor); + + if (dashWidth != 0.0f) { + final float dashGap = a.getDimension( + R.styleable.NotificationProgressDrawableSegments_dashGap, state.mStrokeDashGap); + setStroke(width, color, dashWidth, dashGap); + } else { + setStroke(width, color); + } + } + + private void updatePointsFromTypedArray(TypedArray a) { + final State state = mState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mThemeAttrsPoints = a.extractThemeAttrs(); + + state.mPointRadius = a.getDimension(R.styleable.NotificationProgressDrawablePoints_radius, + state.mPointRadius); + state.mPointRectInset = a.getDimension(R.styleable.NotificationProgressDrawablePoints_inset, + state.mPointRectInset); + state.mPointRectCornerRadius = a.getDimension( + R.styleable.NotificationProgressDrawablePoints_cornerRadius, + state.mPointRectCornerRadius); + state.mPointRectColor = a.getColor(R.styleable.NotificationProgressDrawablePoints_color, + state.mPointRectColor); + } + + static int resolveDensity(@Nullable Resources r, int parentDensity) { + final int densityDpi = r == null ? parentDensity : r.getDisplayMetrics().densityDpi; + return densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi; + } + + /** + * Scales a floating-point pixel value from the source density to the + * target density. + */ + private static float scaleFromDensity(float pixels, int sourceDensity, int targetDensity) { + return pixels * targetDensity / sourceDensity; + } + + /** + * Scales a pixel value from the source density to the target density. + * <p> + * Optionally, when {@code isSize} is true, handles the resulting pixel value as a size, + * which is rounded to the closest positive integer. + * <p> + * Note: Iteratively applying density changes could result in drift of the pixel values due + * to rounding, especially for paddings which are truncated. Therefore it should be avoided. + * This isn't an issue for the notifications because the inflation pipeline reinflates + * notification views on density change. + */ + private static int scaleFromDensity( + int pixels, int sourceDensity, int targetDensity, boolean isSize) { + if (pixels == 0 || sourceDensity == targetDensity) { + return pixels; + } + + final float result = pixels * targetDensity / (float) sourceDensity; + if (!isSize) { + return (int) result; + } + + final int rounded = Math.round(result); + if (rounded != 0) { + return rounded; + } else if (pixels > 0) { + return 1; + } else { + return -1; + } + } + + /** + * A part of the progress bar, which is either a S{@link Segment} with non-zero length, or a + * {@link Point} with zero length. + */ + public interface Part { + + } + + /** + * A segment is a part of the progress bar with non-zero length. For example, it can + * represent a portion in a navigation journey with certain traffic condition. + */ + public static final class Segment implements Part { + private final float mFraction; + @ColorInt private final int mColor; + private final boolean mDashed; + + public Segment(float fraction) { + this(fraction, Color.TRANSPARENT); + } + + public Segment(float fraction, @ColorInt int color) { + this(fraction, color, false); + } + + public Segment(float fraction, @ColorInt int color, boolean dashed) { + mFraction = fraction; + mColor = color; + mDashed = dashed; + } + + public float getFraction() { + return this.mFraction; + } + + public int getColor() { + return this.mColor; + } + + public boolean getDashed() { + return this.mDashed; + } + + @Override + public String toString() { + return "Segment(fraction=" + this.mFraction + ", color=" + this.mColor + ", dashed=" + + this.mDashed + ')'; + } + } + + /** + * A point is a part of the progress bar with zero length. Points are designated points within a + * progressbar to visualize distinct stages or milestones. For example, a stop in a multi-stop + * ride-share journey. + */ + public static final class Point implements Part { + @Nullable + private final Drawable mIcon; + @ColorInt private final int mColor; + + public Point(@Nullable Drawable icon) { + this(icon, Color.TRANSPARENT); + } + + public Point(@Nullable Drawable icon, @ColorInt int color) { + mIcon = icon; + mColor = color; + } + + @Nullable + public Drawable getIcon() { + return this.mIcon; + } + + @Override + public String toString() { + return "Point(icon=" + this.mIcon + ", color=" + this.mColor + ')'; + } + } + + @Override + public Drawable mutate() { + if (!mMutated && super.mutate() == this) { + mState = new State(mState, null); + updateLocalState(); + mMutated = true; + } + return this; + } + + @Override + public void clearMutated() { + super.clearMutated(); + mMutated = false; + } + + static final class State extends ConstantState { + @Config + int mChangingConfigurations; + float mSegSegGap = 0.0f; + float mSegPointGap = 0.0f; + int mStrokeWidth = 0; + int mStrokeColor; + float mStrokeDashWidth = 0.0f; + float mStrokeDashGap = 0.0f; + float mPointRadius; + float mPointRectInset; + float mPointRectCornerRadius; + int mPointRectColor; + + int[] mThemeAttrs; + int[] mThemeAttrsSegments; + int[] mThemeAttrsPoints; + + int mDensity = DisplayMetrics.DENSITY_DEFAULT; + + State() { + } + + State(@NonNull State orig, @Nullable Resources res) { + mChangingConfigurations = orig.mChangingConfigurations; + mStrokeColor = orig.mStrokeColor; + mStrokeWidth = orig.mStrokeWidth; + mStrokeDashWidth = orig.mStrokeDashWidth; + mStrokeDashGap = orig.mStrokeDashGap; + mPointRadius = orig.mPointRadius; + mPointRectInset = orig.mPointRectInset; + mPointRectCornerRadius = orig.mPointRectCornerRadius; + mPointRectColor = orig.mPointRectColor; + + mThemeAttrs = orig.mThemeAttrs; + mThemeAttrsSegments = orig.mThemeAttrsSegments; + mThemeAttrsPoints = orig.mThemeAttrsPoints; + + mDensity = resolveDensity(res, orig.mDensity); + if (orig.mDensity != mDensity) { + applyDensityScaling(orig.mDensity, mDensity); + } + } + + private void applyDensityScaling(int sourceDensity, int targetDensity) { + if (mStrokeWidth > 0) { + mStrokeWidth = scaleFromDensity( + mStrokeWidth, sourceDensity, targetDensity, true); + } + if (mStrokeDashWidth > 0) { + mStrokeDashWidth = scaleFromDensity( + mStrokeDashWidth, sourceDensity, targetDensity); + } + if (mStrokeDashGap > 0) { + mStrokeDashGap = scaleFromDensity( + mStrokeDashGap, sourceDensity, targetDensity); + } + if (mPointRadius > 0) { + mPointRadius = scaleFromDensity( + mPointRadius, sourceDensity, targetDensity); + } + if (mPointRectInset > 0) { + mPointRectInset = scaleFromDensity( + mPointRectInset, sourceDensity, targetDensity); + } + if (mPointRectCornerRadius > 0) { + mPointRectCornerRadius = scaleFromDensity( + mPointRectCornerRadius, sourceDensity, targetDensity); + } + } + + @NonNull + @Override + public Drawable newDrawable() { + return new NotificationProgressDrawable(this, null); + } + + @Override + public Drawable newDrawable(@Nullable Resources res) { + // If this drawable is being created for a different density, + // just create a new constant state and call it a day. + final State state; + final int density = resolveDensity(res, mDensity); + if (density != mDensity) { + state = new State(this, res); + } else { + state = this; + } + + return new NotificationProgressDrawable(state, res); + } + + @Override + public int getChangingConfigurations() { + return mChangingConfigurations; + } + + @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || mThemeAttrsSegments != null || mThemeAttrsPoints != null + || super.canApplyTheme(); + } + + public void setDensity(int targetDensity) { + if (mDensity != targetDensity) { + final int sourceDensity = mDensity; + mDensity = targetDensity; + + applyDensityScaling(sourceDensity, targetDensity); + } + } + + public void setStroke(int width, int color, float dashWidth, float dashGap) { + mStrokeWidth = width; + mStrokeColor = color; + mStrokeDashWidth = dashWidth; + mStrokeDashGap = dashGap; + } + } + + @Override + public ConstantState getConstantState() { + mState.mChangingConfigurations = getChangingConfigurations(); + return mState; + } + + /** + * Creates a new themed NotificationProgressDrawable based on the specified constant state. + * <p> + * The resulting drawable is guaranteed to have a new constant state. + * + * @param state Constant state from which the drawable inherits + */ + private NotificationProgressDrawable(@NonNull State state, @Nullable Resources res) { + mState = state; + + updateLocalState(); + } + + private void updateLocalState() { + final State state = mState; + + mStrokePaint.setStrokeWidth(state.mStrokeWidth); + + if (state.mStrokeDashWidth != 0.0f) { + final DashPathEffect e = new DashPathEffect( + new float[] { state.mStrokeDashWidth, state.mStrokeDashGap }, 0); + mDashedStrokePaint.setPathEffect(e); + } + } +} diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 9797d9662387..2bc32657bd4a 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -73,6 +73,12 @@ cc_library_shared_for_libandroid_runtime { srcs: [ "android_animation_PropertyValuesHolder.cpp", + "android_database_CursorWindow.cpp", + "android_database_SQLiteCommon.cpp", + "android_database_SQLiteConnection.cpp", + "android_database_SQLiteGlobal.cpp", + "android_database_SQLiteDebug.cpp", + "android_database_SQLiteRawStatement.cpp", "android_os_SystemClock.cpp", "android_os_SystemProperties.cpp", "android_os_Trace.cpp", @@ -157,12 +163,6 @@ cc_library_shared_for_libandroid_runtime { "android_opengl_GLES31.cpp", "android_opengl_GLES31Ext.cpp", "android_opengl_GLES32.cpp", - "android_database_CursorWindow.cpp", - "android_database_SQLiteCommon.cpp", - "android_database_SQLiteConnection.cpp", - "android_database_SQLiteGlobal.cpp", - "android_database_SQLiteDebug.cpp", - "android_database_SQLiteRawStatement.cpp", "android_graphics_GraphicBuffer.cpp", "android_graphics_SurfaceTexture.cpp", "android_view_CompositionSamplingListener.cpp", @@ -308,6 +308,7 @@ cc_library_shared_for_libandroid_runtime { "spatializer-aidl-cpp", "av-types-aidl-cpp", "android.hardware.camera.device@3.2", + "camera_platform_flags_c_lib", "libandroid_net", "libbattery", "libnetdutils", @@ -427,6 +428,7 @@ cc_library_shared_for_libandroid_runtime { "libnativehelper_jvm", "libpiex", "libpng", + "libsqlite", "libtiff_directory", "libui-types", "libutils", @@ -442,12 +444,6 @@ cc_library_shared_for_libandroid_runtime { host_linux: { srcs: [ "android_content_res_ApkAssets.cpp", - "android_database_CursorWindow.cpp", - "android_database_SQLiteCommon.cpp", - "android_database_SQLiteConnection.cpp", - "android_database_SQLiteGlobal.cpp", - "android_database_SQLiteDebug.cpp", - "android_database_SQLiteRawStatement.cpp", "android_hardware_input_InputApplicationHandle.cpp", "android_os_MessageQueue.cpp", "android_os_Parcel.cpp", @@ -463,7 +459,6 @@ cc_library_shared_for_libandroid_runtime { ], static_libs: [ "libbinderthreadstateutils", - "libsqlite", "libgui_window_info_static", ], shared_libs: [ diff --git a/core/jni/OWNERS b/core/jni/OWNERS index af106235bd77..af393fdc5ad4 100644 --- a/core/jni/OWNERS +++ b/core/jni/OWNERS @@ -119,3 +119,4 @@ per-file android_tracing_Perfetto* = file:platform/development:/tools/winscope/O # ApplicationSharedMemory per-file *ApplicationSharedMemory* = file:/PERFORMANCE_OWNERS +per-file *PropertyInvalidatedCache* = file:/PERFORMANCE_OWNERS diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp index c0e9215267e6..18c314610bb2 100644 --- a/core/jni/android_database_CursorWindow.cpp +++ b/core/jni/android_database_CursorWindow.cpp @@ -38,7 +38,9 @@ #define LOG_NDEBUG 1 #include <androidfw/CursorWindow.h> +#ifdef __linux__ #include "android_os_Parcel.h" +#endif #include "android_util_Binder.h" #include "android_database_SQLiteCommon.h" @@ -111,6 +113,7 @@ fail: return 0; } +#ifdef __linux__ static jlong nativeCreateFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) { Parcel* parcel = parcelForJavaObject(env, parcelObj); @@ -128,6 +131,7 @@ static jlong nativeCreateFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj window->getNumRows(), window->getNumColumns(), window); return reinterpret_cast<jlong>(window); } +#endif static void nativeDispose(JNIEnv* env, jclass clazz, jlong windowPtr) { CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); @@ -142,6 +146,7 @@ static jstring nativeGetName(JNIEnv* env, jclass clazz, jlong windowPtr) { return env->NewStringUTF(window->name().c_str()); } +#ifdef __linux__ static void nativeWriteToParcel(JNIEnv * env, jclass clazz, jlong windowPtr, jobject parcelObj) { CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); @@ -154,6 +159,7 @@ static void nativeWriteToParcel(JNIEnv * env, jclass clazz, jlong windowPtr, jniThrowRuntimeException(env, msg.c_str()); } } +#endif static void nativeClear(JNIEnv * env, jclass clazz, jlong windowPtr) { CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); @@ -520,55 +526,35 @@ static jboolean nativePutNull(JNIEnv* env, jclass clazz, jlong windowPtr, return true; } -static const JNINativeMethod sMethods[] = -{ - /* name, signature, funcPtr */ - { "nativeCreate", "(Ljava/lang/String;I)J", - (void*)nativeCreate }, - { "nativeCreateFromParcel", "(Landroid/os/Parcel;)J", - (void*)nativeCreateFromParcel }, - { "nativeDispose", "(J)V", - (void*)nativeDispose }, - { "nativeWriteToParcel", "(JLandroid/os/Parcel;)V", - (void*)nativeWriteToParcel }, - - { "nativeGetName", "(J)Ljava/lang/String;", - (void*)nativeGetName }, - { "nativeGetBlob", "(JII)[B", - (void*)nativeGetBlob }, - { "nativeGetString", "(JII)Ljava/lang/String;", - (void*)nativeGetString }, - { "nativeCopyStringToBuffer", "(JIILandroid/database/CharArrayBuffer;)V", - (void*)nativeCopyStringToBuffer }, - { "nativePutBlob", "(J[BII)Z", - (void*)nativePutBlob }, - { "nativePutString", "(JLjava/lang/String;II)Z", - (void*)nativePutString }, - - // ------- @FastNative below here ---------------------- - { "nativeClear", "(J)V", - (void*)nativeClear }, - { "nativeGetNumRows", "(J)I", - (void*)nativeGetNumRows }, - { "nativeSetNumColumns", "(JI)Z", - (void*)nativeSetNumColumns }, - { "nativeAllocRow", "(J)Z", - (void*)nativeAllocRow }, - { "nativeFreeLastRow", "(J)V", - (void*)nativeFreeLastRow }, - { "nativeGetType", "(JII)I", - (void*)nativeGetType }, - { "nativeGetLong", "(JII)J", - (void*)nativeGetLong }, - { "nativeGetDouble", "(JII)D", - (void*)nativeGetDouble }, - - { "nativePutLong", "(JJII)Z", - (void*)nativePutLong }, - { "nativePutDouble", "(JDII)Z", - (void*)nativePutDouble }, - { "nativePutNull", "(JII)Z", - (void*)nativePutNull }, +static const JNINativeMethod sMethods[] = { + /* name, signature, funcPtr */ + {"nativeCreate", "(Ljava/lang/String;I)J", (void*)nativeCreate}, + {"nativeDispose", "(J)V", (void*)nativeDispose}, +#ifdef __linux__ + {"nativeCreateFromParcel", "(Landroid/os/Parcel;)J", (void*)nativeCreateFromParcel}, + {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V", (void*)nativeWriteToParcel}, +#endif + {"nativeGetName", "(J)Ljava/lang/String;", (void*)nativeGetName}, + {"nativeGetBlob", "(JII)[B", (void*)nativeGetBlob}, + {"nativeGetString", "(JII)Ljava/lang/String;", (void*)nativeGetString}, + {"nativeCopyStringToBuffer", "(JIILandroid/database/CharArrayBuffer;)V", + (void*)nativeCopyStringToBuffer}, + {"nativePutBlob", "(J[BII)Z", (void*)nativePutBlob}, + {"nativePutString", "(JLjava/lang/String;II)Z", (void*)nativePutString}, + + // ------- @FastNative below here ---------------------- + {"nativeClear", "(J)V", (void*)nativeClear}, + {"nativeGetNumRows", "(J)I", (void*)nativeGetNumRows}, + {"nativeSetNumColumns", "(JI)Z", (void*)nativeSetNumColumns}, + {"nativeAllocRow", "(J)Z", (void*)nativeAllocRow}, + {"nativeFreeLastRow", "(J)V", (void*)nativeFreeLastRow}, + {"nativeGetType", "(JII)I", (void*)nativeGetType}, + {"nativeGetLong", "(JII)J", (void*)nativeGetLong}, + {"nativeGetDouble", "(JII)D", (void*)nativeGetDouble}, + + {"nativePutLong", "(JJII)Z", (void*)nativePutLong}, + {"nativePutDouble", "(JDII)Z", (void*)nativePutDouble}, + {"nativePutNull", "(JII)Z", (void*)nativePutNull}, }; int register_android_database_CursorWindow(JNIEnv* env) diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 3f74fac35bb7..10e49efee92e 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -25,6 +25,7 @@ #include <binder/Parcel.h> #include <camera/Camera.h> #include <camera/StringUtils.h> +#include <com_android_internal_camera_flags.h> #include <cutils/properties.h> #include <gui/GLConsumer.h> #include <gui/Surface.h> @@ -37,6 +38,7 @@ #include "jni.h" using namespace android; +namespace flags = com::android::internal::camera::flags; enum { // Keep up to date with Camera.java @@ -527,14 +529,19 @@ void JNICameraContext::clearCallbackBuffers_l(JNIEnv *env, Vector<jbyteArray> *b } static bool attributionSourceStateForJavaParcel(JNIEnv *env, jobject jClientAttributionParcel, + bool useContextAttributionSource, AttributionSourceState &clientAttribution) { const Parcel *clientAttributionParcel = parcelForJavaObject(env, jClientAttributionParcel); if (clientAttribution.readFromParcel(clientAttributionParcel) != ::android::OK) { jniThrowRuntimeException(env, "Fail to unparcel AttributionSourceState"); return false; } - clientAttribution.uid = Camera::USE_CALLING_UID; - clientAttribution.pid = Camera::USE_CALLING_PID; + + if (!(useContextAttributionSource && flags::use_context_attribution_source())) { + clientAttribution.uid = Camera::USE_CALLING_UID; + clientAttribution.pid = Camera::USE_CALLING_PID; + } + return true; } @@ -542,7 +549,9 @@ static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz jobject jClientAttributionParcel, jint devicePolicy) { AttributionSourceState clientAttribution; - if (!attributionSourceStateForJavaParcel(env, jClientAttributionParcel, clientAttribution)) { + if (!attributionSourceStateForJavaParcel(env, jClientAttributionParcel, + /* useContextAttributionSource= */ false, + clientAttribution)) { return 0; } return Camera::getNumberOfCameras(clientAttribution, devicePolicy); @@ -553,7 +562,9 @@ static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz, jin jobject jClientAttributionParcel, jint devicePolicy, jobject info_obj) { AttributionSourceState clientAttribution; - if (!attributionSourceStateForJavaParcel(env, jClientAttributionParcel, clientAttribution)) { + if (!attributionSourceStateForJavaParcel(env, jClientAttributionParcel, + /* useContextAttributionSource= */ false, + clientAttribution)) { return; } @@ -587,7 +598,9 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobj jobject jClientAttributionParcel, jint devicePolicy) { AttributionSourceState clientAttribution; - if (!attributionSourceStateForJavaParcel(env, jClientAttributionParcel, clientAttribution)) { + if (!attributionSourceStateForJavaParcel(env, jClientAttributionParcel, + /* useContextAttributionSource= */ true, + clientAttribution)) { return -EACCES; } diff --git a/core/jni/android_hardware_OverlayProperties.cpp b/core/jni/android_hardware_OverlayProperties.cpp index 96494b16cc21..63de1950f2a5 100644 --- a/core/jni/android_hardware_OverlayProperties.cpp +++ b/core/jni/android_hardware_OverlayProperties.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "OverlayProperties" // #define LOG_NDEBUG 0 +#include <android/gui/LutProperties.h> #include <android/gui/OverlayProperties.h> #include <binder/Parcel.h> #include <gui/SurfaceComposerClient.h> @@ -35,6 +36,12 @@ static struct { jclass clazz; jmethodID ctor; } gOverlayPropertiesClassInfo; + +static struct { + jclass clazz; + jmethodID ctor; +} gLutPropertiesClassInfo; + // ---------------------------------------------------------------------------- // OverlayProperties lifecycle // ---------------------------------------------------------------------------- @@ -95,6 +102,36 @@ static jlong android_hardware_OverlayProperties_createDefault(JNIEnv* env, jobje return reinterpret_cast<jlong>(overlayProperties); } +static jobjectArray android_hardware_OverlayProperties_getLutProperties(JNIEnv* env, jobject thiz, + jlong nativeObject) { + gui::OverlayProperties* overlayProperties = + reinterpret_cast<gui::OverlayProperties*>(nativeObject); + if (overlayProperties->lutProperties.has_value()) { + return NULL; + } + auto& lutProperties = overlayProperties->lutProperties.value(); + if (lutProperties.empty()) { + return NULL; + } + int32_t size = static_cast<int32_t>(lutProperties.size()); + jobjectArray nativeLutProperties = + env->NewObjectArray(size, gLutPropertiesClassInfo.clazz, NULL); + if (nativeLutProperties == NULL) { + return NULL; + } + for (int32_t i = 0; i < size; i++) { + if (lutProperties[i].has_value()) { + auto& item = lutProperties[i].value(); + jobject properties = + env->NewObject(gLutPropertiesClassInfo.clazz, gLutPropertiesClassInfo.ctor, + static_cast<int32_t>(item.dimension), item.size, + item.samplingKeys.data()); + env->SetObjectArrayElement(nativeLutProperties, i, properties); + } + } + return nativeLutProperties; +} + // ---------------------------------------------------------------------------- // Serialization // ---------------------------------------------------------------------------- @@ -161,6 +198,8 @@ static const JNINativeMethod gMethods[] = { { "nReadOverlayPropertiesFromParcel", "(Landroid/os/Parcel;)J", (void*) android_hardware_OverlayProperties_read }, {"nCreateDefault", "()J", (void*) android_hardware_OverlayProperties_createDefault }, + {"nGetLutProperties", "(J)[Landroid/hardware/LutProperties;", + (void*) android_hardware_OverlayProperties_getLutProperties }, }; // clang-format on @@ -171,5 +210,9 @@ int register_android_hardware_OverlayProperties(JNIEnv* env) { gOverlayPropertiesClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); gOverlayPropertiesClassInfo.ctor = GetMethodIDOrDie(env, gOverlayPropertiesClassInfo.clazz, "<init>", "(J)V"); + clazz = FindClassOrDie(env, "android/hardware/LutProperties"); + gLutPropertiesClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); + gLutPropertiesClassInfo.ctor = + GetMethodIDOrDie(env, gLutPropertiesClassInfo.clazz, "<init>", "(IJ[I)V"); return err; } diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h index a9b19062b764..704aef3cd131 100644 --- a/core/jni/android_media_AudioFormat.h +++ b/core/jni/android_media_AudioFormat.h @@ -50,6 +50,7 @@ #define ENCODING_DTS_HD_MA 29 #define ENCODING_DTS_UHD_P2 30 #define ENCODING_DSD 31 +#define ENCODING_AC4_L4 32 #define ENCODING_INVALID 0 #define ENCODING_DEFAULT 1 @@ -95,6 +96,8 @@ static inline audio_format_t audioFormatToNative(int audioFormat) return AUDIO_FORMAT_AAC_XHE; case ENCODING_AC4: return AUDIO_FORMAT_AC4; + case ENCODING_AC4_L4: + return AUDIO_FORMAT_AC4_L4; case ENCODING_E_AC3_JOC: return AUDIO_FORMAT_E_AC3_JOC; case ENCODING_DEFAULT: @@ -177,6 +180,8 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) return ENCODING_AAC_XHE; case AUDIO_FORMAT_AC4: return ENCODING_AC4; + case AUDIO_FORMAT_AC4_L4: + return ENCODING_AC4_L4; case AUDIO_FORMAT_E_AC3_JOC: return ENCODING_E_AC3_JOC; case AUDIO_FORMAT_MAT: diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 17c89f88b441..a939d9274956 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -33,11 +33,13 @@ #include <android_runtime/android_view_Surface.h> #include <android_runtime/android_view_SurfaceControl.h> #include <android_runtime/android_view_SurfaceSession.h> +#include <cutils/ashmem.h> #include <gui/ISurfaceComposer.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <jni.h> #include <nativehelper/JNIHelp.h> +#include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedUtfChars.h> #include <private/gui/ComposerService.h> #include <stdio.h> @@ -48,6 +50,7 @@ #include <ui/DisplayMode.h> #include <ui/DisplayedFrameStats.h> #include <ui/DynamicDisplayInfo.h> +#include <ui/FloatRect.h> #include <ui/FrameStats.h> #include <ui/GraphicTypes.h> #include <ui/HdrCapabilities.h> @@ -735,6 +738,65 @@ static void nativeSetDesiredHdrHeadroom(JNIEnv* env, jclass clazz, jlong transac transaction->setDesiredHdrHeadroom(ctrl, desiredRatio); } +static void nativeSetLuts(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, + jfloatArray jbufferArray, jintArray joffsetArray, + jintArray jdimensionArray, jintArray jsizeArray, + jintArray jsamplingKeyArray) { + auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject); + + ScopedIntArrayRW joffsets(env, joffsetArray); + if (joffsets.get() == nullptr) { + jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from joffsetArray"); + return; + } + ScopedIntArrayRW jdimensions(env, jdimensionArray); + if (jdimensions.get() == nullptr) { + jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from jdimensionArray"); + return; + } + ScopedIntArrayRW jsizes(env, jsizeArray); + if (jsizes.get() == nullptr) { + jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from jsizeArray"); + return; + } + ScopedIntArrayRW jsamplingKeys(env, jsamplingKeyArray); + if (jsamplingKeys.get() == nullptr) { + jniThrowRuntimeException(env, "Failed to get ScopedIntArrayRW from jsamplingKeyArray"); + return; + } + + jsize numLuts = env->GetArrayLength(jdimensionArray); + std::vector<int32_t> offsets(joffsets.get(), joffsets.get() + numLuts); + std::vector<int32_t> dimensions(jdimensions.get(), jdimensions.get() + numLuts); + std::vector<int32_t> sizes(jsizes.get(), jsizes.get() + numLuts); + std::vector<int32_t> samplingKeys(jsamplingKeys.get(), jsamplingKeys.get() + numLuts); + + ScopedFloatArrayRW jbuffers(env, jbufferArray); + if (jbuffers.get() == nullptr) { + jniThrowRuntimeException(env, "Failed to get ScopedFloatArrayRW from jbufferArray"); + return; + } + + // create the shared memory and copy jbuffers + size_t bufferSize = jbuffers.size() * sizeof(float); + int32_t fd = ashmem_create_region("lut_shread_mem", bufferSize); + if (fd < 0) { + jniThrowRuntimeException(env, "ashmem_create_region() failed"); + return; + } + void* ptr = mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED) { + jniThrowRuntimeException(env, "Failed to map the shared memory"); + return; + } + memcpy(ptr, jbuffers.get(), bufferSize); + // unmap + munmap(ptr, bufferSize); + + transaction->setLuts(ctrl, base::unique_fd(fd), offsets, dimensions, sizes, samplingKeys); +} + static void nativeSetCachingHint(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jint cachingHint) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); @@ -992,6 +1054,15 @@ static void nativeSetWindowCrop(JNIEnv* env, jclass clazz, jlong transactionObj, transaction->setCrop(ctrl, crop); } +static void nativeSetCrop(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, + jfloat l, jfloat t, jfloat r, jfloat b) { + auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); + + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject); + FloatRect crop(l, t, r, b); + transaction->setCrop(ctrl, crop); +} + static void nativeSetCornerRadius(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jfloat cornerRadius) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); @@ -2347,6 +2418,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetFrameRateSelectionPriority }, {"nativeSetWindowCrop", "(JJIIII)V", (void*)nativeSetWindowCrop }, + {"nativeSetCrop", "(JJFFFF)V", + (void*)nativeSetCrop }, {"nativeSetCornerRadius", "(JJF)V", (void*)nativeSetCornerRadius }, {"nativeSetBackgroundBlurRadius", "(JJI)V", @@ -2529,6 +2602,7 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*) nativeSetDesiredPresentTimeNanos }, {"nativeNotifyShutdown", "()V", (void*)nativeNotifyShutdown }, + {"nativeSetLuts", "(JJ[F[I[I[I[I)V", (void*)nativeSetLuts }, // clang-format on }; diff --git a/core/jni/jni_wrappers.h b/core/jni/jni_wrappers.h index 21b5b1308fcf..e3e17eed54d5 100644 --- a/core/jni/jni_wrappers.h +++ b/core/jni/jni_wrappers.h @@ -79,13 +79,14 @@ inline static void setJniMethodFormat(std::string value) { jniMethodFormat = value; } -// Potentially translates the given JNINativeMethods if setJniMethodFormat has been set. -// Has no effect otherwise -inline const JNINativeMethod* maybeRenameJniMethods(const JNINativeMethod* gMethods, - int numMethods) { +// Register the native methods, potenially applying the jniMethodFormat if it has been set. +static inline int jniRegisterMaybeRenamedNativeMethods(JNIEnv* env, const char* className, + const JNINativeMethod* gMethods, + int numMethods) { if (jniMethodFormat.empty()) { - return gMethods; + return jniRegisterNativeMethods(env, className, gMethods, numMethods); } + // Make a copy of gMethods with reformatted method names. JNINativeMethod* modifiedMethods = new JNINativeMethod[numMethods]; LOG_ALWAYS_FATAL_IF(!modifiedMethods, "Failed to allocate a copy of the JNI methods"); @@ -103,13 +104,17 @@ inline const JNINativeMethod* maybeRenameJniMethods(const JNINativeMethod* gMeth std::strcpy(modifiedNameChars, modifiedName.c_str()); modifiedMethods[i].name = modifiedNameChars; } - return modifiedMethods; + int res = jniRegisterNativeMethods(env, className, modifiedMethods, numMethods); + for (int i = 0; i < numMethods; i++) { + delete[] modifiedMethods[i].name; + } + delete[] modifiedMethods; + return res; } static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { - const JNINativeMethod* modifiedMethods = maybeRenameJniMethods(gMethods, numMethods); - int res = jniRegisterNativeMethods(env, className, modifiedMethods, numMethods); + int res = jniRegisterMaybeRenamedNativeMethods(env, className, gMethods, numMethods); LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods."); return res; } diff --git a/core/jni/platform/host/HostRuntime.cpp b/core/jni/platform/host/HostRuntime.cpp index 19f82998c1a3..88b3e1c1ed9d 100644 --- a/core/jni/platform/host/HostRuntime.cpp +++ b/core/jni/platform/host/HostRuntime.cpp @@ -115,6 +115,9 @@ static const std::unordered_map<std::string, RegJNIRec> gRegJNIMap = { #ifdef __linux__ {"android.content.res.ApkAssets", REG_JNI(register_android_content_res_ApkAssets)}, {"android.content.res.AssetManager", REG_JNI(register_android_content_AssetManager)}, + {"android.content.res.StringBlock", REG_JNI(register_android_content_StringBlock)}, + {"android.content.res.XmlBlock", REG_JNI(register_android_content_XmlBlock)}, +#endif {"android.database.CursorWindow", REG_JNI(register_android_database_CursorWindow)}, {"android.database.sqlite.SQLiteConnection", REG_JNI(register_android_database_SQLiteConnection)}, @@ -122,9 +125,6 @@ static const std::unordered_map<std::string, RegJNIRec> gRegJNIMap = { {"android.database.sqlite.SQLiteDebug", REG_JNI(register_android_database_SQLiteDebug)}, {"android.database.sqlite.SQLiteRawStatement", REG_JNI(register_android_database_SQLiteRawStatement)}, -#endif - {"android.content.res.StringBlock", REG_JNI(register_android_content_StringBlock)}, - {"android.content.res.XmlBlock", REG_JNI(register_android_content_XmlBlock)}, #ifdef __linux__ {"android.os.Binder", REG_JNI(register_android_os_Binder)}, {"android.os.FileObserver", REG_JNI(register_android_os_FileObserver)}, diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index ed33edecb333..549f8df3e527 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -792,6 +792,7 @@ <protected-broadcast android:name="com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO" /> <protected-broadcast android:name="com.android.internal.telephony.ACTION_CARRIER_CERTIFICATE_DOWNLOAD" /> <protected-broadcast android:name="com.android.internal.telephony.action.COUNTRY_OVERRIDE" /> + <protected-broadcast android:name="com.android.internal.telephony.action.SILENCE_WIFI_CALLING_NOTIFICATION"/> <protected-broadcast android:name="com.android.internal.telephony.OPEN_DEFAULT_SMS_APP" /> <protected-broadcast android:name="com.android.internal.telephony.ACTION_TEST_OVERRIDE_CARRIER_ID" /> <protected-broadcast android:name="android.telephony.action.SIM_CARD_STATE_CHANGED" /> @@ -844,6 +845,8 @@ <protected-broadcast android:name="android.intent.action.MAIN_USER_LOCKSCREEN_KNOWLEDGE_FACTOR_CHANGED" /> <protected-broadcast android:name="com.android.uwb.uwbcountrycode.GEOCODE_RETRY" /> <protected-broadcast android:name="android.telephony.action.ACTION_SATELLITE_SUBSCRIBER_ID_LIST_CHANGED" /> + <protected-broadcast android:name="android.service.ondeviceintelligence.MODEL_LOADED" /> + <protected-broadcast android:name="android.service.ondeviceintelligence.MODEL_UNLOADED" /> <!-- ====================================================================== --> <!-- RUNTIME PERMISSIONS --> diff --git a/core/res/res/drawable/notification_progress_icon_background.xml b/core/res/res/drawable/notification_progress_icon_background.xml new file mode 100644 index 000000000000..8e843bea3d6a --- /dev/null +++ b/core/res/res/drawable/notification_progress_icon_background.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> + <solid android:color="#00000000" /> + <corners android:radius="4dp" /> +</shape>
\ No newline at end of file diff --git a/core/res/res/layout/notification_template_material_progress.xml b/core/res/res/layout/notification_template_material_progress.xml new file mode 100644 index 000000000000..b413c701d6c5 --- /dev/null +++ b/core/res/res/layout/notification_template_material_progress.xml @@ -0,0 +1,121 @@ +<?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 + --> +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/status_bar_latest_event_content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:clipChildren="false" + android:tag="progress" + > + + <LinearLayout + android:id="@+id/notification_action_list_margin_target" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/notification_content_margin" + android:orientation="vertical" + > + + <FrameLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="top" + > + + <include layout="@layout/notification_template_header" /> + + <LinearLayout + android:id="@+id/notification_main_column" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/notification_content_margin_start" + android:layout_marginEnd="@dimen/notification_content_margin_end" + android:layout_marginTop="@dimen/notification_content_margin_top" + android:orientation="vertical" + > + + <include layout="@layout/notification_template_part_line1" /> + + <include layout="@layout/notification_template_text_multiline" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:layout_marginTop="@dimen/notification_progress_margin_top" + android:orientation="horizontal"> + + <com.android.internal.widget.CachingIconView + android:id="@+id/notification_progress_start_icon" + android:layout_width="@dimen/notification_progress_icon_size" + android:layout_height="@dimen/notification_progress_icon_size" + android:background="@drawable/notification_progress_icon_background" + android:clipToOutline="true" + android:importantForAccessibility="no" + android:layout_marginEnd="@dimen/notification_progress_margin_horizontal" + android:scaleType="centerCrop" + android:maxDrawableWidth="@dimen/notification_progress_icon_size" + android:maxDrawableHeight="@dimen/notification_progress_icon_size" + /> + + + <include + android:layout_width="0dp" + android:layout_height="@dimen/notification_progress_bar_height" + layout="@layout/notification_template_progress" + android:layout_weight="1" + /> + + <com.android.internal.widget.CachingIconView + android:id="@+id/notification_progress_end_icon" + android:layout_width="@dimen/notification_progress_icon_size" + android:layout_height="@dimen/notification_progress_icon_size" + android:background="@drawable/notification_progress_icon_background" + android:clipToOutline="true" + android:importantForAccessibility="no" + android:scaleType="centerCrop" + android:layout_marginStart="@dimen/notification_progress_margin_horizontal" + android:maxDrawableWidth="@dimen/notification_progress_icon_size" + android:maxDrawableHeight="@dimen/notification_progress_icon_size" + /> + </LinearLayout> + </LinearLayout> + + <include layout="@layout/notification_template_right_icon" /> + </FrameLayout> + + <ViewStub + android:layout="@layout/notification_material_reply_text" + android:id="@+id/notification_material_reply_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + /> + + <include + layout="@layout/notification_template_smart_reply_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/notification_content_margin_start" + android:layout_marginEnd="@dimen/notification_content_margin_end" + android:layout_marginTop="@dimen/notification_content_margin" + /> + + <include layout="@layout/notification_material_action_list" /> + </LinearLayout> +</FrameLayout>
\ No newline at end of file diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 1cd21504193c..cdae26541737 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Oproepe en kennisgewings sal vibreer"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Oproepe en kennisgewings sal gedemp wees"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Stelselveranderinge"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Moenie Steur Nie"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Nuut: Moenie Steur Nie versteek tans kennisgewings"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tik om meer te wete te kom en te verander."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Moenie Steur Nie het verander"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tik om te kyk wat geblokkeer word."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Gaan kennisgewinginstellings na"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Vanaf Android 13 het programme wat jy installeer jou toestemming nodig om kennisgewings te stuur. Tik om hierdie toestemming vir bestaande programme te verander."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Herinner my later"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 484afc3c344e..cc8ab3e03f6e 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"ጥሪዎች እና ማሳወቂያዎች ይነዝራሉ"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"ጥሪዎች እና ማሳወቂያዎች ድምፀ-ከል ይሆናሉ"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"የሥርዓት ለውጦች"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"አትረብሽ"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"አዲስ፦ አትረብሽ ማሳወቂያዎችን እየደበቀ ነው"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"የበለጠ ለመረዳት እና ለመለወጥ መታ ያድርጉ።"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"አትረብሽ ተቀይሯል"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"ምን እንደታገደ ለመፈተሽ መታ ያድርጉ።"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"የማሳወቂያ ቅንብሮችን ይገምግሙ"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"ከAndroid 13 ጀምረው የሚጭኗቸው መተግበሪያዎች ማሳወቂያዎችን ለመላክ የእርስዎ ፈቃድ ያስፈልጋቸዋል። ይህን ፈቃድ ለነባር መተግበሪያዎች ለመቀየር መታ ያድርጉ።"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"በኋላ አስታውሰኝ"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 75e93d1aa315..e81ec89ebe51 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -2133,11 +2133,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"سيهتز الهاتف عند تلقّي المكالمات والإشعارات."</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"سيتم كتم صوت الهاتف عند تلقي المكالمات والإشعارات."</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"تغييرات النظام"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"عدم الإزعاج"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"جديد: يؤدي تفعيل ميزة \"عدم الإزعاج\" إلى إخفاء الإشعارات."</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"انقر لمعرفة مزيد من المعلومات وإجراء التغيير."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"تم تغيير ميزة \"عدم الإزعاج\""</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"انقر للاطّلاع على ما تم حظره."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"مراجعة إعدادات الإشعارات"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"بدءً من نظام التشغيل Android 13، يجب أن تحصل التطبيقات التي تُثبِّتها على إذن لإرسال الإشعارات. انقر لتغيير هذا الإذن للتطبيقات الحالية."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"تذكيري لاحقًا"</string> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index e64c85e058d5..f36a659dd84d 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"কল আৰু জাননীসমূহে কম্পন কৰিব"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"কল আৰু জাননীসমূহ মিউট কৰা হ\'ব"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"ছিষ্টেমৰ সালসলনি"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"অসুবিধা নিদিব"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"নতুন: অসুবিধা নিদিব ম\'ডে জাননীসমূহ লুকাই ৰাখিছে"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"অধিক জানিবলৈ আৰু সলনি কৰিবলৈ টিপক।"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"অসুবিধা নিদিব সলনি হৈছে"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"কি কি অৱৰোধ কৰা হৈছে জানিবলৈ টিপক।"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"জাননীৰ ছেটিং পৰ্যালোচনা কৰক"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13ৰ পৰা, আপুনি ইনষ্টল কৰা এপক জাননী পঠিয়াবলৈ আপোনাৰ অনুমতিৰ প্ৰয়োজন। আগৰে পৰা থকা এপৰ বাবে এই অনুমতিটো সলনি কৰিবলৈ টিপক।"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"পাছত মনত পেলাই দিব"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index 25dc42904995..2a77df23934c 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Zəng və bildirişlər vibrasiya verəcək"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Zəng və bildirişlər səssiz ediləcək"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Sistem dəyişiklikləri"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Narahat Etməyin"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Yenilik: \"Narahat etməyin\" rejimi bildirişləri gizlədir"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Ətraflı məıumat əldə edərək dəyişmək üçün klikləyin."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\"Narahat Etməyin\" rejimi dəyişdirildi"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Nəyin blok edildiyini yoxlamaq üçün klikləyin."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Bildiriş ayarlarını nəzərdən keçirin"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13-dən başlayaraq quraşdırdığınız tətbiqlər bildiriş göndərmək üçün icazənizi tələb edir. Mövcud tətbiqlər üçün bu icazəni dəyişmək üçün toxunun."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Sonra xatırladın"</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 7413703e2ada..a51aad24b06f 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Vibracija za pozive i obaveštenja je uključena"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Melodija zvona za pozive i obaveštenje je isključena"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Sistemske promene"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Ne uznemiravaj"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novo: Režim Ne uznemiravaj krije obaveštenja"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Dodirnite da biste saznali više i promenili podešavanje."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Režim Ne uznemiravaj je promenjen"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Dodirnite da biste proverili šta je blokirano."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Pregledajte podešavanja obaveštenja"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Od Android-a 13 aplikacije koje instalirate moraju da imaju dozvolu za slanje obaveštenja. Dodirnite da biste promenili ovu dozvolu za postojeće aplikacije."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Podseti me kasnije"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index a5af4b9fbdfe..26f11df6259c 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -2131,11 +2131,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Для выклікаў і апавяшчэнняў уключаны вібрасігнал"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Для выклікаў і апавяшчэнняў гук выключаны"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Сістэмныя змены"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Не турбаваць"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Новае: у рэжыме \"Не турбаваць\" апавяшчэнні не паказваюцца"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Дакраніцеся, каб даведацца больш і змяніць."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Зменены налады рэжыму \"Не турбаваць\""</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Націсніце, каб паглядзець заблакіраванае."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Праверце налады апавяшчэнняў"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Пачынаючы з версіі Android 13 усталяваным вамі праграмам неабходна даваць дазвол на адпраўку апавяшчэнняў. Націсніце, каб змяніць дазвол для існуючых праграм."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Нагадаць пазней"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 9b5a825b9e38..38c9d0b7cd94 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"При обаждания и известия устройството ще вибрира"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Обажданията и известията ще бъдат заглушени"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Промени в системата"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Не безпокойте"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Ново: Режимът „Не безпокойте“ скрива известията"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Докоснете, за да научите повече и да извършите промени."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Настройките за „Не безпокойте“ са променени"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Докоснете, за да проверите какво е блокирано."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Преглед на настройките за известия"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"От Android 13 инсталираните от вас приложения трябва да получат разрешението ви, за да изпращат известия. Докоснете, за да промените това разрешение за съществуващите приложения."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Напомняне по-късно"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 0871bfd244fe..8a833c88e44a 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"কল এবং বিজ্ঞপ্তি আসলে ভাইব্রেট হবে"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"কল এবং বিজ্ঞপ্তিগুলি মিউট করা হবে"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"সিস্টেমে হয়ে থাকা পরিবর্তন"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"বিরক্ত করবে না"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"নতুন: \'বিরক্ত করবে না\' মোড চালু আছে, তাই বিজ্ঞপ্তি লুকিয়ে ফেলা হচ্ছে"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"আরও জানতে এবং পরিবর্তন করতে ট্যাপ করুন।"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\'বিরক্ত করবে না\' মোডের সেটিং বদলে গেছে"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"কী কী ব্লক করা আছে তা দেখতে ট্যাপ করুন।"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"বিজ্ঞপ্তির সেটিংস পর্যালোচনা করুন"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 থেকে শুরু করে, বিজ্ঞপ্তি পাঠানোর জন্য আপনার ইনস্টল করা অ্যাপকে অনুমতি নিতে হবে। বর্তমান অ্যাপের জন্য এই অনুমতি পরিবর্তন করতে ট্যাপ করুন।"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"পরে মনে করিয়ে দিও"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 9d5ecdcc1933..9e29b7f7795f 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Pozivi i obavještenja će vibrirati"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Pozivi i obavještenja će se isključiti"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Sistemske promjene"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Ne ometaj"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novo: Način rada Ne ometaj sakriva obavještenja"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Dodirnite da saznate više i izvršite promjene."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Način rada Ne ometaj je promijenjen"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Dodirnite da provjerite šta je blokirano."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Pregledajte postavke obavještenja"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Počevši od Androida 13, aplikacije koje instalirate trebaju odobrenje da šalju obavještenja. Dodirnite da promijenite ovo odobrenje za postojeće aplikacije."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Podsjeti me kasnije"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 5728aed8551a..0dd1bca868ad 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Les trucades i les notificacions vibraran"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Les trucades i les notificacions se silenciaran"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Canvis del sistema"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"No molestis"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novetat: el mode No molestis està amagant notificacions"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Toca per obtenir més informació i canviar la configuració."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"S\'ha canviat el mode No molestis"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Toca per consultar què s\'ha bloquejat."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Consulta la configuració de notificacions"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"A partir de la versió Android 13, les aplicacions que instal·les necessiten el teu permís per enviar notificacions. Toca per canviar aquest permís per a les aplicacions existents."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Recorda-m\'ho més tard"</string> @@ -2394,12 +2389,12 @@ <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Utilitza un altre cable i torna-ho a provar"</string> <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"El dispositiu està massa calent i no pot duplicar a la pantalla fins que es refredi"</string> <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Pantalla dual"</string> - <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"La pantalla dual està activada"</string> + <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Pantalla dual està activada"</string> <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> està utilitzant les dues pantalles per mostrar contingut"</string> <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"El dispositiu està massa calent"</string> - <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"La pantalla dual no està disponible perquè el telèfon està massa calent"</string> - <string name="concurrent_display_notification_power_save_title" msgid="1794569070730736281">"Dual Screen no està disponible"</string> - <string name="concurrent_display_notification_power_save_content" msgid="2198116070583851493">"Dual Screen no està disponible perquè la funció Estalvi de bateria està activada. Pots desactivar aquesta opció a Configuració."</string> + <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Pantalla dual no està disponible perquè el telèfon està massa calent"</string> + <string name="concurrent_display_notification_power_save_title" msgid="1794569070730736281">"Pantalla dual no està disponible"</string> + <string name="concurrent_display_notification_power_save_content" msgid="2198116070583851493">"Pantalla dual no està disponible perquè la funció Estalvi de bateria està activada. Pots desactivar aquesta opció a Configuració."</string> <string name="device_state_notification_settings_button" msgid="691937505741872749">"Ves a Configuració"</string> <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desactiva"</string> <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> configurat"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 2fea7fba45dc..35f269ab48e0 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -2131,11 +2131,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Volání a oznámení budou vibrovat"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Volání a oznámení budou ztlumena"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Změny nastavení systému"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Nerušit"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novinka: Režim Nerušit skrývá oznámení"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Klepnutím zobrazíte další informace a provedete změny."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Nastavení režimu Nerušit se změnilo"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Klepnutím zkontrolujete, co je blokováno."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Zkontrolujte nastavení oznámení"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Počínaje systémem Android 13 od vás nainstalované aplikace potřebují oprávnění k odesílání oznámení. Klepnutím toto oprávnění změníte pro stávající aplikace."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Připomenout později"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index a9626a650cf9..833b0c5f29b1 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Telefonen vibrerer ved opkald og notifikationer"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Der afspilles ikke lyd ved opkald og notifikationer"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Systemændringer"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Forstyr ikke"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Nyhed! Forstyr ikke skjuler notifikationer"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tryk for at få flere oplysninger og foretage ændringer."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Tilstanden Forstyr ikke blev ændret"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tryk for at se, hvad der er blokeret."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Gennemgå indstillinger for notifikationer"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Fra og med Android 13 skal de apps, som du installerer, have din tilladelse til at sende notifikationer. Tryk for at ændre denne indstilling for eksisterende apps."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Påmind mig senere"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index da0e9bd2c835..1318f64178f8 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Gerät vibriert bei Anrufen und Benachrichtigungen"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Anrufe und Benachrichtigungen stummgeschaltet"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Systemänderungen"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Bitte nicht stören"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Neu: Durch „Bitte nicht stören“ werden Benachrichtigungen nicht mehr angezeigt"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Für weitere Informationen und zum Ändern tippen."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"„Bitte nicht stören“ wurde geändert"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tippe, um zu überprüfen, welche Inhalte blockiert werden."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Benachrichtigungseinstellungen überprüfen"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Ab Android 13 benötigen Apps, die du installierst, die Berechtigung zum Senden von Benachrichtigungen. Wenn du diese Berechtigung für bereits installierte Apps ändern möchtest, tippe hier."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Später erinnern"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 0556a0820dea..bccea8f8bc0b 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -507,7 +507,7 @@ <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Επιτρέπει στην εφαρμογή την τροποποίηση καθολικών ρυθμίσεων ήχου, όπως η ένταση και ποιο ηχείο χρησιμοποιείται για έξοδο."</string> <string name="permlab_recordAudio" msgid="1208457423054219147">"εγγράφει ήχο"</string> <string name="permdesc_recordAudio" msgid="5857246765327514062">"Αυτή η εφαρμογή μπορεί να εγγράφει ήχο μέσω του μικροφώνου, όταν τη χρησιμοποιείτε."</string> - <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"εγγραφή ήχου στο παρασκήνιο"</string> + <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"ηχογράφηση στο παρασκήνιο"</string> <string name="permdesc_recordBackgroundAudio" msgid="1992623135737407516">"Αυτή η εφαρμογή μπορεί να εγγράφει ήχο μέσω του μικροφώνου, ανά πάσα στιγμή."</string> <string name="permlab_detectScreenCapture" msgid="4447042362828799433">"ανίχνευση καταγραφών οθόνης που περιέχουν τα παράθυρα της εφαρμογής"</string> <string name="permdesc_detectScreenCapture" msgid="3485784917960342284">"Η εφαρμογή θα λάβει ειδοποίηση όταν ληφθεί ένα στιγμιότυπο οθόνης ενώ βρίσκεται σε χρήση."</string> @@ -541,7 +541,7 @@ <string name="permlab_callCompanionApp" msgid="3654373653014126884">"προβολή και έλεγχος κλήσεων μέσω του συστήματος."</string> <string name="permdesc_callCompanionApp" msgid="8474168926184156261">"Επιτρέπει στην εφαρμογή να βλέπει και να ελέγχει τις εισερχόμενες κλήσεις στη συσκευή. Αυτό περιλαμβάνει πληροφορίες όπως τους αριθμούς κλήσεων για τις κλήσεις και την κατάσταση των κλήσεων."</string> <string name="permlab_exemptFromAudioRecordRestrictions" msgid="1164725468350759486">"εξαίρεση από περιορισμούς εγγραφής ήχου"</string> - <string name="permdesc_exemptFromAudioRecordRestrictions" msgid="2425117015896871976">"Εξαιρέστε την εφαρμογή από περιορισμούς για την εγγραφή ήχου."</string> + <string name="permdesc_exemptFromAudioRecordRestrictions" msgid="2425117015896871976">"Εξαιρέστε την εφαρμογή από περιορισμούς για την ηχογράφηση."</string> <string name="permlab_acceptHandover" msgid="2925523073573116523">"συνέχιση κλήσης από άλλη συσκευή"</string> <string name="permdesc_acceptHandovers" msgid="7129026180128626870">"Επιτρέπει στην εφαρμογή να συνεχίσει μια κλήση η οποία ξεκίνησε σε άλλη εφαρμογή."</string> <string name="permlab_readPhoneNumbers" msgid="5668704794723365628">"ανάγνωση αριθμών τηλεφώνου"</string> @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Θα υπάρχει δόνηση για κλήσεις και ειδοποιήσεις"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Οι κλήσεις και οι ειδοποιήσεις θα τεθούν σε παύση"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Αλλαγές στο σύστημα"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Μην ενοχλείτε"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Νέο: Η λειτουργία \"Μην ενοχλείτε\" αποκρύπτει ειδοποιήσεις"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Πατήστε για να μάθετε περισσότερα και να κάνετε αλλαγές."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Η λειτουργία \"Μην ενοχλείτε\" άλλαξε"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Πατήστε για να ελέγξετε το περιεχόμενο που έχει αποκλειστεί."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Έλεγχος ρυθμίσεων ειδοποιήσεων"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Από το Android 13 και έπειτα, οι εφαρμογές που εγκαθιστάτε θα χρειάζονται την άδειά σας για την αποστολή ειδοποιήσεων. Πατήστε για να αλλάξετε αυτή την άδεια για υπάρχουσες εφαρμογές."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Υπενθύμιση αργότερα"</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 086835c1cd5a..e9239e233092 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Calls and notifications will vibrate"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Calls and notifications will be muted"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"System changes"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Do not disturb"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"New: Do Not Disturb is hiding notifications"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tap to find out more and change."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Do Not Disturb has changed"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tap to check what\'s blocked."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Review notification settings"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Starting in Android 13, apps that you install need your permission to send notifications. Tap to change this permission for existing apps."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Remind me later"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index 88a83b595520..c624e2a724a5 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Calls and notifications will vibrate"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Calls and notifications will be muted"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"System changes"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Do Not Disturb"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"New: Do Not Disturb is hiding notifications"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tap to learn more and change."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Do Not Disturb has changed"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tap to check what\'s blocked."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Review notification settings"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Starting in Android 13, apps that you install need your permission to send notifications. Tap to change this permission for existing apps."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Remind me later"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index ef399b715631..9ffaa5d31e95 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Calls and notifications will vibrate"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Calls and notifications will be muted"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"System changes"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Do not disturb"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"New: Do Not Disturb is hiding notifications"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tap to find out more and change."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Do Not Disturb has changed"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tap to check what\'s blocked."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Review notification settings"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Starting in Android 13, apps that you install need your permission to send notifications. Tap to change this permission for existing apps."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Remind me later"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 94ddc434926f..23441bbb0e4d 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Calls and notifications will vibrate"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Calls and notifications will be muted"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"System changes"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Do not disturb"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"New: Do Not Disturb is hiding notifications"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tap to find out more and change."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Do Not Disturb has changed"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tap to check what\'s blocked."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Review notification settings"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Starting in Android 13, apps that you install need your permission to send notifications. Tap to change this permission for existing apps."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Remind me later"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index a0a891eefac2..b1ba09c406c9 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Calls and notifications will vibrate"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Calls and notifications will be muted"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"System changes"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Do Not Disturb"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"New: Do Not Disturb is hiding notifications"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tap to learn more and change."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Do Not Disturb has changed"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tap to check what\'s blocked."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Review notification settings"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Starting in Android 13, apps that you install need your permission to send notifications. Tap to change this permission for existing apps."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Remind me later"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index cbb30fd70768..89b22b975ef2 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Vibrarán las llamadas y notificaciones"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Se silenciarán las llamadas y notificaciones"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Cambios del sistema"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"No interrumpir"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Nuevo: No interrumpir oculta las notificaciones"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Presiona para obtener más información y realizar cambios."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Se modificó la opción No interrumpir"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Presiona para consultar lo que está bloqueado."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Revisa la configuración de notificaciones"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"A partir de Android 13, las apps que instales necesitarán tu permiso a fin de enviar notificaciones. Presiona para cambiar este permiso para las apps existentes."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Recordarme más tarde"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 23024f097dec..0082adecddce 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -1407,7 +1407,7 @@ <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Se ha detectado un accesorio de audio analógico"</string> <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"El dispositivo adjunto no es compatible con este teléfono. Toca para obtener más información."</string> <string name="adb_active_notification_title" msgid="408390247354560331">"Depuración por USB activa"</string> - <string name="adb_active_notification_message" msgid="5617264033476778211">"Toca para desactivar la depuración por USB"</string> + <string name="adb_active_notification_message" msgid="5617264033476778211">"Toca para desactivar depuración USB"</string> <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Seleccionar para inhabilitar la depuración por USB"</string> <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Depuración inalámbrica conectada"</string> <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Toca para desactivar la depuración inalámbrica"</string> @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Las llamadas y las notificaciones vibrarán"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Las llamadas y las notificaciones se silenciarán"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Cambios del sistema"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"No molestar"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novedad: El modo No molestar oculta las notificaciones"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Toca para obtener más información y hacer cambios."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Ha cambiado el modo No molestar"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Toca para consultar lo que se está bloqueando."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Consulta los ajustes de notificaciones"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"A partir de Android 13, las aplicaciones que instalas necesitan tu permiso para enviar notificaciones. Toca para cambiar este permiso en las aplicaciones que ya tengas."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Recordar más tarde"</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index 326b3db247c8..44f105544454 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Kõnede ja märguannete puhul seade vibreerib"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Kõned ja märguanded on vaigistatud"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Süsteemi muudatused"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Mitte segada"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Uus: režiim Mitte segada peidab märguandeid"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Puudutage lisateabe vaatamiseks ja muutmiseks."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Režiimi Mitte segada muudeti"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Puudutage, et kontrollida, mis on blokeeritud."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Vaadake üle märguandeseaded"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Alates operatsioonisüsteemist Android 13 vajavad installitavad rakendused märguannete saatmiseks teie luba. Puudutage, et muuta seda luba olemasolevate rakenduste jaoks."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Tuleta hiljem meelde"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index d092f46ab6c2..d017a05a57c7 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -745,7 +745,7 @@ <string name="face_error_lockout_screen_lock" msgid="5062609811636860928">"Saiakera gehiegi egin dira. Horren ordez, erabili pantailaren blokeoa."</string> <string name="face_error_unable_to_process" msgid="5723292697366130070">"Ezin da egiaztatu aurpegia. Saiatu berriro."</string> <string name="face_error_not_enrolled" msgid="1134739108536328412">"Ez duzu konfiguratu aurpegi bidez desblokeatzeko eginbidea"</string> - <string name="face_error_hw_not_present" msgid="7940978724978763011">"Aurpegi bidez desblokeatzeko eginbidea ez da bateragarria gailu honekin"</string> + <string name="face_error_hw_not_present" msgid="7940978724978763011">"Aurpegi bidez desblokeatzeko eginbidea ez da onartzen gailu honetan"</string> <string name="face_error_security_update_required" msgid="5076017208528750161">"Sentsorea aldi baterako desgaitu da."</string> <string name="face_name_template" msgid="3877037340223318119">"<xliff:g id="FACEID">%d</xliff:g> aurpegia"</string> <string name="face_app_setting_name" msgid="5854024256907828015">"Erabili aurpegi bidez desblokeatzeko eginbidea"</string> @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Dar-dar egingo du deiak eta jakinarazpenak jasotzean"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Ez da joko tonurik deiak eta jakinarazpenak jasotzean"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Sistema-aldaketak"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Ez molestatzeko modua"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Berria: Ez molestatzeko modua jakinarazpenak ezkutatzen ari da"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Sakatu informazio gehiago lortzeko eta portaera aldatzeko."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Ez molestatzeko modua aldatu da"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Sakatu zer dagoen blokeatuta ikusteko."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Berrikusi jakinarazpen-ezarpenak"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 ezkero, jakinarazpenak bidaltzeko baimena eman behar diezu instalatzen dituzun aplikazioei. Sakatu hau lehendik dauden aplikazioen baimenak aldatzeko."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Gogorarazi geroago"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 6933a16dd97e..ad8f056a8609 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -458,7 +458,7 @@ <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"اجرای سرویس پیشنما از نوع «استفاده ویژه»"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"به برنامه اجازه میدهد از سرویسهای پیشنما از نوع «استفاده ویژه» استفاده کند"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"اندازهگیری اندازه فضای ذخیرهسازی برنامه"</string> - <string name="permdesc_getPackageSize" msgid="742743530909966782">"به برنامه اجازه میدهد تا کدها، دادهها و اندازههای حافظهٔ پنهان خود را بازیابی کند"</string> + <string name="permdesc_getPackageSize" msgid="742743530909966782">"به برنامه اجازه میدهد تا کدها، دادهها و اندازههای حافظه نهان خود را بازیابی کند"</string> <string name="permlab_writeSettings" msgid="8057285063719277394">"تغییر تنظیمات سیستم"</string> <string name="permdesc_writeSettings" msgid="8293047411196067188">"به برنامه اجازه میدهد تا دادههای تنظیم سیستم را تغییر دهد. برنامههای مخرب میتوانند پیکربندی سیستم شما را خراب کنند."</string> <string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"اجرا شدن در هنگام راهاندازی"</string> @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"دستگاهتان برای تماسها و اعلانها میلرزد"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"دستگاهتان برای تماسها و اعلانها بیصدا خواهد شد"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"تغییرات سیستم"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"مزاحم نشوید"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"جدید: «مزاحم نشوید» اعلانها را پنهان میکند"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"برای اطلاعات بیشتر و تغییر دادن، تکضرب بزنید."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"«مزاحم نشوید» تغییر کرده است"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"برای بررسی موارد مسدودشده تکضرب بزنید."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"مرور تنظیمات اعلان"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"از Android نسخه ۱۳ به بعد، برنامههایی که نصب میکنید برای ارسال اعلان به اجازه شما نیاز دارند. برای تغییر دادن این اجازه در برنامههای موجود، تکضرب بزنید."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"بعداً یادآوری شود"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 18c7902511a0..196db127fb0e 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Puhelut ja ilmoitukset värisevät"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Puhelut ja ilmoitukset mykistetään"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Järjestelmän muutokset"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Älä häiritse"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Uutta: Älä häiritse ‑tila piilottaa ilmoitukset"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Napauta, jos haluat lukea lisää ja tehdä muutoksia."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Älä häiritse ‑tila muuttui"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Napauta niin näet, mitä on estetty."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Tarkista ilmoitusasetukset"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Asentamasi sovellukset tarvitsevat sinulta luvan ilmoitusten lähettämiseen Android 13 ‑käyttöjärjestelmästä alkaen. Napauta muuttaaksesi nykyisten sovellusten lupia."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Muistuta myöhemmin"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index bc11e547bb82..ac87d3bac69d 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Les appels et les notifications vibreront"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Les appels et les notifications seront silencieux"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Changements système"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Ne pas déranger"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Nouveau : Le mode Ne pas déranger masque les notifications"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Touchez ici pour en savoir plus et changer les paramètres"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Les paramètres du mode Ne pas déranger ont changé"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Touchez l\'écran pour vérifier ce qui est bloqué."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Examiner les paramètres de notification"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"À partir d\'Android 13, les applis que vous installez ont besoin de votre autorisation pour envoyer des notifications. Touchez pour modifier cette autorisation pour les applis existantes."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Me rappeler plus tard"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 03cf4634bad2..2368c885ccf9 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1407,7 +1407,7 @@ <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Accessoire audio analogique détecté"</string> <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"L\'appareil connecté n\'est pas compatible avec ce téléphone. Appuyez ici pour en savoir plus."</string> <string name="adb_active_notification_title" msgid="408390247354560331">"Débogage USB activé"</string> - <string name="adb_active_notification_message" msgid="5617264033476778211">"Appuyez pour désactiver le débogage USB"</string> + <string name="adb_active_notification_message" msgid="5617264033476778211">"Appuyez pour le désactiver"</string> <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Sélectionnez cette option pour désactiver le débogage USB."</string> <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Débogage sans fil connecté"</string> <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Appuyez pour désactiver le débogage sans fil"</string> @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Les appels et les notifications vibreront"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Les appels et les notifications seront silencieux"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Modifications du système"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Ne pas déranger"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Nouveau : Le mode Ne pas déranger masque les notifications"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Appuyez pour en savoir plus et pour modifier les paramètres."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Le mode Ne pas déranger a été modifié"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Appuyez pour vérifier les contenus bloqués."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Vérifiez les paramètres de notification"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"À partir d\'Android 13, les applications que vous installez ont besoin de votre autorisation pour envoyer des notifications. Appuyez pour modifier cette autorisation pour les applications déjà installées."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Plus tard"</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 430d64918470..2aba79031b69 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"As chamadas e as notificacións vibrarán"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"As chamadas e as notificacións estarán silenciadas"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Cambios no sistema"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Non molestar"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novidade! O modo Non molestar oculta as notificacións"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Toca para obter máis información e facer cambios."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"O modo Non molestar cambiou"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Toca para comprobar o contido bloqueado."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Consulta a configuración de notificacións"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Desde Android 13, as aplicacións que instales necesitan o teu permiso para enviar notificacións. Toca para cambiar este permiso nas aplicacións que xa teñas."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Lembrarmo máis tarde"</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index f40fb93ca6a9..8d90e3b82c92 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"કૉલ અને નોટિફિકેશન માટે ઉપકરણ વાઇબ્રેટ થશે"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"કૉલ અને નોટિફિકેશન મ્યૂટ કરવામાં આવશે"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"સિસ્ટમના ફેરફારો"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"ખલેલ પાડશો નહીં"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"નવું: ખલેલ પાડશો નહીં હવે નોટિફિકેશન છુપાવી શકે છે"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"વધુ જાણવા અને બદલવા માટે ટૅપ કરો."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"ખલેલ પાડશો નહીંમાં ફેરફાર થયો છે"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"શું બ્લૉક કરેલ છે તે તપાસવા માટે ટૅપ કરો."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"નોટિફિકેશનના સેટિંગ રિવ્યૂ કરો"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13થી શરૂઆત કરીને, તમે જે પણ ઍપ ઇન્સ્ટૉલ કરશો, તેને નોટિફિકેશન મોકલવા માટે તમારી પરવાનગીની જરૂર રહેશે. હાલની બધી ઍપ માટે આ પરવાનગીમાં ફેરફાર કરવા માટે ટૅપ કરો."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"મને પછી યાદ અપાવજો"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 0386387fc134..12ffe8774fe8 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"कॉल और सूचनाओं आने पर डिवाइस वाइब्रेट हाेगा"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"कॉल और सूचनाओं के लिए डिवाइस म्यूट रहेगा"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"सिस्टम में हुए बदलाव"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"परेशान न करें"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"नई सुविधा: परेशान न करें सुविधा चालू होने की वजह से सूचनाएं नहीं दिखाई जा रही हैं"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ज़्यादा जानने और बदलाव करने के लिए टैप करें."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"परेशान न करें की सुविधा बदल गई है"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"टैप करके देखें कि किन चीज़ों पर रोक लगाई गई है."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"सूचना सेटिंग देखें"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 में जो ऐप्लिकेशन इंस्टॉल किए जाएंगे, उन्हें आपको सूचनाएं भेजने के लिए अनुमति लेनी होगी. पहले से इंस्टॉल किए गए ऐप्लिकेशन को दी गई अनुमति बदलने के लिए टैप करें."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"बाद में याद दिलाएं"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 54dc55de7991..895c3fa420ec 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Uređaj će vibrirati za pozive i obavijesti"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Zvučni signal poziva i obavijesti bit će isključen"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Promjene sustava"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Ne uznemiravaj"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novo: način Ne uznemiravaj sakriva obavijesti"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Dodirnite da biste saznali više i promijenili postavke."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Promijenjena je postavka Ne uznemiravaj"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Dodirnite da biste provjerili što je blokirano."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Pregledajte postavke obavijesti"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Od Androida 13 aplikacije koje instalirate trebaju vaše dopuštenje za slanje obavijesti. Dodirnite da biste promijenili to dopuštenje za postojeće aplikacije."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Podsjeti me kasnije"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 179de2009dc5..3bbaef2b18ac 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"A hívások és az értesítések rezegnek"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"A hívások és az értesítések némák"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Rendszermódosítások"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Ne zavarjanak"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Újdonság: A Ne zavarjanak mód elrejti az értesítéseket"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Koppintással további információhoz juthat, és elvégezheti a módosítást."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Módosultak a Ne zavarjanak mód beállításai"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Koppintson a letiltott elemek megtekintéséhez."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Értesítési beállítások áttekintése"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Az Android 13-as rendszertől kezdődően a telepített alkalmazásoknak engedélyre van szükségük értesítések küldéséhez. Koppintással módosíthatja ezt az engedélyt a meglévő alkalmazások esetében."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Emlékeztessen később"</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 312a105285e1..d341adafd871 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Զանգերի և ծանուցումների համար թրթռոցը միացված է"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Զանգերի և ծանուցումների համար ձայնն անջատված է"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Համակարգի փոփոխություններ"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Չանհանգստացնել"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Այժմ «Չանհանգստացնել» ռեժիմում ծանուցումները թաքցվում են"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Հպեք՝ ավելին իմանալու և կարգավորումները փոխելու համար:"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"«Չանհանգստացնել» ռեժիմի կարգավորումները փոխվել են"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Հպեք՝ տեսնելու, թե ինչ է արգելափակվել:"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Ստուգեք ծանուցումների կարգավորումները"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Հավելվածներին, որոնք տեղադրում եք Android 13 և ավելի նոր տարբերակներով սարքերում, անհրաժեշտ է տրամադրել ծանուցումներ ուղարկելու թույլտվություն։ Հպեք և փոխեք այս թույլտվությունն արդեն տեղադրված հավելվածների համար։"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Հիշեցնել ավելի ուշ"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index e830d6d10e0e..1d205264af99 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Panggilan dan notifikasi akan bergetar"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Suara panggilan dan notifikasi akan dinonaktifkan"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Perubahan sistem"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Jangan Ganggu"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Baru: Mode Jangan Ganggu menyembunyikan notifikasi"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Ketuk untuk mempelajari lebih lanjut dan mengubah."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Jangan Ganggu telah berubah"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Ketuk untuk memeriksa item yang diblokir."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Tinjau setelan notifikasi"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Mulai Android 13, aplikasi yang Anda instal memerlukan izin untuk mengirim notifikasi. Ketuk guna mengubah izin ini untuk aplikasi yang sudah ada."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Ingatkan saya nanti"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 307fb529b903..b6d1c12549df 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Titringur er virkur fyrir símtöl og tilkynningar"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Slökkt verður á hljóði símtala og tilkynninga"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Breytingar á kerfi"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Ónáðið ekki"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Nýtt: „Ónáðið ekki“ er að fela tilkynningar"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Ýttu til að fá frekari upplýsingar og breyta."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"„Ónáðið ekki“ var breytt"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Ýttu til að skoða hvað lokað hefur verið á."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Yfirfara tilkynningastillingar"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Frá og með Android 13 þurfa forrit sem þú setur upp heimild frá þér til að senda tilkynningar. Ýttu til að breyta þessari heimild fyrir forrit sem fyrir eru."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Minna mig á seinna"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 08ea1f1adee4..66e5f72fcabb 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"La vibrazione sarà attiva per chiamate e notifiche"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"L\'audio di chiamate e notifiche sarà disattivato"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Modifiche al sistema"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Non disturbare"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novità: la modalità Non disturbare nasconde le notifiche"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tocca per avere ulteriori informazioni e modificare."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"L\'impostazione Non disturbare è cambiata"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tocca per controllare le notifiche bloccate."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Controlla le impostazioni di notifica"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"A partire da Android 13, le app che installi devono avere la tua autorizzazione per poter inviare notifiche. Tocca per cambiare questa autorizzazione per le app esistenti."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Ricordamelo dopo"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 1c1918cac58b..8f4fbcd76939 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"שיחות והודעות ירטטו"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"שיחות והתראות יושתקו"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"שינויים במערכת"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"נא לא להפריע"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"חדש: מצב \'נא לא להפריע\' מסתיר התראות"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"אפשר להקיש כדי לקבל מידע נוסף ולבצע שינויים."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"ההגדרה \'נא לא להפריע\' השתנתה"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"יש להקיש כדי לבדוק מה חסום."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"בדיקת הגדרת ההתראות"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"החל מגרסת Android 13, אפליקציות שיותקנו יוכלו לשלוח התראות רק אם יקבלו ממך הרשאה. אפשר להקיש כדי לשנות את ההרשאה הזו באפליקציות קיימות."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"תזכירו לי מאוחר יותר"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 36d956c3bdd0..cd5527c80cba 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"着信や通知をバイブレーションで知らせます"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"着信音と通知音が鳴りません"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"システムの変更"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"サイレント モード"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"新機能: サイレント モードでは通知が非表示になります"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"タップすると、詳細を確認して設定を変更できます。"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"サイレント モードが変わりました"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"タップしてブロック対象をご確認ください。"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"通知設定の確認"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 以降では、インストールするアプリに、通知を送信する権限を付与する必要があります。既存のアプリのこの権限を変更するには、タップしてください。"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"後で"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 9a88e545b0c6..9b1c07fb2af6 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"ზარების და შეტყობინებების მიღებისას ვიბრაცია ჩაირთვება"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"ზარები და შეტყობინებები დადუმებული იქნება"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"სისტემის ცვლილებები"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"არ შემაწუხოთ"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"ახალი: „არ შემაწუხოთ“ რეჟიმი მალავს შეტყობინებებს"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"შეეხეთ მეტის გასაგებად და შესაცვლელად."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"„არ შემაწუხოთ“ რეჟიმი შეცვლილია"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"შეეხეთ იმის სანახავად, თუ რა არის დაბლოკილი."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"შეტყობინების პარამეტრების შემოწმება"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13-ზე შეტყობინებების გასაგზავნად საჭიროა თქვენ მიერ დაინსტალირებული აპებისთვის ნებართვის მინიჭება. არსებული აპებისთვის ამ ნებართვის შესაცვლელად შეეხეთ."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"შემახსენე მოგვიან."</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 595b9baaa254..ebf627f763ba 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Қоңыраулар мен хабарландырулардың дірілі болады."</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Қоңыраулар мен хабарландырулардың дыбыстық сигналы өшіріледі"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Жүйе өзгерістері"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Мазаламау режимі"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Жаңа: Мазаламау режимі хабарландыруларды жасыруда"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Толығырақ ақпарат алу және өзгерту үшін түртіңіз."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Мазаламау режимі өзгерді"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Түймені түртіп, неге тыйым салынатынын көріңіз."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Хабарландыру параметрлерін қарау"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 нұсқасынан бастап орнатылатын қолданбалар үшін хабарландыру жіберу рұқсаты керек. Бұрынғы қолданбаларда осы рұқсатты өзгерту үшін түртіңіз."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Кейінірек еске салу"</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 696bd79509ac..df7006ace657 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"ការហៅទូរសព្ទ និងការជូនដំណឹងនឹងញ័រ"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"ការហៅទូរសព្ទ និងការជូនដំណឹងនឹងបិទសំឡេង"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"ការផ្លាស់ប្ដូរប្រព័ន្ធ"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"កុំរំខាន"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"ថ្មី៖ មុខងារកុំរំខានកំពុងលាក់ការជូនដំណឹង"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ចុចដើម្បីស្វែងយល់បន្ថែម និងផ្លាស់ប្ដូរ។"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"មុខងារកុំរំខានត្រូវបានប្ដូរ"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"សូមចុចដើម្បីមើលថាបានទប់ស្កាត់អ្វីខ្លះ។"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"ពិនិត្យមើលការកំណត់ការជូនដំណឹង"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"ចាប់ពី Android 13 ឡើងទៅ កម្មវិធីដែលអ្នកដំឡើងត្រូវការការអនុញ្ញាតរបស់អ្នក ដើម្បីផ្ញើការជូនដំណឹង។ សូមចុចដើម្បីផ្លាស់ប្ដូរការអនុញ្ញាតនេះសម្រាប់កម្មវិធីដែលមានស្រាប់។"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"រំលឹកខ្ញុំពេលក្រោយ"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 419dd17d233c..5ddb586b541e 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"ಕರೆಗಳು ಮತ್ತು ಅಧಿಸೂಚನೆಗಳು ವೈಬ್ರೇಟ್ ಆಗುತ್ತವೆ"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"ಕರೆಗಳು ಮತ್ತು ಅಧಿಸೂಚನೆಗಳನ್ನು ಮ್ಯೂಟ್ ಮಾಡಲಾಗುತ್ತದೆ"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"ಸಿಸ್ಟಂ ಬದಲಾವಣೆಗಳು"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಮೋಡ್ ಅಧಿಸೂಚನೆಗಳನ್ನು ಮರೆಮಾಡುತ್ತಿದೆ"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಮತ್ತು ಬದಲಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಬದಲಾಗಿದೆ"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"ಏನನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ ಎಂಬುದನ್ನು ಪರೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"ನೋಟಿಫಿಕೇಶನ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 ನಿಂದ ಪ್ರಾರಂಭಿಸಿ, ನೀವು ಇನ್ಸ್ಟಾಲ್ ಮಾಡುವ ಆ್ಯಪ್ಗಳಿಗೆ, ಅಧಿಸೂಚನೆಗಳನ್ನು ಕಳುಹಿಸಲು ನಿಮ್ಮ ಅನುಮತಿಯ ಅಗತ್ಯವಿದೆ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಆ್ಯಪ್ಗಳಿಗಾಗಿ ಈ ಅನುಮತಿಯನ್ನು ಬದಲಾಯಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"ನಂತರ ರಿಮೈಂಡ್ ಮಾಡಿ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 5f0e1f9760e0..92ca1d529563 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"전화 및 알림이 오면 진동이 사용됩니다."</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"전화 및 알림 소리가 음소거됩니다."</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"시스템 변경사항"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"방해 금지 모드"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"새로운 기능: 방해 금지 모드로 알림 숨기기"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"자세히 알아보고 변경하려면 탭하세요."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"방해 금지 모드 변경"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"차단된 항목을 확인하려면 탭하세요."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"알림 설정 검토"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13부터 설치된 앱에는 알림을 전송하기 위한 권한이 필요합니다. 기존 앱의 알림 전송 권한을 변경하려면 탭하세요."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"나중에 알림"</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index 14e1064a9aec..a4380253cd73 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Чалуулар менен билдирмелер дирилдөө режиминде иштейт"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Чалуулар менен эскертмелердин үнү өчүрүлөт"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Система өзгөрүүлөрү"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Тынчымды алба"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Жаңы: \"Тынчымды алба\" режими билдирмелерди жашырууда"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Көбүрөөк маалымат алып, өзгөртүү үчүн таптаңыз."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\"Тынчымды алба\" режими өзгөрдү"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Бөгөттөлгөн нерселерди көрүү үчүн таптаңыз."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Билдирмелердин параметрлерин карап чыгуу"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 версиясынан баштап билдирмелерди жөнөтүү үчүн орноткон колдонмолоруңузга уруксат берүү керек. Учурдагы колдонмолор үчүн бул уруксатты өзгөртүү үчүн таптап коюңуз."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Кийинчерээк эскертүү"</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index fb677cf1e44f..be09c1081f28 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"ການໂທ ແລະ ການແຈ້ງເຕືອນຈະສັ່ນ"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"ການໂທ ແລະ ການແຈ້ງເຕືອນຈະບໍ່ມີສຽງ"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"ການປ່ຽນແປງລະບົບ"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"ຫ້າມລົບກວນ"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"ໃໝ່: ໂໝດຫ້າມລົບກວນຈະເຊື່ອງການແຈ້ງເຕືອນໄວ້"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ແຕະເພື່ອສຶກສາເພີ່ມເຕີມ ແລະ ປ່ຽນແປງ."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"ປ່ຽນໂໝດຫ້າມລົບກວນແລ້ວ"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"ແຕະເພື່ອກວດສອບວ່າມີຫຍັງຖືກບລັອກໄວ້ແດ່."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"ກວດສອບການຕັ້ງຄ່າການແຈ້ງເຕືອນ"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"ເລີ່ມຕົ້ນໃນ Android 13, ແອັບຕ່າງໆທີ່ທ່ານຕິດຕັ້ງຈະຕ້ອງໃຊ້ການອະນຸຍາດຂອງທ່ານເພື່ອສົ່ງການແຈ້ງເຕືອນ. ແຕະເພື່ອປ່ຽນການອະນຸຍາດນີ້ສຳລັບແອັບທີ່ມີຢູ່ກ່ອນແລ້ວ."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"ແຈ້ງເຕືອນຂ້ອຍພາຍຫຼັງ"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index e617a4cfbfc6..45998ee38787 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -2131,11 +2131,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Skambučiai ir pranešimai vibruos"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Skambučiai ir pranešimai bus nutildyti"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Sistemos pakeitimai"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Netrukdymo režimas"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Naujiena: naudojant netrukdymo režimą pranešimai slepiami"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Palieskite, kad sužinotumėte daugiau ir pakeistumėte."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Netrukdymo režimas pakeistas"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Palieskite, kad patikrintumėte, kas blokuojama."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Peržiūrėkite pranešimų nustatymus"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Tryliktos ir naujesnių versijų „Android” jūsų įdiegtoms programoms reikia suteikti leidimą siųsti pranešimus. Palieskite, kad pakeistumėte šį leidimą esamoms programoms."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Priminti vėliau"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index b04dd4521a31..973d8e2c0568 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Zvaniem un paziņojumiem tiks aktivizēta vibrācija."</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Zvanu un paziņojumu signāla skaņa būs izslēgta."</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Sistēmas izmaiņas"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Netraucēt"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Jaunums: režīmā “Netraucēt” paziņojumi tiek paslēpti"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Pieskarieties, lai uzzinātu vairāk un veiktu izmaiņas."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Režīms “Netraucēt” ir mainīts"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Pieskarieties, lai uzzinātu, kas tiek bloķēts."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Pārskatīt paziņojumu iestatījumus"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Operētājsistēmā Android 13 un jaunākās versijās jūsu instalētajām lietotnēm ir nepieciešama atļauja sūtīt paziņojumus. Pieskarieties, lai mainītu šo atļauju esošajām lietotnēm."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Atgādināt vēlāk"</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index b0d6351f5667..3943dc359bd9 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Повиците и известувањата ќе вибрираат"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Повиците и известувањата нема да имаат звук"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Системски промени"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Не вознемирувај"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Ново: режимот „Не вознемирувај“ ги крие известувањата"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Допрете за да дознаете повеќе и да ги промените поставките."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Поставките за „Не вознемирувај“ се изменија"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Допрете за да проверите што е блокирано."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Прегледајте ги поставките за известувања"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Почнувајќи од Android 13, на апликациите што ги инсталирате им е потребна ваша дозвола за испраќање известувања. Допрете за да ја промените оваа дозвола за постојни апликации."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Потсети ме подоцна"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index cc545e29ac4f..242e9679baf6 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"കോളുകളും അറിയിപ്പുകളും വൈബ്രേറ്റ് ചെയ്യും"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"കോളുകളും അറിയിപ്പുകളും മ്യൂട്ട് ചെയ്യപ്പെടും"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"സിസ്റ്റത്തിലെ മാറ്റങ്ങൾ"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"ശല്യപ്പെടുത്തരുത്"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"പുതിയത്: അറിയിപ്പുകളെ \'ശല്യപ്പെടുത്തരുത്\' അദൃശ്യമാക്കുന്നു"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"കൂടുതലറിയാനും മാറ്റാനും ടാപ്പ് ചെയ്യുക."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\'ശല്യപ്പെടുത്തരുത്\' മാറ്റി"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"എന്തിനെയാണ് ബ്ലോക്ക് ചെയ്തതെന്ന് പരിശോധിക്കാൻ ടാപ്പ് ചെയ്യുക."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"അറിയിപ്പ് ക്രമീകരണം അവലോകനം ചെയ്യുക"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 മുതൽ, നിങ്ങൾ ഇൻസ്റ്റാൾ ചെയ്യുന്ന ആപ്പുകൾക്ക് അറിയിപ്പുകൾ അയയ്ക്കാൻ നിങ്ങളുടെ അനുമതി വേണം. നിലവിലുള്ള ആപ്പുകൾക്ക് ഈ അനുമതി മാറ്റാൻ ടാപ്പ് ചെയ്യുക."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"പിന്നീട് ഓർമ്മിപ്പിക്കൂ"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index 87ce94ba6939..c8f2eaaf0b5c 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Дуудлага болон мэдэгдэл чичирнэ"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Дуудлага болон мэдэгдлийн дууг хаана"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Системийн өөрчлөлт"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Бүү саад бол"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Шинэ: Бүү саад бол горим мэдэгдлийг нууж байна"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Илүү ихийг мэдэж, өөрчлөхийн тулд товшино уу."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Бүү саад бол горимыг өөрчилсөн"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Блоклосон зүйлийг шалгахын тулд товшино уу."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Мэдэгдлийн тохиргоог шалгах"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13-аас эхлэн таны суулгасан аппууд мэдэгдэл илгээхийн тулд танаас зөвшөөрөл авах шаардлагатай. Одоо байгаа аппуудын уг зөвшөөрлийг өөрчлөхийн тулд товшино уу."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Надад дараа сануул"</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 03cabc31f573..9980d9f5e4c8 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"कॉल आणि सूचनांवर व्हायब्रेट होईल"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"कॉल आणि सूचना म्यूट केल्या जातील"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"सिस्टम बदल"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"व्यत्यय आणू नका"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"व्यत्यय आणू नका सूचना लपवत आहे"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"अधिक जाणून घेण्यासाठी आणि बदलण्यासाठी टॅप करा."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"व्यत्यय आणू नका बदलले आहे"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"काय ब्लॉक केले आहे हे तपासण्यासाठी टॅप करा."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"सूचना सेटिंग्जचे पुनरावलोकन करा"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 पासून, तुम्ही त्यामध्ये इंस्टॉल केलेल्या अॅप्सना सूचना पाठवण्यासाठी तुमच्या परवानगीची आवश्यकता आहे. सध्याच्या अॅप्ससाठी ही परवानगी बदलण्याकरिता टॅप करा."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"मला आठवण करून द्या"</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index 57f1472b6f34..e8116355477e 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Panggilan dan pemberitahuan akan bergetar"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Panggilan dan pemberitahuan akan diredamkan"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Perubahan sistem"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Jangan Ganggu"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Baharu: Jangan Ganggu menyembunyikan pemberitahuan"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Ketik untuk mengetahui lebih lanjut dan menukar tetapan."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Jangan Ganggu telah berubah"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Ketik untuk menyemak item yang disekat."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Semak tetapan pemberitahuan"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Bermula dengan Android 13, apl yang anda pasang memerlukan kebenaran anda untuk menghantar pemberitahuan. Ketik untuk menukar kebenaran ini bagi apl sedia ada."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Ingatkan saya nanti"</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index f568d7112cc0..7088a15797f3 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -322,7 +322,7 @@ <string name="permgrouplab_location" msgid="1858277002233964394">"တည်နေရာ"</string> <string name="permgroupdesc_location" msgid="1995955142118450685">"ဤစက်ပစ္စည်း၏ တည်နေရာကို ရယူရန်"</string> <string name="permgrouplab_calendar" msgid="6426860926123033230">"ပြက္ခဒိန်"</string> - <string name="permgroupdesc_calendar" msgid="6762751063361489379">"သင့်ပြက္ခဒိန်အား ဝင်ရောက်သုံးရန်"</string> + <string name="permgroupdesc_calendar" msgid="6762751063361489379">"သင့်ပြက္ခဒိန်အား ဝင်သုံးရန်"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS စာတိုစနစ်"</string> <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS စာများကို ပို့ကာ ကြည့်မည်"</string> <string name="permgrouplab_storage" msgid="17339216290379241">"ဖိုင်များ"</string> @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"ခေါ်ဆိုမှုများနှင့် အကြောင်းကြားချက်များ တုန်ခါပါမည်"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"ခေါ်ဆိုမှုများနှင့် အကြောင်းကြားချက်များကို အသံပိတ်ထားပါမည်"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"စနစ် အပြောင်းအလဲများ"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"မနှောင့်ယှက်ရ"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"အသစ်− \'မနှောင့်ယှက်ရ\' က အကြောင်းကြားချက်များကို ဖျောက်ထားသည်"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ပိုမိုလေ့လာရန်နှင့် ပြောင်းလဲရန် တို့ပါ။"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\'မနှောင့်ယှက်ရ\' ပြောင်းလဲသွားပါပြီ"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"ပိတ်ထားသည့်အရာများကို ကြည့်ရန် တို့ပါ။"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"အကြောင်းကြားချက် ဆက်တင်များ စိစစ်ရန်"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 မှစ၍ ထည့်သွင်းသော အက်ပ်များသည် အကြောင်းကြားချက်များပို့ရန် သင်၏ခွင့်ပြုချက် လိုအပ်ပါမည်။ ရှိပြီးသားအက်ပ်များအတွက် ဤခွင့်ပြုချက်ကိုပြောင်းရန် တို့ပါ။"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"နောက်မှ သတိပေးပါ"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 6d24bdfc39b3..f39a4f8a1a8e 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Anrop og varsler vibrerer"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Anrop og varsler er lydløse"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Systemendringer"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Ikke forstyrr"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Nytt: «Ikke forstyrr» skjuler varsler"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Trykk for å finne ut mer og endre."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Ikke forstyrr er endret"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Trykk for å sjekke hva som er blokkert."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Gjennomgå varslingsinnstillingene"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Fra og med Android 13 må apper du installerer, få tillatelse til å sende varsler. Trykk for å endre denne tillatelsen for eksisterende apper."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Påminn meg senere"</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 914c04c65495..82052b5b2806 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"कल तथा सूचनाहरू आउँदा कम्पन हुने छ"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"कल तथा सूचनाहरूलाई म्युट गरिने छ"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"प्रणालीसम्बन्धी परिवर्तनहरू"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"बाधा नपुऱ्याउनुहोस्"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"नयाँ: बाधा नपुर्याउनुहोस् नामक मोडले सूचनाहरू लुकाइरहेको छ"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"थप जान्न र परिवर्तन गर्न ट्याप गर्नुहोस्।"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"बाधा नपुर्याउनुहोस् मोड परिवर्तन भएको छ"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"रोक लगाइएका कुराहरू जाँच गर्न ट्याप गर्नुहोस्।"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"सूचनाका सेटिङको समीक्षा गर्नुहोस्"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android १३ मा तपाईंले अनुमति दिनुभएका खण्डमा मात्र तपाईंले इन्स्टल गर्नुभएका एपले सूचना पठाउन सक्छन्। यसअघि इन्स्टल गरिसकिएका एपका हकमा यो अनुमति परिवर्तन गर्न ट्याप गर्नुहोस्।"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"मलाई पछि स्मरण गराइयोस्"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index d2ec4ba725a3..f591754aafb6 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Trillen bij gesprekken en meldingen"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Telefoon- en meldingsgeluid wordt uitgezet"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Systeemwijzigingen"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Niet storen"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Nieuw: \'Niet storen\' verbergt meldingen"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tik voor meer informatie en om te wijzigen."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\'Niet storen\' is gewijzigd"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tik om te controleren wat er is geblokkeerd."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Instellingen voor meldingen bekijken"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Vanaf Android 13 hebben de apps die je installeert je toestemming nodig om meldingen te sturen. Tik om deze toestemming voor bestaande apps te wijzigen."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Later herinneren"</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 85a6aecda0bd..1a952a3a8e14 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"କଲ୍ ଓ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଭାଇବ୍ରେଟ୍ ହେବ"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"କଲ୍ ଓ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ନିଃଶବ୍ଦ କରିଦିଆଯିବ"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"ସିଷ୍ଟମ୍ରେ ପରିବର୍ତ୍ତନ"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"ନୂଆ: \"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ମୋଡ୍ ଅନ୍ ଥିବା ଯୋଗୁଁ ବିଜ୍ଞପ୍ତି ଲୁଚାଇ ଦିଆଯାଉଛି"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ଅଧିକ ଜାଣିବାକୁ ଟ୍ୟାପ୍ କରନ୍ତୁ ଏବଂ ବଦଳାନ୍ତୁ।"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"’ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ’ ବଦଳିଯାଇଛି"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"କ’ଣ ଅବରୋଧ ହୋଇଛି ଯାଞ୍ଚ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"ବିଜ୍ଞପ୍ତି ସେଟିଂସକୁ ସମୀକ୍ଷା କରନ୍ତୁ"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13ଠାରୁ, ଆପଣ ଇନଷ୍ଟଲ କରୁଥିବା ଆପ୍ସ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ପଠାଇବା ପାଇଁ ଆପଣଙ୍କ ଅନୁମତି ଆବଶ୍ୟକ କରେ। ପୂର୍ବରୁ ଥିବା ଆପ୍ସ ପାଇଁ ଏହି ଅନୁମତିକୁ ପରିବର୍ତ୍ତନ କରିବାକୁ ଟାପ କରନ୍ତୁ।"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"ମୋତେ ପରେ ରିମାଇଣ୍ଡ କର"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 51d71ff28260..69535091213a 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"ਕਾਲਾਂ ਅਤੇ ਸੂਚਨਾਵਾਂ ਦੀ ਥਰਥਰਾਹਟ ਹੋਵੇਗੀ"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"ਕਾਲਾਂ ਅਤੇ ਸੂਚਨਾਵਾਂ ਨੂੰ ਮਿਊਟ ਕੀਤਾ ਜਾਵੇਗਾ"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"ਸਿਸਟਮ ਬਦਲਾਅ"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"ਨਵਾਂ: \'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਮੋਡ ਸੂਚਨਾਵਾਂ ਨੂੰ ਲੁਕਾ ਰਿਹਾ ਹੈ"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ਹੋਰ ਜਾਣਨ ਲਈ ਅਤੇ ਬਦਲਾਅ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਵਿਕਲਪ ਬਦਲ ਗਿਆ ਹੈ"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"ਟੈਪ ਕਰਕੇ ਦੋਖੋ ਕਿ ਕਿਹੜੀਆਂ ਚੀਜ਼ਾਂ ਬਲਾਕ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ।"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"ਸੂਚਨਾ ਸੈਟਿੰਗਾਂ ਦੀ ਸਮੀਖਿਆ ਕਰੋ"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 ਜਾਂ ਇਸ ਤੋਂ ਬਾਅਦ ਵਾਲੇ ਵਰਜਨਾਂ ਵਿੱਚ, ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਜਾਣ ਵਾਲੀਆਂ ਐਪਾਂ ਨੂੰ ਸੂਚਨਾਵਾਂ ਭੇਜਣ ਲਈ ਤੁਹਾਡੀ ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ। ਮੌਜੂਦਾ ਐਪਾਂ ਲਈ ਇਸ ਇਜਾਜ਼ਤ ਨੂੰ ਬਦਲਣ ਵਾਸਤੇ ਟੈਪ ਕਰੋ।"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"ਬਾਅਦ ਵਿੱਚ ਯਾਦ ਕਰਵਾਓ"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 49c30c771044..065e9bae5334 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -2131,11 +2131,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Wibracje przy połączeniach i powiadomieniach"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Wyciszenie połączeń i powiadomień"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Zmiany w systemie"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Nie przeszkadzać"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Nowość: w trybie Nie przeszkadzać powiadomienia są ukrywane"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Kliknij, by dowiedzieć się więcej i zmienić ustawienia."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Zmiany w trybie Nie przeszkadzać"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Kliknij, by sprawdzić, co jest zablokowane."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Sprawdź ustawienia powiadomień"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"W Androidzie 13 i nowszych zainstalowane aplikacje będą potrzebowały zezwolenia na wysyłanie powiadomień. Kliknij, aby zmienić uprawnienia dla istniejących aplikacji."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Przypomnij później"</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 99ef60484276..c972e7afa3b1 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Chamadas e notificações farão o dispositivo vibrar"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Chamadas e notificações ficarão silenciadas"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Alterações do sistema"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Não perturbe"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novo: o modo Não perturbe está ocultando as notificações"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Toque para saber mais e fazer alterações."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"O modo \"Não perturbe\" foi alterado"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Toque para verificar o que está bloqueado."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Revise as configurações de notificação"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"No Android 13 ou em versões mais recentes, os apps que você instala precisam de permissão para enviar notificações. Toque para mudar essa permissão para os apps já instalados."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Lembrar mais tarde"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 12245b9a65e3..8dddd95b87cc 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"As chamadas e as notificações vibram."</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"É desativado o som das chamadas e das notificações."</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Alterações ao sistema"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Não incomodar"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novo: o modo Não incomodar está a ocultar as notificações"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Toque para saber mais e alterar."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"O modo Não incomodar foi alterado"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Toque para verificar o que está bloqueado."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Analise as definições de notificação"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"A partir do Android 13, as apps que instalar precisam da sua autorização para enviar notificações. Toque para alterar esta autorização para as apps existentes."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Lembrar mais tarde"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 99ef60484276..c972e7afa3b1 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Chamadas e notificações farão o dispositivo vibrar"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Chamadas e notificações ficarão silenciadas"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Alterações do sistema"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Não perturbe"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novo: o modo Não perturbe está ocultando as notificações"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Toque para saber mais e fazer alterações."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"O modo \"Não perturbe\" foi alterado"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Toque para verificar o que está bloqueado."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Revise as configurações de notificação"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"No Android 13 ou em versões mais recentes, os apps que você instala precisam de permissão para enviar notificações. Toque para mudar essa permissão para os apps já instalados."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Lembrar mais tarde"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 85f859240b7f..014a11543ea2 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Apelurile și notificările vor vibra"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Apelurile și notificările vor avea sunetul dezactivat"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Modificări de sistem"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Nu deranja"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Funcția nouă Nu deranja ascunde notificările"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Atinge ca să afli mai multe și să modifici"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Funcția Nu deranja s-a schimbat"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Atinge pentru a verifica ce este blocat."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Verifică setările pentru notificări"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Începând cu Android 13, aplicațiile pe care le instalezi necesită permisiunea de a trimite notificări. Atinge ca să modifici permisiunea pentru aplicațiile existente."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Mai târziu"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 65597649917c..1e819d607858 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -2131,11 +2131,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Для звонков и уведомлений включен вибросигнал."</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Для звонков и уведомлений отключен звук."</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Системные изменения"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Не беспокоить"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Теперь в режиме \"Не беспокоить\" уведомления не приходят"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Нажмите, чтобы узнать больше и изменить настройки."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Настройки режима \"Не беспокоить\" изменены"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Нажмите, чтобы проверить настройки."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Проверьте настройки уведомлений"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"В Android 13 и более поздних версий приложения могут отправлять вам уведомления только в том случае, если вы предоставили им такое разрешение. Нажмите, чтобы настроить разрешения для установленных приложений."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Напомнить позже"</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index be4151280e3a..8c808038f898 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"ඇමතුම් සහ දැනුම්දීම් කම්පනය වනු ඇත"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"ඇමතුම් සහ දැනුම්දීම් නිහඬ වනු ඇත"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"පද්ධති වෙනස් කිරීම්"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"බාධා නොකරන්න"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"නව: බාධා නොකරන්න දැනුම්දීම් සඟවමින්"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"තව දැන ගැනීමට සහ වෙනස් කිරීමට තට්ටු කරන්න."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"බාධා නොකරන්න වෙනස් කර ඇත"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"අවහිර කර ඇති දේ පරීක්ෂා කිරීමට තට්ටු කරන්න."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"දැනුම්දීම් සැකසීම් සමාලෝචනය කරන්න"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 හි සිට ආරම්භ වෙමින්, ඔබ ස්ථාපනය කරන යෙදුම්වලට දැනුම්දීම් යැවීමට ඔබගේ අවසරය අවශ්ය වේ. තිබෙන යෙදුම් සඳහා මෙම අවසරය වෙනස් කිරීමට තට්ටු කරන්න."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"මට පසුව මතක් කරන්න"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index 61d322951879..cb3cd610c678 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -2131,11 +2131,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Hovory a upozornenia budú vibrovať"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Hovory a upozornenia budú stlmené"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Zmeny systému"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Režim bez vyrušení"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novinka: režim bez vyrušení skrýva upozornenia"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Klepnutím získate ďalšie informácie a budete môcť vykonať zmeny."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Režim bez vyrušení sa zmenil"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Klepnutím skontrolujete, čo je blokované."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Kontrola nastavení upozornení"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"V Androide verzie 13 a novších vyžadujú nainštalované aplikácie povolenie, aby mohli odosielať upozornenia. Klepnutím môžete zmeniť toto povolenie pre existujúce aplikácie."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Pripomenúť neskôr"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index ed8cf505d7eb..5378875ed2f2 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -2131,11 +2131,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Vibriranje bo vklopljeno za klice in obvestila"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Zvonjenje bo izklopljeno za klice in obvestila"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Sistemske spremembe"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Ne moti"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Novi način »ne moti« skriva obvestila"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Dotaknite se, če želite izvedeti več in spremeniti."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Način »ne moti« je spremenjen"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Dotaknite se, da preverite, kaj je blokirano."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Preglejte nastavitve obvestil"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"V Androidu 13 in novejših različicah bodo aplikacije, ki jih namestite, za pošiljanje obvestil potrebovale vaše dovoljenje. Dotaknite se, če želite spremeniti to dovoljenje za obstoječe aplikacije."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Opomni me pozneje"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index e24e310e5772..4c8dfbcf6f1e 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Do të lëshojë dridhje për telefonatat dhe njoftimet"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Do të hiqet zëri për telefonatat dhe njoftimet"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Ndryshimet e sistemit"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Mos shqetëso"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"E re: Modaliteti \"Mos shqetëso\" po fsheh njoftimet"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Trokit për të mësuar më shumë dhe për të ndryshuar."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\"Mos shqetëso\" ka ndryshuar"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Trokit për të shënuar atë që është bllokuar"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Rishiko cilësimet e njoftimeve"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Nga Android 13, aplikacionet që instalon kanë nevojë për lejen tënde për të dërguar njoftime. Trokit për ta ndryshuar këtë leje për aplikacionet ekzistuese."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Më kujto më vonë"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 915486e990e9..c9f44dbbfc43 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -2130,11 +2130,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Вибрација за позиве и обавештења је укључена"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Мелодија звона за позиве и обавештење је искључена"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Системске промене"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Не узнемиравај"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Ново: Режим Не узнемиравај крије обавештења"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Додирните да бисте сазнали више и променили подешавање."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Режим Не узнемиравај је промењен"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Додирните да бисте проверили шта је блокирано."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Прегледајте подешавања обавештења"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Од Android-а 13 апликације које инсталирате морају да имају дозволу за слање обавештења. Додирните да бисте променили ову дозволу за постојеће апликације."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Подсети ме касније"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 0c5b6acec0fd..574b4e8ce925 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -202,7 +202,7 @@ <string name="work_profile_deleted_reason_maximum_password_failure" msgid="1080323158315663167">"För många försök med lösenord"</string> <string name="device_ownership_relinquished" msgid="4080886992183195724">"Administratören tillåter inte längre privat bruk av enheten"</string> <string name="private_space_deleted_by_admin" msgid="1484365588862066939">"Privat område har tagits bort"</string> - <string name="private_space_deleted_by_admin_details" msgid="7007781735201818689">"Din organisation tillåter inte privata områden på den här hanterade enheten."</string> + <string name="private_space_deleted_by_admin_details" msgid="7007781735201818689">"Din organisation tillåter inte privata utrymmen på den här hanterade enheten."</string> <string name="network_logging_notification_title" msgid="554983187553845004">"Enheten hanteras"</string> <string name="network_logging_notification_text" msgid="1327373071132562512">"Organisationen hanterar den här enheten och kan övervaka nätverkstrafiken. Tryck om du vill veta mer."</string> <string name="location_changed_notification_title" msgid="3620158742816699316">"Appar har åtkomst till din plats"</string> @@ -2009,8 +2009,8 @@ <string name="work_mode_emergency_call_button" msgid="6818855962881612322">"Nödsituation"</string> <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Ställ in ett skärmlås"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Ställ in skärmlås"</string> - <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Ställ in ett skärmlås för enheten om du vill använda ditt privata område."</string> - <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"Ange ett skärmlås för enheten om du vill radera privat område"</string> + <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Ställ in ett skärmlås för enheten om du vill använda ditt privata utrymme."</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"Ange ett skärmlås för enheten om du vill radera privat utrymme"</string> <string name="app_blocked_title" msgid="7353262160455028160">"Appen är inte tillgänglig"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> är inte tillgängligt just nu."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> är inte tillgänglig"</string> @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Vibrerar vid samtal och aviseringar"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Ljudet stängs av för samtal och aviseringar"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Systemändringar"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Stör ej"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Nytt: Aviseringar döljs av Stör ej"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tryck här om du vill läsa mer och ändra inställningarna."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Stör ej har ändrats"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tryck om du vill se vad som blockeras."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Granska aviseringsinställningarna"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"I Android 13 behöver appar som du installerar behörighet att skicka aviseringar. Tryck om du vill ändra denna behörighet för befintliga appar."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Påminn mig senare"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index c002866aa6ad..676e7abef414 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Itatetema arifa ikitumwa au simu ikipigwa"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Haitatoa mlio arifa ikitumwa au simu ikipigwa"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Mabadiliko kwenye mfumo"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Usinisumbue"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Mpya: Kipengele cha Usinisumbue kinaficha arifa"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Gusa ili upate maelezo zaidi na ubadilishe."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Kipengele cha Usinisumbue kimebadilishwa"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Gusa ili uangalie kipengee ambacho kimezuiwa."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Kagua mipangilio ya arifa"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Kuanzia Android toleo la 13, programu unazosakinisha zitahitaji ruhusa yako ili zitume arifa. Gusa ili ubadilishe ruhusa hii kwa programu zilizopo."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Nikumbushe baadaye"</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index dfc6a791e876..35cad789af8a 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"அழைப்புகள் மற்றும் அறிவிப்புகளுக்கு அதிரும்"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"அழைப்புகள் மற்றும் அறிவிப்புகளுக்கு ஒலியை முடக்கும்"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"சிஸ்டம் மாற்றங்கள்"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"தொந்தரவு செய்ய வேண்டாம்"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"புதியது: \'தொந்தரவு செய்ய வேண்டாம்\' பயன்முறையானது அறிவிப்புகளைக் காட்டாமல் மறைக்கிறது"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"மேலும் அறிந்து மாற்ற, தட்டவும்."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"தொந்தரவு செய்ய வேண்டாம் அமைப்புகள் மாற்றப்பட்டன"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"எவற்றையெல்லாம் தடுக்கிறது என்பதைப் பார்க்க, தட்டவும்."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"அறிவிப்பு அமைப்புகளை மதிப்பாய்வு செய்யுங்கள்"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 பதிப்பு முதல், நீங்கள் நிறுவுகின்ற ஆப்ஸ் உங்களுக்கு அறிவிப்புகளை அனுப்ப அனுமதி தேவை. ஏற்கெனவே உள்ள ஆப்ஸுக்கு இந்த அனுமதியை மாற்ற தட்டவும்."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"பின்னர் நினைவூட்டு"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 70732664c973..fd78f1d13304 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"కాల్స్ మరియు నోటిఫికేషన్లు వైబ్రేట్ అవుతాయి"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"కాల్స్ మరియు నోటిఫికేషన్లు మ్యూట్ చేయబడతాయి"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"సిస్టమ్ మార్పులు"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"అంతరాయం కలిగించవద్దు"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"కొత్తది: అంతరాయం కలిగించవద్దు నోటిఫికేషన్లను దాస్తోంది"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"మరింత తెలుసుకోవడానికి మరియు మార్చడానికి నొక్కండి."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"అంతరాయం కలిగించవద్దు మార్చబడింది"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"బ్లాక్ చేయబడిన దాన్ని చెక్ చేయడానికి నొక్కండి."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"నోటిఫికేషన్ సెట్టింగ్లను రివ్యూ చేయండి"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13తో మొదలుకుని, మీరు ఇన్స్టాల్ చేసే యాప్లకు నోటిఫికేషన్లను పంపడానికి మీ అనుమతి అవసరం. ఇప్పటికే ఉన్న యాప్ల కోసం ఈ అనుమతిని మార్చడానికి ట్యాప్ చేయండి."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"తర్వాత గుర్తు చేయి"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 5ee187fa8a41..cbac93d4d681 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"สายเรียกเข้าและการแจ้งเตือนจะสั่น"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"สายเรียกเข้าและการแจ้งเตือนจะไม่ส่งเสียง"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"การเปลี่ยนแปลงระบบ"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"ห้ามรบกวน"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"ใหม่: โหมดห้ามรบกวนซ่อนการแจ้งเตือนไว้"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"แตะเพื่อดูข้อมูลเพิ่มเติมและเปลี่ยนแปลง"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"เปลี่ยน \"ห้ามรบกวน\" แล้ว"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"แตะเพื่อดูรายการที่ถูกบล็อก"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"ตรวจสอบการตั้งค่าการแจ้งเตือน"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"ตั้งแต่ Android 13 เป็นต้นไป แอปที่คุณติดตั้งจะต้องได้รับสิทธิ์จากคุณเพื่อส่งการแจ้งเตือน แตะเพื่อเปลี่ยนแปลงสิทธิ์นี้สำหรับแอปที่มีอยู่"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"เตือนภายหลัง"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index e76dacdf0191..f9edcdca9a4a 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Magva-vibrate ang mga tawag at notification"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Mamu-mute ang mga tawag at notification"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Mga pagbabago sa system"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Huwag Istorbohin"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Bago: Itinatago ng Huwag Istorbohin ang mga notification"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"I-tap para matuto pa at baguhin."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Binago ang Huwag Istorbohin"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"I-tap para tingnan kung ano ang naka-block."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Suriin ang mga setting ng notification"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Simula sa Android 13, kakailanganin na ng mga app na ii-install mo ang iyong pahintulot para makapagpadala ng mga notification. I-tap para baguhin ang pahintulot na ito para sa mga kasalukuyang app."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Ipaalala mamaya"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index ad6fc0de5cd5..fea095101da9 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Aramalar ve bildirimler titreşim yapacak"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Aramalar ve bildirimlerin sesi kapalı olacak"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Sistem değişiklikleri"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Rahatsız Etmeyin"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Yeni: Rahatsız Etmeyin ayarı bildirimleri gizliyor"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Daha fazla bilgi edinmek ve değiştirmek için dokunun."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Rahatsız Etmeyin modu değişti"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Nelerin engellendiğini kontrol etmek için dokunun."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Bildirim ayarlarını inceleyin"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13\'te başlayarak yüklediğiniz uygulamaların bildirim gönderebilmesi için izniniz gereklidir. Mevcut uygulamalarda bu izni değiştirmek için dokunun."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Sonra hatırlat"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index a63f3fbf4e92..68f85b8b5342 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -2131,11 +2131,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Вібросигнал для викликів і сповіщень увімкнено"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Звуковий сигнал для викликів і сповіщень вимкнено"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Системні зміни"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Не турбувати"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Нове: у режимі \"Не турбувати\" сповіщення ховаються"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Торкніться, щоб дізнатися більше та змінити."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Налаштування режиму \"Не турбувати\" змінено"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Торкніться, щоб перевірити, що заблоковано."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Перегляньте налаштування сповіщень"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Починаючи з ОС Android 13, установленим додаткам потрібно надати дозвіл, щоб вони могли надсилати сповіщення. Натисніть, щоб змінити цей дозвіл для наявних додатків."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Нагадати пізніше"</string> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 52d9e3bbc5cc..4f0971765bcc 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"کالز اور اطلاعات پر وائبریٹ کرے گا"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"کالز اور اطلاعات کی آواز خاموش کر دی جائے گی"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"سسٹم کی تبدیلیاں"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"ڈسٹرب نہ کریں"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"نئی: \'ڈسٹرب نہ کریں\' اطلاعات کو چھپا رہی ہے"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"مزید جاننے اور تبدیل کرنے کیلئے تھپتھپائیں۔"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\'ڈسٹرب نہ کریں\' تبدیل ہو گيا ہے"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"مسدود کی گئی چیزوں کو چیک کرنے کے لیے تھپتھپائیں۔"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"اطلاع کی ترتیبات کا جائزہ لیں"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 کے ساتھ اب آپ جو بھی ایپس انسٹال کریں گے انہیں اطلاعات بھیجنے کے لیے آپ کی اجازت درکار ہوگی۔ موجودہ ایپس کے لیے اس اجازت کو تبدیل کرنے کی خاطر تھپتھپائیں۔"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"بعد میں یاد دلائیں"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index f62074e060d7..1bb3bcdc9759 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Chaqiruvlar va bildirishnomalar tebranadi"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Chaqiruvlar va bildirishnomalar ovozsiz qilinadi"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Tizimga oid o‘zgarishlar"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Bezovta qilinmasin"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Yangi: Bezovta qilinmasin rejimi bildirishnomalarni berkitmoqda"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Batafsil axborot olish va o‘zgartirish uchun bosing."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Bezovta qilinmasin rejimi sozlamalari o‘zgartirildi"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Nimalar bloklanganini tekshirish uchun bosing"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Bildirishnoma sozlamalarini tekshiring"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Android 13 versiyasidan boshlab, oʻrnatiladigan ilovalar bildirishnoma yuborish uchun sizdan ruxsat oladi. Mavjud ilovalarda ushbu ruxsatni oʻzgartirish uchun bosing."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Keyinroq eslatilsin"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 3b08a22ea956..3b1b21d7c3c6 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Cuộc gọi và thông báo sẽ rung"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Cuộc gọi và thông báo sẽ tắt tiếng"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Thay đổi hệ thống"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Không làm phiền"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Mới: Chế độ Không làm phiền sẽ ẩn thông báo"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Nhấn để tìm hiểu thêm và thay đổi."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Cài đặt Không làm phiền đã thay đổi"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Nhấn để xem những thông báo bị chặn."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Xem lại chế độ cài đặt thông báo"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Bắt đầu trên Android 13, các ứng dụng bạn cài đặt sẽ cần bạn cấp quyền để gửi thông báo. Hãy nhấn để thay đổi quyền này cho các ứng dụng hiện có."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Nhắc tôi sau"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 95753ebb093b..e7ebb6cff1c5 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"有来电和通知时会振动"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"有来电和通知时会静音"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"系统变更"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"勿扰"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"新功能:勿扰模式目前可隐藏通知"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"点按即可了解详情以及进行更改。"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"“勿扰”设置有变更"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"点按即可查看屏蔽内容。"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"查看通知设置"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"从 Android 13 开始,您安装的应用需要您授予相应权限才能发送通知。点按即可为现有应用更改此权限。"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"稍后提醒我"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index df04ec8e8387..8f7e17c749fa 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"有來電和通知時會震動"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"有來電和通知時會靜音"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"系統變更"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"請勿騷擾"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"新通知:「請勿騷擾」模式目前隱藏通知"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"輕按即可瞭解詳情和作出變更。"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"請勿騷擾已變更"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"輕按即可查看封鎖內容。"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"查看通知設定"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"由 Android 13 開始,你安裝的應用程式須獲得授權才能傳送通知。輕按即可變更現有應用程式的這項權限。"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"稍後提醒我"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index f0351ceb5591..76c581c8f73d 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"有來電和通知時會震動"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"有來電和通知時會靜音"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"系統變更"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"零打擾"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"新功能:「零打擾」模式現在可以隱藏通知"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"輕觸即可瞭解詳情及進行變更。"</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"「零打擾」設定已變更"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"輕觸即可查看遭封鎖的項目。"</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"查看通知設定"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"從 Android 13 開始,你安裝的應用程式必須獲得授權,才能傳送通知。輕觸即可為現有應用程式變更這項權限。"</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"稍後提醒我"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index f051a456a9bb..5aab13b2f087 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -2129,11 +2129,6 @@ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"Amakholi nezaziso zizodlidliza"</string> <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"Amakholi nezaziso zizothuliswa"</string> <string name="notification_channel_system_changes" msgid="2462010596920209678">"Ushintsho lwesistimu"</string> - <string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"Ungaphazamisi"</string> - <string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"Ukungaphazamisi kufihle izaziso"</string> - <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Thepha ukuze ufunde kabanzi futhi ushintshe."</string> - <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Ukungaphazamisi kushintshile"</string> - <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Thepha ukuze uhlole ukuthi yini evinjelwe."</string> <string name="review_notification_settings_title" msgid="5102557424459810820">"Buyekeza amasethingi wesaziso"</string> <string name="review_notification_settings_text" msgid="5916244866751849279">"Kusukela ku-Android 13, ama-app owafakayo adinga imvume yakho yokuthumela izaziso. Thepha ukuze ushintshe le mvume yama-app akhona kakade."</string> <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Ngikhumbuze ngesinye isikhathi"</string> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 440219de9561..02f9f3c5f0db 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -7720,6 +7720,44 @@ <attr name="animation" /> </declare-styleable> + <!-- ================================== --> + <!-- NotificationProgressDrawable class --> + <!-- ================================== --> + + <!-- Drawable used to render a segmented bar, with segments and points. --> + <!-- @hide internal use only --> + <declare-styleable name="NotificationProgressDrawable"> + <!-- Default color for the parts. --> + <attr name="segSegGap" format="dimension" /> + <attr name="segPointGap" format="dimension" /> + </declare-styleable> + + <!-- Used to config the segments of a NotificationProgressDrawable. --> + <!-- @hide internal use only --> + <declare-styleable name="NotificationProgressDrawableSegments"> + <!-- Width of the stroke. --> + <attr name="width" /> + <!-- Default color of the stroke. --> + <attr name="color" /> + <!-- Length of a dash in the stroke for the dashed segments. --> + <attr name="dashWidth" /> + <!-- Gap between dashes in the stroke for the dashed segments. --> + <attr name="dashGap" /> + </declare-styleable> + + <!-- Used to config the points of a NotificationProgressDrawable. --> + <!-- @hide internal use only --> + <declare-styleable name="NotificationProgressDrawablePoints"> + <!-- Radius (1/2 size) of the point rect. --> + <attr name="radius" /> + <!-- Inset of the point icon or rect. --> + <attr name="inset" /> + <!-- Corner radius of the point rect. --> + <attr name="cornerRadius" format="dimension" /> + <!-- Default color of the point rect. --> + <attr name="color" /> + </declare-styleable> + <!-- ========================== --> <!-- Animation class attributes --> <!-- ========================== --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 1a3a30d9c36d..8a2d767e9ad1 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1529,6 +1529,11 @@ factory reset. --> <bool name="config_enableCredentialFactoryResetProtection">true</bool> + <!-- If true, then work around broken Weaver HALs that don't work reliably before the device has + fully booted. Setting this to true weakens a security feature; it should be done only when + necessary, though it is still better than not using Weaver at all. --> + <bool name="config_disableWeaverOnUnsecuredUsers">false</bool> + <!-- Control the behavior when the user long presses the home button. 0 - Nothing 1 - Launch all apps intent @@ -6913,6 +6918,14 @@ entering the corresponding modes --> <string name="config_rearDisplayPhysicalAddress" translatable="false"></string> + <!-- The maximum number of virtual displays that can exist at the same time. + It must be >= 1. --> + <integer name="config_virtualDisplayLimit">100</integer> + + <!-- The maximum number of virtual displays per package that can exist at the same time. + It must be >= 1. --> + <integer name="config_virtualDisplayLimitPerPackage">50</integer> + <!-- List of certificate to be used for font fs-verity integrity verification --> <string-array translatable="false" name="config_fontManagerServiceCerts"> </string-array> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 6683dc044c9a..b92aa2f355ed 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -304,6 +304,9 @@ <!-- The top margin before the notification progress bar. --> <dimen name="notification_progress_margin_top">8dp</dimen> + <!-- The horizontal margin before and after the notification progress bar. --> + <dimen name="notification_progress_margin_horizontal">2dp</dimen> + <!-- height of the notification header --> <dimen name="notification_header_height">56dp</dimen> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index d63421057939..7aca535ad277 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -5818,16 +5818,6 @@ <!-- Title for the notification channel notifying user of settings system changes. [CHAR LIMIT=NONE] --> <string name="notification_channel_system_changes">System changes</string> - <!-- Title for the notification channel notifying user of do not disturb system changes (i.e. Do Not Disturb has changed). [CHAR LIMIT=NONE] --> - <string name="notification_channel_do_not_disturb">Do Not Disturb</string> - <!-- Title of notification indicating do not disturb visual interruption settings have changed when upgrading to P --> - <string name="zen_upgrade_notification_visd_title">New: Do Not Disturb is hiding notifications</string> - <!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings --> - <string name="zen_upgrade_notification_visd_content">Tap to learn more and change.</string> - <!-- Title of notification indicating do not disturb settings have changed when upgrading to P --> - <string name="zen_upgrade_notification_title">Do Not Disturb has changed</string> - <!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings --> - <string name="zen_upgrade_notification_content">Tap to check what\'s blocked.</string> <!-- Notification permission informational notification text --> <!-- Title for notification inviting users to review their notification settings [CHAR LIMIT=NONE] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 0ccef9123e10..c1893ab85d2b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -224,6 +224,8 @@ <java-symbol type="id" name="status_bar_latest_event_content" /> <java-symbol type="id" name="notification_main_column" /> <java-symbol type="id" name="notification_headerless_view_column" /> + <java-symbol type="id" name="notification_progress_start_icon" /> + <java-symbol type="id" name="notification_progress_end_icon" /> <java-symbol type="id" name="sms_short_code_confirm_message" /> <java-symbol type="id" name="sms_short_code_detail_layout" /> <java-symbol type="id" name="sms_short_code_detail_message" /> @@ -2390,6 +2392,7 @@ <java-symbol type="layout" name="notification_template_material_media" /> <java-symbol type="layout" name="notification_template_material_big_media" /> <java-symbol type="layout" name="notification_template_material_big_text" /> + <java-symbol type="layout" name="notification_template_material_progress" /> <java-symbol type="layout" name="notification_template_header" /> <java-symbol type="layout" name="notification_material_media_action" /> <java-symbol type="color" name="notification_progress_background_color" /> @@ -3205,6 +3208,7 @@ <java-symbol type="dimen" name="notification_heading_margin_end" /> <java-symbol type="dimen" name="notification_content_margin_top" /> <java-symbol type="dimen" name="notification_content_margin" /> + <java-symbol type="dimen" name="notification_progress_margin_horizontal" /> <java-symbol type="dimen" name="notification_header_background_height" /> <java-symbol type="dimen" name="notification_header_touchable_height" /> <java-symbol type="dimen" name="notification_header_expand_icon_size" /> @@ -3937,7 +3941,6 @@ <java-symbol type="string" name="notification_channel_usb" /> <java-symbol type="string" name="notification_channel_heavy_weight_app" /> <java-symbol type="string" name="notification_channel_system_changes" /> - <java-symbol type="string" name="notification_channel_do_not_disturb" /> <java-symbol type="string" name="notification_channel_accessibility_magnification" /> <java-symbol type="string" name="notification_channel_accessibility_security_policy" /> <java-symbol type="string" name="notification_channel_display" /> @@ -3989,6 +3992,7 @@ <java-symbol type="string" name="foreground_service_multiple_separator" /> <java-symbol type="bool" name="config_enableCredentialFactoryResetProtection" /> + <java-symbol type="bool" name="config_disableWeaverOnUnsecuredUsers" /> <!-- ETWS primary messages --> <java-symbol type="string" name="etws_primary_default_message_earthquake" /> @@ -4076,6 +4080,7 @@ <java-symbol type="dimen" name="text_size_body_2_material" /> <java-symbol type="dimen" name="notification_icon_circle_size" /> <java-symbol type="drawable" name="notification_icon_circle" /> + <java-symbol type="drawable" name="notification_progress_icon_background" /> <java-symbol type="dimen" name="messaging_avatar_size" /> <java-symbol type="dimen" name="messaging_group_sending_progress_size" /> <java-symbol type="dimen" name="messaging_image_rounding" /> @@ -4164,11 +4169,6 @@ <!-- For Wear devices --> <java-symbol type="array" name="config_wearActivityModeRadios" /> - <java-symbol type="string" name="zen_upgrade_notification_title" /> - <java-symbol type="string" name="zen_upgrade_notification_content" /> - <java-symbol type="string" name="zen_upgrade_notification_visd_title" /> - <java-symbol type="string" name="zen_upgrade_notification_visd_content" /> - <java-symbol type="string" name="review_notification_settings_title" /> <java-symbol type="string" name="review_notification_settings_text" /> <java-symbol type="string" name="review_notification_settings_remind_me_action" /> @@ -5240,6 +5240,9 @@ <java-symbol type="integer" name="config_deviceStateConcurrentRearDisplay" /> <java-symbol type="string" name="config_rearDisplayPhysicalAddress" /> + <java-symbol type="integer" name="config_virtualDisplayLimit" /> + <java-symbol type="integer" name="config_virtualDisplayLimitPerPackage" /> + <!-- For app language picker --> <java-symbol type="string" name="system_locale_title" /> <java-symbol type="layout" name="app_language_picker_system_default" /> diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java index e9b137cd5477..48e26203fab4 100644 --- a/core/tests/coretests/src/android/app/NotificationTest.java +++ b/core/tests/coretests/src/android/app/NotificationTest.java @@ -2301,13 +2301,13 @@ public class NotificationTest { @Test @EnableFlags(Flags.FLAG_API_RICH_ONGOING) - public void progressStyle_onProgressStepChange_visiblyDifferent() { + public void progressStyle_onProgressPointChange_visiblyDifferent() { final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") .setStyle(new Notification.ProgressStyle() - .addProgressStep(new Notification.ProgressStyle.Step(10))); + .addProgressPoint(new Notification.ProgressStyle.Point(10))); final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") .setStyle(new Notification.ProgressStyle() - .addProgressStep(new Notification.ProgressStyle.Step(12))); + .addProgressPoint(new Notification.ProgressStyle.Point(12))); assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) .isTrue(); @@ -2315,13 +2315,13 @@ public class NotificationTest { @Test @EnableFlags(Flags.FLAG_API_RICH_ONGOING) - public void indeterminateProgressStyle_onProgressStepChange_visiblyNotDifferent() { + public void indeterminateProgressStyle_onProgressPointChange_visiblyNotDifferent() { final Notification.Builder nProgress1 = new Notification.Builder(mContext, "test") .setStyle(new Notification.ProgressStyle().setProgressIndeterminate(true) - .addProgressStep(new Notification.ProgressStyle.Step(10))); + .addProgressPoint(new Notification.ProgressStyle.Point(10))); final Notification.Builder nProgress2 = new Notification.Builder(mContext, "test") .setStyle(new Notification.ProgressStyle().setProgressIndeterminate(true) - .addProgressStep(new Notification.ProgressStyle.Step(12))); + .addProgressPoint(new Notification.ProgressStyle.Point(12))); assertThat(Notification.areStyledNotificationsVisiblyDifferent(nProgress1, nProgress2)) .isFalse(); diff --git a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java index 3eefe044de90..b16c237252f6 100644 --- a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java +++ b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java @@ -119,7 +119,7 @@ public class ResourcesManagerTest { } @Override - protected DisplayMetrics getDisplayMetrics(int displayId, DisplayAdjustments daj) { + public DisplayMetrics getDisplayMetrics(int displayId, DisplayAdjustments daj) { return mDisplayMetricsMap.get(displayId); } }; @@ -470,6 +470,48 @@ public class ResourcesManagerTest { @Test @SmallTest + public void testResourceConfigurationAppliedWhenOverrideDoesNotExist() { + final int width = 240; + final int height = 360; + final float densityDpi = mDisplayMetricsMap.get(Display.DEFAULT_DISPLAY).densityDpi; + final int widthDp = (int) (width / densityDpi + 0.5f); + final int heightDp = (int) (height / densityDpi + 0.5f); + + final int overrideWidth = 480; + final int overrideHeight = 720; + final int overrideWidthDp = (int) (overrideWidth / densityDpi + 0.5f); + final int overrideHeightDp = (int) (height / densityDpi + 0.5f); + + // The method to be tested is overridden for other tests to provide a setup environment. + // Create a new one for this test only. + final ResourcesManager resourcesManager = new ResourcesManager(); + + Configuration newConfig = new Configuration(); + newConfig.windowConfiguration.setAppBounds(0, 0, width, height); + newConfig.screenWidthDp = widthDp; + newConfig.screenHeightDp = heightDp; + resourcesManager.applyConfigurationToResources(newConfig, null); + + assertEquals(width, resourcesManager.getDisplayMetrics(Display.DEFAULT_DISPLAY, + DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS).widthPixels); + assertEquals(height, resourcesManager.getDisplayMetrics(Display.DEFAULT_DISPLAY, + DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS).heightPixels); + + Configuration overrideConfig = new Configuration(); + overrideConfig.windowConfiguration.setAppBounds(0, 0, overrideWidth, overrideHeight); + overrideConfig.screenWidthDp = overrideWidthDp; + overrideConfig.screenHeightDp = overrideHeightDp; + + final DisplayAdjustments daj = new DisplayAdjustments(overrideConfig); + + assertEquals(overrideWidth, resourcesManager.getDisplayMetrics( + Display.DEFAULT_DISPLAY, daj).widthPixels); + assertEquals(overrideHeight, resourcesManager.getDisplayMetrics( + Display.DEFAULT_DISPLAY, daj).heightPixels); + } + + @Test + @SmallTest @RequiresFlagsEnabled(Flags.FLAG_REGISTER_RESOURCE_PATHS) @DisabledOnRavenwood(blockedBy = PackageManager.class) public void testNewResourcesWithOutdatedImplAfterResourcePathsRegistration() diff --git a/core/tests/coretests/src/android/window/BackTouchTrackerTest.kt b/core/tests/coretests/src/android/window/BackTouchTrackerTest.kt index b7bccd46cede..381b566018c7 100644 --- a/core/tests/coretests/src/android/window/BackTouchTrackerTest.kt +++ b/core/tests/coretests/src/android/window/BackTouchTrackerTest.kt @@ -46,45 +46,43 @@ class BackTouchTrackerTest { val linearTracker = linearTouchTracker() linearTracker.setGestureStartLocation(INITIAL_X_LEFT_EDGE, 0f, BackEvent.EDGE_LEFT) var touchX = 10f - val velocityX = 0f - val velocityY = 0f // Pre-commit - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / MAX_DISTANCE) // Post-commit touchX += 100f linearTracker.setTriggerBack(true) - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / MAX_DISTANCE) // Cancel touchX -= 10f linearTracker.setTriggerBack(false) - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress(0f) // Cancel more touchX -= 10f - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress(0f) // Restarted, but pre-commit val restartX = touchX touchX += 10f - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((touchX - restartX) / MAX_DISTANCE) // continue restart within pre-commit touchX += 10f - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((touchX - restartX) / MAX_DISTANCE) // Restarted, post-commit touchX += 10f linearTracker.setTriggerBack(true) - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / MAX_DISTANCE) } @@ -93,46 +91,44 @@ class BackTouchTrackerTest { val linearTracker = linearTouchTracker() linearTracker.setGestureStartLocation(INITIAL_X_RIGHT_EDGE, 0f, BackEvent.EDGE_RIGHT) var touchX = INITIAL_X_RIGHT_EDGE - 10 // Fake right edge - val velocityX = 0f - val velocityY = 0f val target = MAX_DISTANCE // Pre-commit - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((INITIAL_X_RIGHT_EDGE - touchX) / target) // Post-commit touchX -= 100f linearTracker.setTriggerBack(true) - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((INITIAL_X_RIGHT_EDGE - touchX) / target) // Cancel touchX += 10f linearTracker.setTriggerBack(false) - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress(0f) // Cancel more touchX += 10f - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress(0f) // Restarted, but pre-commit val restartX = touchX touchX -= 10f - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((restartX - touchX) / target) // continue restart within pre-commit touchX -= 10f - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((restartX - touchX) / target) // Restarted, post-commit touchX -= 10f linearTracker.setTriggerBack(true) - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((INITIAL_X_RIGHT_EDGE - touchX) / target) } @@ -141,28 +137,26 @@ class BackTouchTrackerTest { val nonLinearTracker = nonLinearTouchTracker() nonLinearTracker.setGestureStartLocation(INITIAL_X_LEFT_EDGE, 0f, BackEvent.EDGE_LEFT) var touchX = 10f - val velocityX = 0f - val velocityY = 0f val linearTarget = LINEAR_DISTANCE + (MAX_DISTANCE - LINEAR_DISTANCE) * NON_LINEAR_FACTOR // Pre-commit: linear progress - nonLinearTracker.update(touchX, 0f, velocityX, velocityY) + nonLinearTracker.update(touchX, 0f) nonLinearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / linearTarget) // Post-commit: still linear progress touchX += 100f nonLinearTracker.setTriggerBack(true) - nonLinearTracker.update(touchX, 0f, velocityX, velocityY) + nonLinearTracker.update(touchX, 0f) nonLinearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / linearTarget) // still linear progress touchX = INITIAL_X_LEFT_EDGE + LINEAR_DISTANCE - nonLinearTracker.update(touchX, 0f, velocityX, velocityY) + nonLinearTracker.update(touchX, 0f) nonLinearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / linearTarget) // non linear progress touchX += 10 - nonLinearTracker.update(touchX, 0f, velocityX, velocityY) + nonLinearTracker.update(touchX, 0f) val nonLinearTouch = (touchX - INITIAL_X_LEFT_EDGE) - LINEAR_DISTANCE val nonLinearProgress = nonLinearTouch / NON_LINEAR_DISTANCE val nonLinearTarget = MathUtils.lerp(linearTarget, MAX_DISTANCE, nonLinearProgress) @@ -178,7 +172,7 @@ class BackTouchTrackerTest { val velocityY = 0f // assert that progress is increased when increasing touchX - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((touchX - INITIAL_X_LEFT_EDGE) / MAX_DISTANCE) // assert that progress is reset to 0 when start location is updated @@ -187,13 +181,13 @@ class BackTouchTrackerTest { // assert that progress remains 0 when touchX is decreased touchX -= 50 - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress(0f) // assert that progress uses new minimal touchX for progress calculation val newInitialTouchX = touchX touchX += 100 - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((touchX - newInitialTouchX) / MAX_DISTANCE) // assert the same for triggerBack==true @@ -207,11 +201,8 @@ class BackTouchTrackerTest { linearTracker.setGestureStartLocation(INITIAL_X_RIGHT_EDGE, 0f, BackEvent.EDGE_RIGHT) var touchX = INITIAL_X_RIGHT_EDGE - 100f - val velocityX = 0f - val velocityY = 0f - // assert that progress is increased when decreasing touchX - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((INITIAL_X_RIGHT_EDGE - touchX) / MAX_DISTANCE) // assert that progress is reset to 0 when start location is updated @@ -220,13 +211,13 @@ class BackTouchTrackerTest { // assert that progress remains 0 when touchX is increased touchX += 50 - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress(0f) // assert that progress uses new maximal touchX for progress calculation val newInitialTouchX = touchX touchX -= 100 - linearTracker.update(touchX, 0f, velocityX, velocityY) + linearTracker.update(touchX, 0f) linearTracker.assertProgress((newInitialTouchX - touchX) / MAX_DISTANCE) // assert the same for triggerBack==true diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java index 0bda0fff6819..b001cc2929e3 100644 --- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java +++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java @@ -18,6 +18,9 @@ package android.window; import static android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT; import static android.window.OnBackInvokedDispatcher.PRIORITY_OVERLAY; +import static android.window.OnBackInvokedDispatcher.PRIORITY_SYSTEM_NAVIGATION_OBSERVER; + +import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -39,6 +42,10 @@ import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; +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.view.IWindow; import android.view.IWindowSession; import android.view.ImeBackAnimationController; @@ -80,6 +87,8 @@ public class WindowOnBackInvokedDispatcherTest { @Rule public final MockitoRule mockito = MockitoJUnit.rule(); + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Mock private IWindowSession mWindowSession; @@ -145,7 +154,8 @@ public class WindowOnBackInvokedDispatcherTest { assertEquals("No setOnBackInvokedCallbackInfo", mCallbackInfoCalls, actual); } - private void assertCallbacksSize(int expectedDefault, int expectedOverlay) { + private void assertCallbacksSize(int expectedDefault, int expectedOverlay, + int expectedObserver) { ArrayList<OnBackInvokedCallback> callbacksDefault = mDispatcher .mOnBackInvokedCallbacks.get(PRIORITY_DEFAULT); int actualSizeDefault = callbacksDefault != null ? callbacksDefault.size() : 0; @@ -155,6 +165,10 @@ public class WindowOnBackInvokedDispatcherTest { .mOnBackInvokedCallbacks.get(PRIORITY_OVERLAY); int actualSizeOverlay = callbacksOverlay != null ? callbacksOverlay.size() : 0; assertEquals("mOnBackInvokedCallbacks OVERLAY size", expectedOverlay, actualSizeOverlay); + + int actualSizeObserver = mDispatcher.mSystemNavigationObserverCallback == null ? 0 : 1; + assertEquals("mOnBackInvokedCallbacks SYSTEM_NAVIGATION_OBSERVER size", expectedObserver, + actualSizeObserver); } private void assertTopCallback(OnBackInvokedCallback expectedCallback) { @@ -164,13 +178,13 @@ public class WindowOnBackInvokedDispatcherTest { @Test public void registerCallback_samePriority_sameCallback() throws RemoteException { mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1); - assertCallbacksSize(/* default */ 1, /* overlay */ 0); + assertCallbacksSize(/* default */ 1, /* overlay */ 0, /* observer */ 0); assertSetCallbackInfo(); assertTopCallback(mCallback1); // The callback is removed and added again mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1); - assertCallbacksSize(/* default */ 1, /* overlay */ 0); + assertCallbacksSize(/* default */ 1, /* overlay */ 0, /* observer */ 0); assertSetCallbackInfo(); assertTopCallback(mCallback1); @@ -182,13 +196,13 @@ public class WindowOnBackInvokedDispatcherTest { @Test public void registerCallback_samePriority_differentCallback() throws RemoteException { mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1); - assertCallbacksSize(/* default */ 1, /* overlay */ 0); + assertCallbacksSize(/* default */ 1, /* overlay */ 0, /* observer */ 0); assertSetCallbackInfo(); assertTopCallback(mCallback1); // The new callback becomes the TopCallback mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback2); - assertCallbacksSize(/* default */ 2, /* overlay */ 0); + assertCallbacksSize(/* default */ 2, /* overlay */ 0, /* observer */ 0); assertSetCallbackInfo(); assertTopCallback(mCallback2); @@ -201,13 +215,13 @@ public class WindowOnBackInvokedDispatcherTest { @Test public void registerCallback_differentPriority_sameCallback() throws RemoteException { mDispatcher.registerOnBackInvokedCallback(PRIORITY_OVERLAY, mCallback1); - assertCallbacksSize(/* default */ 0, /* overlay */ 1); + assertCallbacksSize(/* default */ 0, /* overlay */ 1, /* observer */ 0); assertSetCallbackInfo(); assertTopCallback(mCallback1); // The callback is moved to the new priority list mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1); - assertCallbacksSize(/* default */ 1, /* overlay */ 0); + assertCallbacksSize(/* default */ 1, /* overlay */ 0, /* observer */ 0); assertSetCallbackInfo(); assertTopCallback(mCallback1); @@ -220,13 +234,13 @@ public class WindowOnBackInvokedDispatcherTest { public void registerCallback_differentPriority_differentCallback() throws RemoteException { mDispatcher.registerOnBackInvokedCallback(PRIORITY_OVERLAY, mCallback1); assertSetCallbackInfo(); - assertCallbacksSize(/* default */ 0, /* overlay */ 1); + assertCallbacksSize(/* default */ 0, /* overlay */ 1, /* observer */ 0); assertTopCallback(mCallback1); // The callback with higher priority is still the TopCallback mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback2); assertNoSetCallbackInfo(); - assertCallbacksSize(/* default */ 1, /* overlay */ 1); + assertCallbacksSize(/* default */ 1, /* overlay */ 1, /* observer */ 0); assertTopCallback(mCallback1); waitForIdle(); @@ -238,22 +252,22 @@ public class WindowOnBackInvokedDispatcherTest { @Test public void registerCallback_sameInstanceAddedTwice() throws RemoteException { mDispatcher.registerOnBackInvokedCallback(PRIORITY_OVERLAY, mCallback1); - assertCallbacksSize(/* default */ 0, /* overlay */ 1); + assertCallbacksSize(/* default */ 0, /* overlay */ 1, /* observer */ 0); assertSetCallbackInfo(); assertTopCallback(mCallback1); mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback2); - assertCallbacksSize(/* default */ 1, /* overlay */ 1); + assertCallbacksSize(/* default */ 1, /* overlay */ 1, /* observer */ 0); assertNoSetCallbackInfo(); assertTopCallback(mCallback1); mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1); - assertCallbacksSize(/* default */ 2, /* overlay */ 0); + assertCallbacksSize(/* default */ 2, /* overlay */ 0, /* observer */ 0); assertSetCallbackInfo(); assertTopCallback(mCallback1); mDispatcher.registerOnBackInvokedCallback(PRIORITY_OVERLAY, mCallback2); - assertCallbacksSize(/* default */ 1, /* overlay */ 1); + assertCallbacksSize(/* default */ 1, /* overlay */ 1, /* observer */ 0); assertSetCallbackInfo(); assertTopCallback(mCallback2); @@ -570,13 +584,107 @@ public class WindowOnBackInvokedDispatcherTest { assertFalse(mDispatcher.mProgressAnimator.isBackAnimationInProgress()); } + @Test(expected = IllegalArgumentException.class) + @RequiresFlagsDisabled(FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER) + public void testObserverCallback_registrationFailsWithoutFlaggedApiEnabled() { + mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback2); + } + + @Test + @RequiresFlagsEnabled(FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER) + public void testObserverCallback_invokedWithSystemCallback() throws RemoteException { + mDispatcher.registerSystemOnBackInvokedCallback(mCallback1); + mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback2); + + assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 1); + OnBackInvokedCallbackInfo callbackInfo = assertSetCallbackInfo(); + assertTopCallback(mCallback1); + + callbackInfo.getCallback().onBackStarted(mBackEvent); + waitForIdle(); + verify(mCallback1).onBackStarted(any()); + verify(mCallback2, never()).onBackStarted(any()); + + callbackInfo.getCallback().onBackProgressed(mBackEvent); + waitForIdle(); + verify(mCallback1, atLeast(1)).onBackProgressed(any()); + verify(mCallback2, never()).onBackProgressed(any()); + + callbackInfo.getCallback().onBackCancelled(); + waitForIdle(); + verify(mCallback1, timeout(1000)).onBackCancelled(); + verify(mCallback2, never()).onBackCancelled(); + + // start new gesture to test onBackInvoked case + callbackInfo.getCallback().onBackStarted(mBackEvent); + callbackInfo.getCallback().onBackInvoked(); + waitForIdle(); + verify(mCallback1, timeout(1000)).onBackInvoked(); + verify(mCallback2).onBackInvoked(); + } + + @Test + @RequiresFlagsEnabled(FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER) + public void testObserverCallback_notInvokedWithNonSystemCallback() throws RemoteException { + mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1); + mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback2); + + assertCallbacksSize(/* default */ 1, /* overlay */ 0, /* observer */ 1); + OnBackInvokedCallbackInfo callbackInfo = assertSetCallbackInfo(); + assertTopCallback(mCallback1); + + callbackInfo.getCallback().onBackStarted(mBackEvent); + waitForIdle(); + verify(mCallback1).onBackStarted(any()); + verify(mCallback2, never()).onBackStarted(any()); + + callbackInfo.getCallback().onBackProgressed(mBackEvent); + waitForIdle(); + verify(mCallback1, atLeast(1)).onBackProgressed(any()); + verify(mCallback2, never()).onBackProgressed(any()); + + callbackInfo.getCallback().onBackCancelled(); + waitForIdle(); + verify(mCallback1, timeout(1000)).onBackCancelled(); + verify(mCallback2, never()).onBackCancelled(); + + // start new gesture to test onBackInvoked case + callbackInfo.getCallback().onBackStarted(mBackEvent); + callbackInfo.getCallback().onBackInvoked(); + waitForIdle(); + verify(mCallback1, timeout(1000)).onBackInvoked(); + verify(mCallback2, never()).onBackInvoked(); + } + + @Test + @RequiresFlagsEnabled(FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER) + public void testObserverCallback_reregistrations() { + mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback1); + assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 1); + assertEquals(mCallback1, mDispatcher.mSystemNavigationObserverCallback); + + // test reregistration of observer-callback as observer-callback + mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback2); + assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 1); + assertEquals(mCallback2, mDispatcher.mSystemNavigationObserverCallback); + + // test reregistration of observer-callback as regular callback + mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback2); + assertCallbacksSize(/* default */ 1, /* overlay */ 0, /* observer */ 0); + + // test reregistration of regular callback as observer-callback + mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback2); + assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 1); + + mDispatcher.unregisterOnBackInvokedCallback(mCallback2); + assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 0); + } + private BackMotionEvent backMotionEventFrom(float progress) { return new BackMotionEvent( /* touchX = */ 0, /* touchY = */ 0, /* progress = */ progress, - /* velocityX = */ 0, - /* velocityY = */ 0, /* triggerBack = */ false, /* swipeEdge = */ BackEvent.EDGE_LEFT, /* departingAnimationTarget = */ null); @@ -585,13 +693,13 @@ public class WindowOnBackInvokedDispatcherTest { private void verifyImeCallackRegistrations() throws RemoteException { // verify default callback is replaced with ImeBackAnimationController mDispatcher.registerOnBackInvokedCallbackUnchecked(mDefaultImeCallback, PRIORITY_DEFAULT); - assertCallbacksSize(/* default */ 1, /* overlay */ 0); + assertCallbacksSize(/* default */ 1, /* overlay */ 0, /* observer */ 0); assertSetCallbackInfo(); assertTopCallback(mImeBackAnimationController); // verify regular ime callback is successfully registered mDispatcher.registerOnBackInvokedCallbackUnchecked(mImeCallback, PRIORITY_DEFAULT); - assertCallbacksSize(/* default */ 2, /* overlay */ 0); + assertCallbacksSize(/* default */ 2, /* overlay */ 0, /* observer */ 0); assertSetCallbackInfo(); assertTopCallback(mImeCallback); } diff --git a/core/tests/coretests/src/com/android/internal/notification/SystemNotificationChannelsTest.java b/core/tests/coretests/src/com/android/internal/notification/SystemNotificationChannelsTest.java new file mode 100644 index 000000000000..0bf406c970f2 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/notification/SystemNotificationChannelsTest.java @@ -0,0 +1,107 @@ +/* + * 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.notification; + +import static com.android.internal.notification.SystemNotificationChannels.ABUSIVE_BACKGROUND_APPS; +import static com.android.internal.notification.SystemNotificationChannels.ACCESSIBILITY_MAGNIFICATION; +import static com.android.internal.notification.SystemNotificationChannels.ACCESSIBILITY_SECURITY_POLICY; +import static com.android.internal.notification.SystemNotificationChannels.ACCOUNT; +import static com.android.internal.notification.SystemNotificationChannels.ALERTS; +import static com.android.internal.notification.SystemNotificationChannels.CAR_MODE; +import static com.android.internal.notification.SystemNotificationChannels.DEVELOPER; +import static com.android.internal.notification.SystemNotificationChannels.DEVELOPER_IMPORTANT; +import static com.android.internal.notification.SystemNotificationChannels.DEVICE_ADMIN; +import static com.android.internal.notification.SystemNotificationChannels.FOREGROUND_SERVICE; +import static com.android.internal.notification.SystemNotificationChannels.HEAVY_WEIGHT_APP; +import static com.android.internal.notification.SystemNotificationChannels.NETWORK_ALERTS; +import static com.android.internal.notification.SystemNotificationChannels.NETWORK_AVAILABLE; +import static com.android.internal.notification.SystemNotificationChannels.NETWORK_STATUS; +import static com.android.internal.notification.SystemNotificationChannels.OBSOLETE_DO_NOT_DISTURB; +import static com.android.internal.notification.SystemNotificationChannels.PHYSICAL_KEYBOARD; +import static com.android.internal.notification.SystemNotificationChannels.RETAIL_MODE; +import static com.android.internal.notification.SystemNotificationChannels.SECURITY; +import static com.android.internal.notification.SystemNotificationChannels.SYSTEM_CHANGES; +import static com.android.internal.notification.SystemNotificationChannels.UPDATES; +import static com.android.internal.notification.SystemNotificationChannels.USB; +import static com.android.internal.notification.SystemNotificationChannels.VPN; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.verify; + +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.testing.TestableContext; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.List; + +@RunWith(AndroidJUnit4.class) +public class SystemNotificationChannelsTest { + + @Rule public TestableContext mContext = new TestableContext( + ApplicationProvider.getApplicationContext()); + + @Mock private NotificationManager mNm; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext.addMockSystemService(NotificationManager.class, mNm); + } + + @Test + @SuppressWarnings("unchecked") + public void createAll_createsExpectedChannels() { + ArgumentCaptor<List<NotificationChannel>> createdChannelsCaptor = + ArgumentCaptor.forClass(List.class); + + SystemNotificationChannels.createAll(mContext); + + verify(mNm).createNotificationChannels(createdChannelsCaptor.capture()); + List<NotificationChannel> createdChannels = createdChannelsCaptor.getValue(); + assertThat(createdChannels.stream().map(NotificationChannel::getId).toList()) + .containsExactly(PHYSICAL_KEYBOARD, SECURITY, CAR_MODE, ACCOUNT, DEVELOPER, + DEVELOPER_IMPORTANT, UPDATES, NETWORK_STATUS, NETWORK_ALERTS, + NETWORK_AVAILABLE, VPN, DEVICE_ADMIN, ALERTS, RETAIL_MODE, USB, + FOREGROUND_SERVICE, HEAVY_WEIGHT_APP, SYSTEM_CHANGES, + ACCESSIBILITY_MAGNIFICATION, ACCESSIBILITY_SECURITY_POLICY, + ABUSIVE_BACKGROUND_APPS); + } + + @Test + public void createAll_deletesObsoleteChannels() { + ArgumentCaptor<String> deletedChannelCaptor = ArgumentCaptor.forClass(String.class); + + SystemNotificationChannels.createAll(mContext); + + verify(mNm, atLeastOnce()).deleteNotificationChannel(deletedChannelCaptor.capture()); + List<String> deletedChannels = deletedChannelCaptor.getAllValues(); + assertThat(deletedChannels).containsExactly(OBSOLETE_DO_NOT_DISTURB); + } +} diff --git a/core/tests/vibrator/src/android/os/VibratorInfoTest.java b/core/tests/vibrator/src/android/os/VibratorInfoTest.java index c81081075859..47d01c4452f6 100644 --- a/core/tests/vibrator/src/android/os/VibratorInfoTest.java +++ b/core/tests/vibrator/src/android/os/VibratorInfoTest.java @@ -40,10 +40,10 @@ public class VibratorInfoTest { private static final float[] TEST_AMPLITUDE_MAP = new float[]{ /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f}; - private static final VibratorInfo.FrequencyProfile EMPTY_FREQUENCY_PROFILE = - new VibratorInfo.FrequencyProfile(Float.NaN, Float.NaN, Float.NaN, null); - private static final VibratorInfo.FrequencyProfile TEST_FREQUENCY_PROFILE = - new VibratorInfo.FrequencyProfile(TEST_RESONANT_FREQUENCY, TEST_MIN_FREQUENCY, + private static final VibratorInfo.FrequencyProfileLegacy EMPTY_FREQUENCY_PROFILE = + new VibratorInfo.FrequencyProfileLegacy(Float.NaN, Float.NaN, Float.NaN, null); + private static final VibratorInfo.FrequencyProfileLegacy TEST_FREQUENCY_PROFILE_LEGACY = + new VibratorInfo.FrequencyProfileLegacy(TEST_RESONANT_FREQUENCY, TEST_MIN_FREQUENCY, TEST_FREQUENCY_RESOLUTION, TEST_AMPLITUDE_MAP); @Test @@ -179,53 +179,57 @@ public class VibratorInfoTest { } @Test - public void testGetFrequencyProfile_unsetProfileIsEmpty() { - assertTrue( - new VibratorInfo.Builder(TEST_VIBRATOR_ID).build().getFrequencyProfile().isEmpty()); + public void testGetFrequencyProfileLegacy_unsetProfileIsEmpty() { + assertTrue(new VibratorInfo.Builder( + TEST_VIBRATOR_ID).build().getFrequencyProfileLegacy().isEmpty()); } @Test public void testFrequencyProfile_invalidValuesCreatesEmptyProfile() { // Invalid, contains NaN values or empty array. - assertTrue(new VibratorInfo.FrequencyProfile( + assertTrue(new VibratorInfo.FrequencyProfileLegacy( Float.NaN, 50, 25, TEST_AMPLITUDE_MAP).isEmpty()); - assertTrue(new VibratorInfo.FrequencyProfile( + assertTrue(new VibratorInfo.FrequencyProfileLegacy( 150, Float.NaN, 25, TEST_AMPLITUDE_MAP).isEmpty()); - assertTrue(new VibratorInfo.FrequencyProfile( + assertTrue(new VibratorInfo.FrequencyProfileLegacy( 150, 50, Float.NaN, TEST_AMPLITUDE_MAP).isEmpty()); - assertTrue(new VibratorInfo.FrequencyProfile(150, 50, 25, null).isEmpty()); + assertTrue(new VibratorInfo.FrequencyProfileLegacy(150, 50, 25, null).isEmpty()); // Invalid, contains zero or negative frequency values. - assertTrue(new VibratorInfo.FrequencyProfile(-1, 50, 25, TEST_AMPLITUDE_MAP).isEmpty()); - assertTrue(new VibratorInfo.FrequencyProfile(150, 0, 25, TEST_AMPLITUDE_MAP).isEmpty()); - assertTrue(new VibratorInfo.FrequencyProfile(150, 50, -2, TEST_AMPLITUDE_MAP).isEmpty()); + assertTrue( + new VibratorInfo.FrequencyProfileLegacy(-1, 50, 25, TEST_AMPLITUDE_MAP).isEmpty()); + assertTrue( + new VibratorInfo.FrequencyProfileLegacy(150, 0, 25, TEST_AMPLITUDE_MAP).isEmpty()); + assertTrue( + new VibratorInfo.FrequencyProfileLegacy(150, 50, -2, TEST_AMPLITUDE_MAP).isEmpty()); // Invalid max amplitude entries. - assertTrue(new VibratorInfo.FrequencyProfile( + assertTrue(new VibratorInfo.FrequencyProfileLegacy( 150, 50, 50, new float[] { -1, 0, 1, 1, 0 }).isEmpty()); - assertTrue(new VibratorInfo.FrequencyProfile( + assertTrue(new VibratorInfo.FrequencyProfileLegacy( 150, 50, 50, new float[] { 0, 1, 2, 1, 0 }).isEmpty()); // Invalid, minFrequency > resonantFrequency - assertTrue(new VibratorInfo.FrequencyProfile( + assertTrue(new VibratorInfo.FrequencyProfileLegacy( /* resonantFrequencyHz= */ 150, /* minFrequencyHz= */ 250, 25, TEST_AMPLITUDE_MAP) .isEmpty()); // Invalid, maxFrequency < resonantFrequency by changing resolution. - assertTrue(new VibratorInfo.FrequencyProfile( + assertTrue(new VibratorInfo.FrequencyProfileLegacy( 150, 50, /* frequencyResolutionHz= */ 10, TEST_AMPLITUDE_MAP).isEmpty()); } @Test public void testGetFrequencyRangeHz_emptyProfileReturnsNull() { - assertNull(new VibratorInfo.FrequencyProfile( + assertNull(new VibratorInfo.FrequencyProfileLegacy( Float.NaN, 50, 25, TEST_AMPLITUDE_MAP).getFrequencyRangeHz()); - assertNull(new VibratorInfo.FrequencyProfile( + assertNull(new VibratorInfo.FrequencyProfileLegacy( 150, Float.NaN, 25, TEST_AMPLITUDE_MAP).getFrequencyRangeHz()); - assertNull(new VibratorInfo.FrequencyProfile( + assertNull(new VibratorInfo.FrequencyProfileLegacy( 150, 50, Float.NaN, TEST_AMPLITUDE_MAP).getFrequencyRangeHz()); - assertNull(new VibratorInfo.FrequencyProfile(150, 50, 25, null).getFrequencyRangeHz()); + assertNull( + new VibratorInfo.FrequencyProfileLegacy(150, 50, 25, null).getFrequencyRangeHz()); } @Test public void testGetFrequencyRangeHz_validProfileReturnsMappedValues() { - VibratorInfo.FrequencyProfile profile = new VibratorInfo.FrequencyProfile( + VibratorInfo.FrequencyProfileLegacy profile = new VibratorInfo.FrequencyProfileLegacy( /* resonantFrequencyHz= */ 150, /* minFrequencyHz= */ 50, /* frequencyResolutionHz= */ 25, @@ -239,12 +243,12 @@ public class VibratorInfoTest { @Test public void testGetMaxAmplitude_emptyProfileReturnsAlwaysZero() { - VibratorInfo.FrequencyProfile profile = EMPTY_FREQUENCY_PROFILE; + VibratorInfo.FrequencyProfileLegacy profile = EMPTY_FREQUENCY_PROFILE; assertEquals(0f, profile.getMaxAmplitude(Float.NaN), TEST_TOLERANCE); assertEquals(0f, profile.getMaxAmplitude(100f), TEST_TOLERANCE); assertEquals(0f, profile.getMaxAmplitude(200f), TEST_TOLERANCE); - profile = new VibratorInfo.FrequencyProfile( + profile = new VibratorInfo.FrequencyProfileLegacy( /* resonantFrequencyHz= */ 150, /* minFrequencyHz= */ Float.NaN, /* frequencyResolutionHz= */ Float.NaN, @@ -257,7 +261,7 @@ public class VibratorInfoTest { @Test public void testGetMaxAmplitude_validProfileReturnsMappedValues() { - VibratorInfo.FrequencyProfile profile = new VibratorInfo.FrequencyProfile( + VibratorInfo.FrequencyProfileLegacy profile = new VibratorInfo.FrequencyProfileLegacy( /* resonantFrequencyHz= */ 150, /* minFrequencyHz= */ 50, /* frequencyResolutionHz= */ 25, @@ -301,7 +305,7 @@ public class VibratorInfoTest { .setPwlePrimitiveDurationMax(50) .setPwleSizeMax(20) .setQFactor(2f) - .setFrequencyProfile(TEST_FREQUENCY_PROFILE) + .setFrequencyProfileLegacy(TEST_FREQUENCY_PROFILE_LEGACY) .setMaxEnvelopeEffectSize(16) .setMinEnvelopeEffectControlPointDurationMillis(20) .setMaxEnvelopeEffectControlPointDurationMillis(1_000); @@ -344,7 +348,7 @@ public class VibratorInfoTest { assertFalse(complete.equalContent(completeWithDifferentPrimitiveDuration)); VibratorInfo completeWithDifferentFrequencyProfile = completeBuilder - .setFrequencyProfile(new VibratorInfo.FrequencyProfile( + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy( TEST_RESONANT_FREQUENCY + 20, TEST_MIN_FREQUENCY + 10, TEST_FREQUENCY_RESOLUTION + 5, @@ -354,7 +358,7 @@ public class VibratorInfoTest { assertFalse(complete.equalContent(completeWithDifferentFrequencyProfile)); VibratorInfo completeWithEmptyFrequencyProfile = completeBuilder - .setFrequencyProfile(EMPTY_FREQUENCY_PROFILE) + .setFrequencyProfileLegacy(EMPTY_FREQUENCY_PROFILE) .build(); assertNotEquals(complete, completeWithEmptyFrequencyProfile); assertFalse(complete.equalContent(completeWithEmptyFrequencyProfile)); @@ -391,7 +395,7 @@ public class VibratorInfoTest { .setSupportedEffects(VibrationEffect.EFFECT_CLICK) .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 20) .setQFactor(Float.NaN) - .setFrequencyProfile(TEST_FREQUENCY_PROFILE) + .setFrequencyProfileLegacy(TEST_FREQUENCY_PROFILE_LEGACY) .build(); Parcel parcel = Parcel.obtain(); diff --git a/core/tests/vibrator/src/android/os/vibrator/MultiVibratorInfoTest.java b/core/tests/vibrator/src/android/os/vibrator/MultiVibratorInfoTest.java index fc31ac44b362..f192b896e1db 100644 --- a/core/tests/vibrator/src/android/os/vibrator/MultiVibratorInfoTest.java +++ b/core/tests/vibrator/src/android/os/vibrator/MultiVibratorInfoTest.java @@ -161,12 +161,12 @@ public class MultiVibratorInfoTest { VibratorInfo firstInfo = new VibratorInfo.Builder(/* id= */ 1) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setQFactor(1f) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 1, null)) + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(1, 1, 1, null)) .build(); VibratorInfo secondInfo = new VibratorInfo.Builder(/* id= */ 2) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setQFactor(2f) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(2, 2, 2, null)) + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(2, 2, 2, null)) .build(); VibratorInfo info = new MultiVibratorInfo(/* id= */ 1, @@ -191,13 +191,13 @@ public class MultiVibratorInfoTest { VibratorInfo firstInfo = new VibratorInfo.Builder(/* id= */ 1) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setQFactor(10f) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile( + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy( /* resonantFrequencyHz= */ 11, 10, 0.5f, null)) .build(); VibratorInfo secondInfo = new VibratorInfo.Builder(/* id= */ 2) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) .setQFactor(10f) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile( + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy( /* resonantFrequencyHz= */ 11, 5, 1, null)) .build(); @@ -207,20 +207,20 @@ public class MultiVibratorInfoTest { assertEquals(10f, info.getQFactor(), TEST_TOLERANCE); assertEquals(11f, info.getResonantFrequencyHz(), TEST_TOLERANCE); // No frequency range defined. - assertTrue(info.getFrequencyProfile().isEmpty()); + assertTrue(info.getFrequencyProfileLegacy().isEmpty()); assertEquals(false, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL)); } @Test - public void testGetFrequencyProfile_differentResonantFrequencyOrResolutions_returnsEmpty() { + public void testGetFrequencyProfileLegacy_differentResonantFreqOrResolutions_returnsEmpty() { VibratorInfo firstInfo = new VibratorInfo.Builder(/* id= */ 1) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 1, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(1, 1, 1, new float[] { 0, 1 })) .build(); VibratorInfo differentResonantFrequency = new VibratorInfo.Builder(/* id= */ 2) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(2, 1, 1, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(2, 1, 1, new float[] { 0, 1 })) .build(); VibratorInfo info = new MultiVibratorInfo(/* id= */ 1, @@ -230,7 +230,7 @@ public class MultiVibratorInfoTest { VibratorInfo differentFrequencyResolution = new VibratorInfo.Builder(/* id= */ 2) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 2, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(1, 1, 2, new float[] { 0, 1 })) .build(); info = new MultiVibratorInfo(/* id= */ 1, @@ -240,15 +240,15 @@ public class MultiVibratorInfoTest { } @Test - public void testGetFrequencyProfile_missingValues_returnsEmpty() { + public void testGetFrequencyProfileLegacy_missingValues_returnsEmpty() { VibratorInfo firstInfo = new VibratorInfo.Builder(/* id= */ 1) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 1, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(1, 1, 1, new float[] { 0, 1 })) .build(); VibratorInfo missingResonantFrequency = new VibratorInfo.Builder(/* id= */ 2) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(Float.NaN, 1, 1, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(Float.NaN, 1, 1, new float[] { 0, 1 })) .build(); @@ -259,7 +259,7 @@ public class MultiVibratorInfoTest { VibratorInfo missingMinFrequency = new VibratorInfo.Builder(/* id= */ 2) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, Float.NaN, 1, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(1, Float.NaN, 1, new float[] { 0, 1 })) .build(); info = new MultiVibratorInfo(/* id= */ 1, @@ -269,7 +269,7 @@ public class MultiVibratorInfoTest { VibratorInfo missingFrequencyResolution = new VibratorInfo.Builder(/* id= */ 2) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, Float.NaN, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(1, 1, Float.NaN, new float[] { 0, 1 })) .build(); info = new MultiVibratorInfo(/* id= */ 1, @@ -279,7 +279,7 @@ public class MultiVibratorInfoTest { VibratorInfo missingMaxAmplitudes = new VibratorInfo.Builder(/* id= */ 2) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(1, 1, 1, null)) + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(1, 1, 1, null)) .build(); info = new MultiVibratorInfo(/* id= */ 1, new VibratorInfo[]{firstInfo, missingMaxAmplitudes}); @@ -288,20 +288,20 @@ public class MultiVibratorInfoTest { } @Test - public void testGetFrequencyProfile_unalignedMaxAmplitudes_returnsEmpty() { + public void testGetFrequencyProfileLegacy_unalignedMaxAmplitudes_returnsEmpty() { VibratorInfo firstInfo = new VibratorInfo.Builder(/* id= */ 1) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10, 0.5f, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(11, 10, 0.5f, new float[] { 0, 1, 1, 0 })) .build(); VibratorInfo unalignedMinFrequency = new VibratorInfo.Builder(/* id= */ 2) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.1f, 0.5f, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(11, 10.1f, 0.5f, new float[] { 0, 1, 1, 0 })) .build(); VibratorInfo thirdVibrator = new VibratorInfo.Builder(/* id= */ 2) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(11, 10.5f, 0.5f, new float[] { 0, 1, 1, 0 })) .build(); @@ -312,20 +312,20 @@ public class MultiVibratorInfoTest { } @Test - public void testGetFrequencyProfile_alignedProfiles_returnsIntersection() { + public void testGetFrequencyProfileLegacy_alignedProfiles_returnsIntersection() { VibratorInfo firstInfo = new VibratorInfo.Builder(/* id= */ 1) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10, 0.5f, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(11, 10, 0.5f, new float[] { 0.5f, 1, 1, 0.5f })) .build(); VibratorInfo secondInfo = new VibratorInfo.Builder(/* id= */ 2) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(11, 10.5f, 0.5f, new float[] { 1, 1, 1 })) .build(); VibratorInfo thirdVibrator = new VibratorInfo.Builder(/* id= */ 3) .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(11, 10.5f, 0.5f, new float[] { 0.8f, 1, 0.8f, 0.5f })) .build(); @@ -333,21 +333,23 @@ public class MultiVibratorInfoTest { new VibratorInfo[]{firstInfo, secondInfo, thirdVibrator}); assertEquals( - new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, new float[] { 0.8f, 1, 0.5f }), - info.getFrequencyProfile()); + new VibratorInfo.FrequencyProfileLegacy(11, 10.5f, 0.5f, + new float[]{0.8f, 1, 0.5f}), + info.getFrequencyProfileLegacy()); assertEquals(true, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL)); // Third vibrator without frequency control capability. thirdVibrator = new VibratorInfo.Builder(/* id= */ 3) - .setFrequencyProfile(new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, + .setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy(11, 10.5f, 0.5f, new float[] { 0.8f, 1, 0.8f, 0.5f })) .build(); info = new MultiVibratorInfo(/* id= */ 1, new VibratorInfo[]{firstInfo, secondInfo, thirdVibrator}); assertEquals( - new VibratorInfo.FrequencyProfile(11, 10.5f, 0.5f, new float[] { 0.8f, 1, 0.5f }), - info.getFrequencyProfile()); + new VibratorInfo.FrequencyProfileLegacy(11, 10.5f, 0.5f, + new float[]{0.8f, 1, 0.5f}), + info.getFrequencyProfileLegacy()); assertEquals(false, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL)); } @@ -355,7 +357,7 @@ public class MultiVibratorInfoTest { * Asserts that the frequency profile is empty, and therefore frequency control isn't supported. */ private void assertEmptyFrequencyProfileAndControl(VibratorInfo info) { - assertTrue(info.getFrequencyProfile().isEmpty()); + assertTrue(info.getFrequencyProfileLegacy().isEmpty()); assertEquals(false, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL)); } } diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 880f30c6cdc0..2e72f0ec90b8 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -585,6 +585,8 @@ applications that come with the platform <permission name="android.permission.EXECUTE_APP_FUNCTIONS" /> <!-- Permission required for CTS test - CtsNfcTestCases --> <permission name="android.permission.NFC_SET_CONTROLLER_ALWAYS_ON" /> + <!-- Permission required for CTS test - CtsAppTestCases --> + <permission name="android.permission.KILL_UID" /> </privapp-permissions> <privapp-permissions package="com.android.statementservice"> diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java index 9887c272e7f8..af26bd0a3404 100644 --- a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java +++ b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java @@ -130,10 +130,6 @@ public final class RequiresPermissionChecker extends BugChecker .onDescendantOf("android.content.Context") .withNameMatching( Pattern.compile("^send(Ordered|Sticky)?Broadcast.*AsUser.*$"))); - private static final Matcher<ExpressionTree> SEND_PENDING_INTENT = methodInvocation( - instanceMethod() - .onDescendantOf("android.app.PendingIntent") - .named("send")); private static final Matcher<ExpressionTree> INTENT_SET_ACTION = methodInvocation( instanceMethod().onDescendantOf("android.content.Intent").named("setAction")); diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 0b3e5456d81c..28c2ca36fd2e 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -155,7 +155,7 @@ public class Canvas extends BaseCanvas { /** * Indicates whether this Canvas is drawing high contrast text. * - * @see android.view.accessibility.AccessibilityManager#isHighTextContrastEnabled() + * @see android.view.accessibility.AccessibilityManager#isHighContrastTextEnabled() * @return True if high contrast text is enabled, false otherwise. * * @hide diff --git a/keystore/OWNERS b/keystore/OWNERS index 689177715711..ea783e7f0c06 100644 --- a/keystore/OWNERS +++ b/keystore/OWNERS @@ -1,5 +1,6 @@ # Bug component: 189335 +ascull@google.com drysdale@google.com -eranm@google.com jbires@google.com +sethmo@google.com swillden@google.com diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp index cee7b418710e..4642fe59bcb2 100644 --- a/libs/WindowManager/Shell/Android.bp +++ b/libs/WindowManager/Shell/Android.bp @@ -197,6 +197,7 @@ java_library { android_library { name: "WindowManager-Shell", srcs: [ + "src/com/android/wm/shell/EventLogTags.logtags", ":wm_shell_protolog_src", // TODO(b/168581922) protologtool do not support kotlin(*.kt) ":wm_shell-sources-kt", diff --git a/libs/WindowManager/Shell/res/color/open_by_default_settings_dialog_radio_button_color.xml b/libs/WindowManager/Shell/res/color/open_by_default_settings_dialog_radio_button_color.xml new file mode 100644 index 000000000000..0f9b28a07bde --- /dev/null +++ b/libs/WindowManager/Shell/res/color/open_by_default_settings_dialog_radio_button_color.xml @@ -0,0 +1,22 @@ +<?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. + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> + <item android:state_checked="true" + android:color="?androidprv:attr/materialColorPrimaryContainer"/> + <item android:color="?androidprv:attr/materialColorSurfaceContainer"/> +</selector> diff --git a/libs/WindowManager/Shell/res/drawable/app_handle_education_tooltip_icon.xml b/libs/WindowManager/Shell/res/drawable/app_handle_education_tooltip_icon.xml index 07e5ac1a604b..b74d92221061 100644 --- a/libs/WindowManager/Shell/res/drawable/app_handle_education_tooltip_icon.xml +++ b/libs/WindowManager/Shell/res/drawable/app_handle_education_tooltip_icon.xml @@ -22,6 +22,6 @@ android:viewportHeight="960" android:viewportWidth="960"> <path - android:fillColor="@android:color/system_on_tertiary_fixed" + android:fillColor="@android:color/system_on_tertiary_container_light" android:pathData="M419,880Q391,880 366.5,868Q342,856 325,834L107,557L126,537Q146,516 174,512Q202,508 226,523L300,568L300,240Q300,223 311.5,211.5Q323,200 340,200Q357,200 369,211.5Q381,223 381,240L381,712L284,652L388,785Q394,792 402,796Q410,800 419,800L640,800Q673,800 696.5,776.5Q720,753 720,720L720,560Q720,543 708.5,531.5Q697,520 680,520L461,520L461,440L680,440Q730,440 765,475Q800,510 800,560L800,720Q800,786 753,833Q706,880 640,880L419,880ZM167,340Q154,318 147,292.5Q140,267 140,240Q140,157 198.5,98.5Q257,40 340,40Q423,40 481.5,98.5Q540,157 540,240Q540,267 533,292.5Q526,318 513,340L444,300Q452,286 456,271.5Q460,257 460,240Q460,190 425,155Q390,120 340,120Q290,120 255,155Q220,190 220,240Q220,257 224,271.5Q228,286 236,300L167,340ZM502,620L502,620L502,620L502,620Q502,620 502,620Q502,620 502,620L502,620Q502,620 502,620Q502,620 502,620L502,620Q502,620 502,620Q502,620 502,620L502,620L502,620Z" /> </vector> diff --git a/libs/WindowManager/Shell/res/drawable/desktop_mode_ic_handle_menu_open_by_default_settings.xml b/libs/WindowManager/Shell/res/drawable/desktop_mode_ic_handle_menu_open_by_default_settings.xml new file mode 100644 index 000000000000..4070c3d577d8 --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/desktop_mode_ic_handle_menu_open_by_default_settings.xml @@ -0,0 +1,25 @@ +<?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. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="960" + android:viewportHeight="960" + android:tint="?attr/colorControlNormal"> + <path android:fillColor="@android:color/black" + android:pathData="M370,880L354,752Q341,747 329.5,740Q318,733 307,725L188,775L78,585L181,507Q180,500 180,493.5Q180,487 180,480Q180,473 180,466.5Q180,460 181,453L78,375L188,185L307,235Q318,227 330,220Q342,213 354,208L370,80L590,80L606,208Q619,213 630.5,220Q642,227 653,235L772,185L882,375L779,453Q780,460 780,466.5Q780,473 780,480Q780,487 780,493.5Q780,500 778,507L881,585L771,775L653,725Q642,733 630,740Q618,747 606,752L590,880L370,880ZM440,800L519,800L533,694Q564,686 590.5,670.5Q617,655 639,633L738,674L777,606L691,541Q696,527 698,511.5Q700,496 700,480Q700,464 698,448.5Q696,433 691,419L777,354L738,286L639,328Q617,305 590.5,289.5Q564,274 533,266L520,160L441,160L427,266Q396,274 369.5,289.5Q343,305 321,327L222,286L183,354L269,418Q264,433 262,448Q260,463 260,480Q260,496 262,511Q264,526 269,541L183,606L222,674L321,632Q343,655 369.5,670.5Q396,686 427,694L440,800ZM482,620Q540,620 581,579Q622,538 622,480Q622,422 581,381Q540,340 482,340Q423,340 382.5,381Q342,422 342,480Q342,538 382.5,579Q423,620 482,620ZM480,480L480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Z"/> +</vector> diff --git a/packages/SystemUI/res/layout/notification_template_en_route_contracted.xml b/libs/WindowManager/Shell/res/drawable/open_by_default_settings_dialog_background.xml index e7a40d129d50..4eb22712f5e1 100644 --- a/packages/SystemUI/res/layout/notification_template_en_route_contracted.xml +++ b/libs/WindowManager/Shell/res/drawable/open_by_default_settings_dialog_background.xml @@ -14,16 +14,9 @@ ~ limitations under the License. --> -<com.android.systemui.statusbar.notification.row.ui.view.EnRouteView +<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@*android:id/status_bar_latest_event_content" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_weight="1" - android:minHeight="@*android:dimen/notification_headerless_min_height" - android:tag="enroute" - > - - <include layout="@*android:layout/notification_template_material_base" /> - -</com.android.systemui.statusbar.notification.row.ui.view.EnRouteView>
\ No newline at end of file + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> + <solid android:color="?androidprv:attr/materialColorSurfaceContainer"/> + <corners android:radius="28dp"/> +</shape> diff --git a/libs/WindowManager/Shell/res/drawable/open_by_default_settings_dialog_dismiss_button_background.xml b/libs/WindowManager/Shell/res/drawable/open_by_default_settings_dialog_dismiss_button_background.xml new file mode 100644 index 000000000000..2b2e9df07dce --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/open_by_default_settings_dialog_dismiss_button_background.xml @@ -0,0 +1,22 @@ +<?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. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:shape="rectangle"> + <solid android:color="?androidprv:attr/materialColorPrimary"/> + <corners android:radius="50dp"/> +</shape> diff --git a/libs/WindowManager/Shell/res/drawable/open_by_default_settings_dialog_radio_buttons_background.xml b/libs/WindowManager/Shell/res/drawable/open_by_default_settings_dialog_radio_buttons_background.xml new file mode 100644 index 000000000000..1ac952bf9112 --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/open_by_default_settings_dialog_radio_buttons_background.xml @@ -0,0 +1,21 @@ +<?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. + --> + +<shape android:shape="rectangle" + xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="@color/open_by_default_settings_dialog_radio_button_color"/> + <corners android:radius="16dp"/> +</shape> diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml index 6913e54c2b10..aeb734e2d2d3 100644 --- a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml +++ b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml @@ -165,17 +165,28 @@ android:layout_height="@dimen/desktop_mode_handle_menu_open_in_browser_pill_height" android:layout_marginTop="@dimen/desktop_mode_handle_menu_pill_spacing_margin" android:layout_marginStart="1dp" - android:orientation="vertical" + android:orientation="horizontal" android:elevation="@dimen/desktop_mode_handle_menu_pill_elevation" android:background="@drawable/desktop_mode_decor_handle_menu_background"> <Button android:id="@+id/open_in_browser_button" + android:layout_weight="1" android:contentDescription="@string/open_in_browser_text" android:text="@string/open_in_browser_text" android:drawableStart="@drawable/desktop_mode_ic_handle_menu_open_in_browser" android:drawableTint="?androidprv:attr/materialColorOnSurface" style="@style/DesktopModeHandleMenuActionButton"/> + + <ImageButton + android:id="@+id/open_by_default_button" + android:layout_width="20dp" + android:layout_height="20dp" + android:layout_gravity="end|center_vertical" + android:layout_marginEnd="16dp" + android:contentDescription="@string/open_by_default_settings_text" + android:src="@drawable/desktop_mode_ic_handle_menu_open_by_default_settings" + android:tint="?androidprv:attr/materialColorOnSurface"/> </LinearLayout> </LinearLayout> diff --git a/libs/WindowManager/Shell/res/layout/desktop_windowing_education_tooltip_container.xml b/libs/WindowManager/Shell/res/layout/desktop_windowing_education_tooltip_container.xml index bdee8836dc2e..09a049c060eb 100644 --- a/libs/WindowManager/Shell/res/layout/desktop_windowing_education_tooltip_container.xml +++ b/libs/WindowManager/Shell/res/layout/desktop_windowing_education_tooltip_container.xml @@ -37,7 +37,7 @@ android:layout_marginStart="2dp" android:lineHeight="20dp" android:maxWidth="150dp" - android:textColor="@android:color/system_on_tertiary_fixed" + android:textColor="@android:color/system_on_tertiary_container_light" android:textFontWeight="500" android:textSize="14sp" /> </LinearLayout>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/layout/open_by_default_settings_dialog.xml b/libs/WindowManager/Shell/res/layout/open_by_default_settings_dialog.xml new file mode 100644 index 000000000000..8ff382bbc7b4 --- /dev/null +++ b/libs/WindowManager/Shell/res/layout/open_by_default_settings_dialog.xml @@ -0,0 +1,130 @@ +<?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. + --> + +<com.android.wm.shell.apptoweb.OpenByDefaultDialogView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + style="@style/LetterboxDialog"> + + <!-- The background of the top-level layout acts as the background dim. --> + <FrameLayout + android:id="@+id/open_by_default_dialog_container" + android:layout_width="@dimen/open_by_default_settings_dialog_width" + android:layout_height="wrap_content" + android:background="@drawable/open_by_default_settings_dialog_background" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"> + + <!-- The ScrollView should only wrap the content of the dialog, otherwise the background + corner radius will be cut off when scrolling to the top/bottom. --> + <ScrollView + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <LinearLayout + android:padding="24dp" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_horizontal" + android:orientation="vertical"> + + <ImageView + android:id="@+id/application_icon" + android:layout_width="32dp" + android:layout_height="32dp" + android:layout_gravity="center_horizontal" + android:importantForAccessibility="no" + android:layout_marginTop="24dp" + android:layout_marginBottom="16dp" + android:scaleType="centerCrop"/> + + <TextView + android:id="@+id/application_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginBottom="8dp" + android:lineHeight="32dp" + android:textFontWeight="400" + android:textSize="24sp" + android:textColor="?androidprv:attr/materialColorOnSurfaceVariant" + tools:text="Gmail" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="12sp" + android:textFontWeight="400" + android:lineHeight="16dp" + android:layout_gravity="center_horizontal" + android:layout_marginBottom="16dp" + android:textColor="?androidprv:attr/materialColorOnSurfaceVariant" + android:text="@string/open_by_default_dialog_subheader_text"/> + + <RadioGroup + android:id="@+id/open_by_default_radio_group" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal"> + <RadioButton + android:id="@+id/open_in_app_button" + android:layout_width="@dimen/open_by_default_settings_dialog_radio_button_width" + android:layout_height="@dimen/open_by_default_settings_dialog_radio_button_height" + android:paddingStart="20dp" + android:paddingEnd="0dp" + android:layout_marginHorizontal="16dp" + android:layout_marginBottom="4dp" + android:text="@string/open_by_default_dialog_in_app_text" + android:textFontWeight="500" + android:textSize="16sp" + android:lineHeight="24dp" + android:background="@drawable/open_by_default_settings_dialog_radio_buttons_background"/> + <RadioButton + android:id="@+id/open_in_browser_button" + android:layout_width="@dimen/open_by_default_settings_dialog_radio_button_width" + android:layout_height="@dimen/open_by_default_settings_dialog_radio_button_height" + android:paddingStart="20dp" + android:paddingEnd="0dp" + android:layout_marginStart="16dp" + android:text="@string/open_by_default_dialog_in_browser_text" + android:textFontWeight="500" + android:textSize="16sp" + android:lineHeight="24dp" + android:background="@drawable/open_by_default_settings_dialog_radio_buttons_background"/> + </RadioGroup> + + <Button + android:id="@+id/open_by_default_settings_dialog_dismiss_button" + android:layout_width="wrap_content" + android:layout_height="36dp" + android:text="@string/open_by_default_dialog_dismiss_button_text" + android:layout_gravity="end" + android:layout_marginHorizontal="24dp" + android:layout_marginTop="32dp" + android:layout_marginBottom="24dp" + android:textSize="14sp" + android:textFontWeight="500" + android:textColor="?androidprv:attr/materialColorOnPrimary" + android:background="@drawable/open_by_default_settings_dialog_dismiss_button_background"/> + </LinearLayout> + </ScrollView> + </FrameLayout> +</com.android.wm.shell.apptoweb.OpenByDefaultDialogView> + diff --git a/libs/WindowManager/Shell/res/layout/pip2_menu_action.xml b/libs/WindowManager/Shell/res/layout/pip2_menu_action.xml new file mode 100644 index 000000000000..04ece31cb820 --- /dev/null +++ b/libs/WindowManager/Shell/res/layout/pip2_menu_action.xml @@ -0,0 +1,39 @@ +<?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. +--> +<com.android.wm.shell.pip2.phone.PipMenuActionView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="@dimen/pip_action_size" + android:layout_height="@dimen/pip_action_size" + android:background="?android:selectableItemBackgroundBorderless" + android:forceHasOverlappingRendering="false"> + + <ImageView + android:id="@+id/custom_close_bg" + android:layout_width="@dimen/pip_custom_close_bg_size" + android:layout_height="@dimen/pip_custom_close_bg_size" + android:layout_gravity="center" + android:src="@drawable/pip_custom_close_bg" + android:visibility="gone"/> + + <ImageView + android:id="@+id/image" + android:layout_width="@dimen/pip_action_inner_size" + android:layout_height="@dimen/pip_action_inner_size" + android:layout_gravity="center" + android:scaleType="fitXY"/> + +</com.android.wm.shell.pip2.phone.PipMenuActionView> diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml index 50aa4ca1a1f1..582c1a22a203 100644 --- a/libs/WindowManager/Shell/res/values-af/strings.xml +++ b/libs/WindowManager/Shell/res/values-af/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamerakwessies?\nTik om aan te pas"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nie opgelos nie?\nTik om terug te stel"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Geen kamerakwessies nie? Tik om toe te maak."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Tik om die appkieslys oop te maak"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Tik om verskeie apps saam te wys"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Keer terug na volskerm van die appkieslys af"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Sien en doen meer"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Sleep ’n ander app in vir verdeelde skerm"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dubbeltik buite ’n program om dit te herposisioneer"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Bestuur vensters"</string> <string name="close_text" msgid="4986518933445178928">"Maak toe"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Maak kieslys toe"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Maak kieslys oop"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimeer skerm"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Gryp skerm vas"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Hierdie app se grootte kan nie verander word nie"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"App kan nie hierheen geskuif word nie"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimeer"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Spring na links"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Spring na regs"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml index 281e313d328f..0798c9a8fbe0 100644 --- a/libs/WindowManager/Shell/res/values-am/strings.xml +++ b/libs/WindowManager/Shell/res/values-am/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"የካሜራ ችግሮች አሉ?\nዳግም ለማበጀት መታ ያድርጉ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"አልተስተካከለም?\nለማህደር መታ ያድርጉ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ምንም የካሜራ ችግሮች የሉም? ለማሰናበት መታ ያድርጉ።"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"የመተግበሪያ ምናሌውን ለመክፈት መታ ያድርጉ"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"በርካታ መተግበሪያዎችን በአንድ ላይ ለማየት መታ ያድርጉ"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"ከመተግበሪያ ምናሌው ወደ ሙሉ ማያ ገፅ ይመለሱ"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ተጨማሪ ይመልከቱ እና ያድርጉ"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"ለተከፈለ ማያ ገፅ ሌላ መተግበሪያ ይጎትቱ"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ቦታውን ለመቀየር ከመተግበሪያው ውጭ ሁለቴ መታ ያድርጉ"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"መስኮቶችን አስተዳድር"</string> <string name="close_text" msgid="4986518933445178928">"ዝጋ"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"ምናሌ ዝጋ"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"ምናሌን ክፈት"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"የማያ ገጹ መጠን አሳድግ"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ማያ ገጹን አሳድግ"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"ይህ መተግበሪያ መጠኑ ሊቀየር አይችልም"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"መተግበሪያ ወደዚህ መንቀሳቀስ አይችልም"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"አሳድግ"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ወደ ግራ አሳድግ"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ወደ ቀኝ አሳድግ"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml index 2c0b34a604a9..9dcb5ec26273 100644 --- a/libs/WindowManager/Shell/res/values-ar/strings.xml +++ b/libs/WindowManager/Shell/res/values-ar/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"هل هناك مشاكل في الكاميرا؟\nانقر لإعادة الضبط."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ألم يتم حل المشكلة؟\nانقر للعودة"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"أليس هناك مشاكل في الكاميرا؟ انقر للإغلاق."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"انقر لفتح قائمة التطبيق"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"انقر لعرض عدة تطبيقات معًا"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"الرجوع إلى وضع ملء الشاشة من قائمة التطبيق"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"استخدام تطبيقات متعدّدة في وقت واحد"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"اسحب تطبيقًا آخر لاستخدام وضع تقسيم الشاشة."</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"انقر مرّتين خارج تطبيق لتغيير موضعه."</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"إدارة النوافذ"</string> <string name="close_text" msgid="4986518933445178928">"إغلاق"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"إغلاق القائمة"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"فتح القائمة"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"تكبير الشاشة إلى أقصى حدّ"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"التقاط صورة للشاشة"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"لا يمكن تغيير حجم نافذة هذا التطبيق"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"لا يمكن نقل التطبيق إلى هنا"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"تكبير"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"المحاذاة إلى اليسار"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"المحاذاة إلى اليمين"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml index c5e37162e2d9..484eef53e087 100644 --- a/libs/WindowManager/Shell/res/values-as/strings.xml +++ b/libs/WindowManager/Shell/res/values-as/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"কেমেৰাৰ কোনো সমস্যা হৈছে নেকি?\nপুনৰ খাপ খোৱাবলৈ টিপক"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"এইটো সমাধান কৰা নাই নেকি?\nপূৰ্বাৱস্থালৈ নিবলৈ টিপক"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"কেমেৰাৰ কোনো সমস্যা নাই নেকি? অগ্ৰাহ্য কৰিবলৈ টিপক।"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"এপৰ মেনুখন খুলিবলৈ টিপক"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"একাধিক এপ্ একেলগে দেখুৱাবলৈ টিপক"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"এপৰ মেনুখনৰ পৰা পূৰ্ণ স্ক্ৰীনলৈ উভতি যাওক"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"চাওক আৰু অধিক কৰক"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"বিভাজিত স্ক্ৰীনৰ বাবে অন্য এটা এপ্ টানি আনি এৰক"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"এপ্টোৰ স্থান সলনি কৰিবলৈ ইয়াৰ বাহিৰত দুবাৰ টিপক"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"ৱিণ্ড’ পৰিচালনা কৰক"</string> <string name="close_text" msgid="4986518933445178928">"বন্ধ কৰক"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"মেনু বন্ধ কৰক"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"মেনু খোলক"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"স্ক্ৰীন মেক্সিমাইজ কৰক"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"স্ক্ৰীন স্নেপ কৰক"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"এই এপ্টোৰ আকাৰ সলনি কৰিব নোৱাৰি"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ইয়ালৈ এপ্টো আনিব নোৱাৰি"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"মেক্সিমাইজ কৰক"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"বাওঁফাললৈ স্নেপ কৰক"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"সোঁফাললৈ স্নেপ কৰক"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml index e23e8d049a8f..ded6da80464d 100644 --- a/libs/WindowManager/Shell/res/values-az/strings.xml +++ b/libs/WindowManager/Shell/res/values-az/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamera problemi var?\nBərpa etmək üçün toxunun"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Düzəltməmisiniz?\nGeri qaytarmaq üçün toxunun"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kamera problemi yoxdur? Qapatmaq üçün toxunun."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Tətbiq menyusunu açmaq üçün toxunun"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Bir neçə tətbiqi birlikdə göstərmək üçün toxunun"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Tətbiq menyusundan tam ekrana qayıdın"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Ardını görün və edin"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Bölünmüş ekran üçün başqa tətbiq sürüşdürün"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Tətbiqin yerini dəyişmək üçün kənarına iki dəfə toxunun"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Pəncərələri idarə edin"</string> <string name="close_text" msgid="4986518933445178928">"Bağlayın"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Menyunu bağlayın"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Menyunu açın"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ekranı maksimum böyüdün"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ekranı çəkin"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Bu tətbiqin ölçüsünü dəyişmək olmur"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Tətbiqi bura köçürmək mümkün deyil"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Böyüdün"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Sola tərəf çəkin"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Sağa tərəf çəkin"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml index 283d1f5578cf..415547c790f4 100644 --- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml +++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Imate problema sa kamerom?\nDodirnite da biste ponovo uklopili"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problem nije rešen?\nDodirnite da biste vratili"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemate problema sa kamerom? Dodirnite da biste odbacili."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Dodirnite da biste otvorili meni aplikacije"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Dodirnite da biste prikazali više aplikacija zajedno"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Vratite se iz menija aplikacije na prikaz preko celog ekrana"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Vidite i uradite više"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Prevucite drugu aplikaciju da biste koristili podeljeni ekran"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvaput dodirnite izvan aplikacije da biste promenili njenu poziciju"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Upravljajte prozorima"</string> <string name="close_text" msgid="4986518933445178928">"Zatvorite"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite meni"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otvorite meni"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Povećaj ekran"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Uklopi ekran"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Veličina ove aplikacije ne može da se promeni"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikacija ne može da se premesti ovde"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Uvećajte"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Prikačite levo"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Prikačite desno"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml index 48914f1eb27c..aded647d43a1 100644 --- a/libs/WindowManager/Shell/res/values-be/strings.xml +++ b/libs/WindowManager/Shell/res/values-be/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Праблемы з камерай?\nНацісніце, каб пераабсталяваць"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не ўдалося выправіць?\nНацісніце, каб аднавіць"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ніякіх праблем з камерай? Націсніце, каб адхіліць."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Адкрыць меню праграмы"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Паказаць некалькі праграм разам"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Вярнуцца ў поўнаэкранны рэжым з меню праграмы"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Адначасова выконвайце розныя задачы"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Перацягніце іншую праграму, каб выкарыстоўваць падзелены экран"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Двойчы націсніце экран па-за праграмай, каб перамясціць яе"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Кіраваць вокнамі"</string> <string name="close_text" msgid="4986518933445178928">"Закрыць"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Закрыць меню"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Адкрыць меню"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Разгарнуць на ўвесь экран"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Размясціць на палавіне экрана"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Немагчыма змяніць памер праграмы"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Нельга перамясціць сюды праграму"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Разгарнуць"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Размясціць злева"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Размясціць справа"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml index f5e94da56055..8a69176f2b6f 100644 --- a/libs/WindowManager/Shell/res/values-bg/strings.xml +++ b/libs/WindowManager/Shell/res/values-bg/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Имате проблеми с камерата?\nДокоснете за ремонтиране"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Проблемът не се отстрани?\nДокоснете за връщане в предишното състояние"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нямате проблеми с камерата? Докоснете, за да отхвърлите."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Докоснете, за да отворите менюто на приложението"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Докоснете, за да видите няколко приложения заедно"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Връщане към цял екран от менюто на приложението"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Преглеждайте и правете повече неща"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Преместете друго приложение с плъзгане, за да преминете в режим за разделен екран"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Докоснете два пъти извън дадено приложение, за да промените позицията му"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Отваряне на менюто"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Увеличаване на екрана"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Прилепване на екрана"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Това приложение не може да бъде преоразмерено"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Приложението не може да бъде преместено тук"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Увеличаване"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Прилепване наляво"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Прилепване надясно"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml index 5d6374403662..3799c9fd1dca 100644 --- a/libs/WindowManager/Shell/res/values-bn/strings.xml +++ b/libs/WindowManager/Shell/res/values-bn/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ক্যামেরা সংক্রান্ত সমস্যা?\nরিফিট করতে ট্যাপ করুন"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"এখনও সমাধান হয়নি?\nরিভার্ট করার জন্য ট্যাপ করুন"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ক্যামেরা সংক্রান্ত সমস্যা নেই? বাতিল করতে ট্যাপ করুন।"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"অ্যাপ মেনু খুলতে ট্যাপ করুন"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"একাধিক অ্যাপ একসাথে দেখতে ট্যাপ করুন"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"অ্যাপ মেনু থেকে ফুল-স্ক্রিন মোডে ফিরে যান"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"দেখুন ও আরও অনেক কিছু করুন"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"স্প্লিট স্ক্রিনের ক্ষেত্রে অন্য কোনও অ্যাপ টেনে আনুন"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"কোনও অ্যাপের স্থান পরিবর্তন করতে তার বাইরে ডবল ট্যাপ করুন"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"মেনু খুলুন"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"স্ক্রিন বড় করুন"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"স্ক্রিনে অ্যাপ মানানসই হিসেবে ছোট বড় করুন"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"এই অ্যাপ ছোট বড় করা যাবে না"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"অ্যাপটি এখানে সরানো যাবে না"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"বড় করুন"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"বাঁদিকে স্ন্যাপ করুন"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ডানদিকে স্ন্যাপ করুন"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml index 95362bbfeab5..f0d172ad20d0 100644 --- a/libs/WindowManager/Shell/res/values-bs/strings.xml +++ b/libs/WindowManager/Shell/res/values-bs/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi s kamerom?\nDodirnite da ponovo namjestite"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nije popravljeno?\nDodirnite da vratite"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nema problema s kamerom? Dodirnite da odbacite."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Otvaranje menija aplikacije dodirom"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Istovremeni prikaz više aplikacija dodirom"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Povratak na prikaz preko cijelog ekrana putem menija aplikacije"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Pogledajte i učinite više"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Prevucite još jednu aplikaciju za podijeljeni ekran"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvaput dodirnite izvan aplikacije da promijenite njen položaj"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Upravljanje prozorima"</string> <string name="close_text" msgid="4986518933445178928">"Zatvaranje"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvaranje menija"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otvaranje menija"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimiziraj ekran"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Snimi ekran"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Nije moguće promijeniti veličinu aplikacije"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Ne možete premjestiti aplikaciju ovdje"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimiziranje"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Pomicanje ulijevo"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Pomicanje udesno"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml index e0b25389e6f1..bf35c90f89ab 100644 --- a/libs/WindowManager/Shell/res/values-ca/strings.xml +++ b/libs/WindowManager/Shell/res/values-ca/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Tens problemes amb la càmera?\nToca per resoldre\'ls"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"El problema no s\'ha resolt?\nToca per desfer els canvis"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No tens cap problema amb la càmera? Toca per ignorar."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Toca per obrir el menú de l\'aplicació"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Toca per mostrar diverses aplicacions alhora"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Torna a la pantalla completa des del menú de l\'aplicació"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Consulta i fes més coses"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Arrossega una altra aplicació per utilitzar la pantalla dividida"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Fes doble toc fora d\'una aplicació per canviar-ne la posició"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Gestiona les finestres"</string> <string name="close_text" msgid="4986518933445178928">"Tanca"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Tanca el menú"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Obre el menú"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximitza la pantalla"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ajusta la pantalla"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"No es pot canviar la mida d\'aquesta aplicació"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"L\'aplicació no es pot moure aquí"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximitza"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Ajusta a l\'esquerra"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Ajusta a la dreta"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml index 716491020c65..7fc1033b71be 100644 --- a/libs/WindowManager/Shell/res/values-cs/strings.xml +++ b/libs/WindowManager/Shell/res/values-cs/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problémy s fotoaparátem?\nKlepnutím vyřešíte"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nepomohlo to?\nKlepnutím se vrátíte"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Žádné problémy s fotoaparátem? Klepnutím zavřete."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Klepnutím otevřete nabídku aplikace"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Klepnutím zobrazíte několik aplikací najednou"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Návrat na celou obrazovku z nabídky aplikace"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Lepší zobrazení a více možností"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Přetáhnutím druhé aplikace použijete rozdělenou obrazovku"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvojitým klepnutím mimo aplikaci změníte její umístění"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otevřít nabídku"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximalizovat obrazovku"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Rozpůlit obrazovku"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Velikost aplikace nelze změnit"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikaci sem nelze přesunout"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximalizovat"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Přichytit vlevo"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Přichytit vpravo"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml index fdc59137dd5e..717e6c42dd51 100644 --- a/libs/WindowManager/Shell/res/values-da/strings.xml +++ b/libs/WindowManager/Shell/res/values-da/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Har du problemer med dit kamera?\nTryk for at gendanne det oprindelige format"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Løste det ikke problemet?\nTryk for at fortryde"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Har du ingen problemer med dit kamera? Tryk for at afvise."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Tryk for at åbne appmenuen"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Tryk for at se flere apps på én gang"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Gå tilbage til fuld skærm via appmenuen"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Se og gør mere"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Træk en anden app hertil for at bruge opdelt skærm"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Tryk to gange uden for en app for at justere dens placering"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Administrer vinduer"</string> <string name="close_text" msgid="4986518933445178928">"Luk"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Luk menu"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Åbn menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimér skærm"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Tilpas skærm"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Størrelsen på denne app kan ikke justeres"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Apps kan ikke flyttes hertil"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimér"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Fastgør til venstre"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Fastgør til højre"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index 913e3d0abf0f..bccd4ae1d6df 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Probleme mit der Kamera?\nZum Anpassen tippen."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Das Problem ist nicht behoben?\nZum Rückgängigmachen tippen."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Keine Probleme mit der Kamera? Zum Schließen tippen."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Zum Öffnen des App-Menüs tippen"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Tippen, um mehrere Apps gleichzeitig anzuzeigen"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Über das App-Menü zum Vollbildmodus zurückkehren"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Mehr sehen und erledigen"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Für Splitscreen-Modus weitere App hineinziehen"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Außerhalb einer App doppeltippen, um die Position zu ändern"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Fenster verwalten"</string> <string name="close_text" msgid="4986518933445178928">"Schließen"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Menü schließen"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Menü öffnen"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Bildschirm maximieren"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Bildschirm teilen"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Die Größe dieser App kann nicht geändert werden"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Die App kann nicht hierher verschoben werden"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximieren"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Links andocken"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Rechts andocken"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml index 564fa910fdcd..1039273978e1 100644 --- a/libs/WindowManager/Shell/res/values-el/strings.xml +++ b/libs/WindowManager/Shell/res/values-el/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Προβλήματα με την κάμερα;\nΠατήστε για επιδιόρθωση."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Δεν διορθώθηκε;\nΠατήστε για επαναφορά."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Δεν αντιμετωπίζετε προβλήματα με την κάμερα; Πατήστε για παράβλεψη."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Πατήστε για άνοιγμα του μενού της εφαρμογής"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Πατήστε για εμφάνιση πολλών εφαρμογών μαζί"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Επιστρέψτε στην πλήρη οθόνη από το μενού της εφαρμογής"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Δείτε και κάντε περισσότερα"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Σύρετε σε μια άλλη εφαρμογή για διαχωρισμό οθόνης."</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Πατήστε δύο φορές έξω από μια εφαρμογή για να αλλάξετε τη θέση της"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Διαχείριση παραθύρων"</string> <string name="close_text" msgid="4986518933445178928">"Κλείσιμο"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Κλείσιμο μενού"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Άνοιγμα μενού"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Μεγιστοποίηση οθόνης"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Προβολή στο μισό της οθόνης"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Δεν είναι δυνατή η αλλαγή μεγέθους αυτής της εφαρμογής"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Δεν είναι δυνατή η μετακίνηση της εφαρμογής εδώ"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Μεγιστοποίηση"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Κούμπωμα αριστερά"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Κούμπωμα δεξιά"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml index 766852d4b1f0..98da627a4434 100644 --- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Tap to open the app menu"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Tap to show multiple apps together"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Return to fullscreen from the app menu"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"See and do more"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Drag in another app for split screen"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Double-tap outside an app to reposition it"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Open menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximise screen"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Snap screen"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"This app can\'t be resized"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"App can\'t be moved here"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximise"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Snap left"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Snap right"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml index aa3a484079f8..e928fe02fbcf 100644 --- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Tap to open the app menu"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Tap to show multiple apps together"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Return to fullscreen from the app menu"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"See and do more"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Drag in another app for split screen"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Double-tap outside an app to reposition it"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Open Menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximize Screen"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Snap Screen"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"This app can\'t be resized"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"App can\'t be moved here"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximize"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Snap left"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Snap right"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml index d5b97037496a..98da627a4434 100644 --- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml @@ -97,12 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string> - <!-- no translation found for windowing_app_handle_education_tooltip (6398482412956375783) --> - <skip /> - <!-- no translation found for windowing_desktop_mode_image_button_education_tooltip (6285279585554484957) --> - <skip /> - <!-- no translation found for windowing_desktop_mode_exit_education_tooltip (6685429075790085337) --> - <skip /> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Tap to open the app menu"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Tap to show multiple apps together"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Return to fullscreen from the app menu"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"See and do more"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Drag in another app for split screen"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Double-tap outside an app to reposition it"</string> @@ -135,9 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Open menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximise screen"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Snap screen"</string> - <!-- no translation found for desktop_mode_non_resizable_snap_text (3771776422751387878) --> - <skip /> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"App can\'t be moved here"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximise"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Snap left"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Snap right"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml index 766852d4b1f0..98da627a4434 100644 --- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Tap to open the app menu"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Tap to show multiple apps together"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Return to fullscreen from the app menu"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"See and do more"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Drag in another app for split screen"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Double-tap outside an app to reposition it"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Open menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximise screen"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Snap screen"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"This app can\'t be resized"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"App can\'t be moved here"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximise"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Snap left"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Snap right"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml index bda5132156cd..e48a9dbc2ebb 100644 --- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Camera issues?\nTap to refit"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Didn’t fix it?\nTap to revert"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No camera issues? Tap to dismiss."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Tap to open the app menu"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Tap to show multiple apps together"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Return to fullscreen from the app menu"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"See and do more"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Drag in another app for split screen"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Double-tap outside an app to reposition it"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Open Menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximize Screen"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Snap Screen"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"This app can\'t be resized"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"App can\'t be moved here"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximize"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Snap left"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Snap right"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml index a4c03632cbe4..f349cbb1aeed 100644 --- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml +++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"¿Tienes problemas con la cámara?\nPresiona para reajustarla"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"¿No se resolvió?\nPresiona para revertir los cambios"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"¿No tienes problemas con la cámara? Presionar para descartar."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Presiona para abrir el menú de la app"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Presiona para mostrar varias apps juntas"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Regresa a pantalla completa desde el menú de la app"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Aprovecha más"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Arrastra otra app para el modo de pantalla dividida"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Presiona dos veces fuera de una app para cambiar su ubicación"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Administrar ventanas"</string> <string name="close_text" msgid="4986518933445178928">"Cerrar"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Cerrar menú"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Abrir el menú"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizar pantalla"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ajustar pantalla"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"No se puede cambiar el tamaño de esta app"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"No se puede mover la app aquí"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximizar"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Ajustar a la izquierda"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Ajustar a la derecha"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml index 69f7d7b020d6..9f6b2e65c27c 100644 --- a/libs/WindowManager/Shell/res/values-es/strings.xml +++ b/libs/WindowManager/Shell/res/values-es/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"¿Problemas con la cámara?\nToca para reajustar"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"¿No se ha solucionado?\nToca para revertir"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"¿No hay problemas con la cámara? Toca para cerrar."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Toca para abrir el menú de aplicaciones"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Toca para mostrar varias aplicaciones a la vez"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Vuelve a pantalla completa desde el menú de aplicaciones"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Consulta más información y haz más"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Arrastra otra aplicación para activar la pantalla dividida"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toca dos veces fuera de una aplicación para cambiarla de posición"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Gestionar ventanas"</string> <string name="close_text" msgid="4986518933445178928">"Cerrar"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Cerrar menú"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Abrir menú"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizar pantalla"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ajustar pantalla"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"No se puede cambiar el tamaño de esta aplicación"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"La aplicación no se puede mover aquí"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximizar"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Acoplar a la izquierda"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Acoplar a la derecha"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml index 3d929f6cd8d3..b2b06d6db5d2 100644 --- a/libs/WindowManager/Shell/res/values-et/strings.xml +++ b/libs/WindowManager/Shell/res/values-et/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kas teil on kaameraprobleeme?\nPuudutage ümberpaigutamiseks."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Kas probleemi ei lahendatud?\nPuudutage ennistamiseks."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kas kaameraprobleeme pole? Puudutage loobumiseks."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Puudutage rakenduse menüü avamiseks"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Puudutage mitme rakenduse koos kuvamiseks"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Minge rakenduse menüüst tagasi täisekraanile"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Vaadake ja tehke rohkem"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Lohistage muusse rakendusse, et jagatud ekraanikuva kasutada"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Topeltpuudutage rakendusest väljaspool, et selle asendit muuta"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Akende haldamine"</string> <string name="close_text" msgid="4986518933445178928">"Sule"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Sule menüü"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Ava menüü"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Kuva täisekraanil"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Kuva poolel ekraanil"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Selle rakenduse aknasuurust ei saa muuta"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Rakendust ei saa siia teisaldada"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimeeri"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Tõmmake vasakule"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Tõmmake paremale"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml index 39bcf080fcf3..4a71c49b8d8a 100644 --- a/libs/WindowManager/Shell/res/values-eu/strings.xml +++ b/libs/WindowManager/Shell/res/values-eu/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Arazoak dauzkazu kamerarekin?\nBerriro doitzeko, sakatu hau."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ez al da konpondu?\nLeheneratzeko, sakatu hau."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ez daukazu arazorik kamerarekin? Baztertzeko, sakatu hau."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Sakatu hau aplikazioen menua irekitzeko"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Sakatu hau aplikazio bat baino gehiago aldi berean erakusteko"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Itzuli pantaila osora aplikazioen menutik"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Ikusi eta egin gauza gehiago"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Pantaila zatitua ikusteko, arrastatu beste aplikazio bat"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Aplikazioaren posizioa aldatzeko, sakatu birritan haren kanpoaldea"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Kudeatu leihoak"</string> <string name="close_text" msgid="4986518933445178928">"Itxi"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Itxi menua"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Ireki menua"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Handitu pantaila"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Zatitu pantaila"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Ezin zaio aldatu tamaina aplikazio honi"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikazioa ezin da hona ekarri"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximizatu"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Ezarri ezkerrean"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Ezarri eskuinean"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml index 9f607bf89656..941ff84b7799 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"دوربین مشکل دارد؟\nبرای تنظیم مجدد اندازه تکضرب بزنید"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"مشکل برطرف نشد؟\nبرای برگرداندن تکضرب بزنید"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"دوربین مشکلی ندارد؟ برای بستن تکضرب بزنید."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"برای باز کردن منو برنامه، تکضرب بزنید"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"برای نمایش چند برنامه با هم، تکضرب بزنید"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"از منو برنامه به تمامصفحه برگردید"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"از چندین برنامه بهطور همزمان استفاده کنید"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"برای حالت صفحهٔ دونیمه، در برنامهای دیگر بکشید"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"برای جابهجا کردن برنامه، بیرون از آن دو تکضرب بزنید"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"مدیریت کردن پنجرهها"</string> <string name="close_text" msgid="4986518933445178928">"بستن"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"بستن منو"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"باز کردن منو"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"بزرگ کردن صفحه"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"بزرگ کردن صفحه"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"اندازه این برنامه را نمیتوان تغییر داد"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"برنامه را نمیتوان به اینجا منتقل کرد"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"بزرگ کردن"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"کشیدن بهچپ"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"کشیدن بهراست"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml index 04b6241ca90b..a45e9afeabfc 100644 --- a/libs/WindowManager/Shell/res/values-fi/strings.xml +++ b/libs/WindowManager/Shell/res/values-fi/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Onko kameran kanssa ongelmia?\nKorjaa napauttamalla"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Eikö ongelma ratkennut?\nKumoa napauttamalla"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ei ongelmia kameran kanssa? Hylkää napauttamalla."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Avaa sovellusvalikko napauttamalla"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Näytä useita sovelluksia yhdessä napauttamalla"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Palaa koko näytön tilaan sovellusvalikosta"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Näe ja tee enemmän"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Käytä jaettua näyttöä vetämällä tähän toinen sovellus"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Kaksoisnapauta sovelluksen ulkopuolella, jos haluat siirtää sitä"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Hallinnoi ikkunoita"</string> <string name="close_text" msgid="4986518933445178928">"Sulje"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Sulje valikko"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Avaa valikko"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Suurenna näyttö"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Jaa näyttö"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Tämän sovellusikkunan kokoa ei voi muuttaa"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Sovellusta ei voi siirtää tänne"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Suurenna"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Siirrä vasemmalle"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Siirrä oikealle"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml index 73129525ebdd..c163165a8296 100644 --- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problèmes d\'appareil photo?\nTouchez pour réajuster"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problème non résolu?\nTouchez pour rétablir"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Aucun problème d\'appareil photo? Touchez pour ignorer."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Toucher ici pour ouvrir le menu de l\'appli"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Toucher ici pour afficher plusieurs applis ensemble"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Revenir au mode Plein écran à partir du menu de l\'appli"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Voir et en faire plus"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Faites glisser une autre appli pour utiliser l\'écran partagé"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Touchez deux fois à côté d\'une appli pour la repositionner"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Gérer les fenêtres"</string> <string name="close_text" msgid="4986518933445178928">"Fermer"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Fermer le menu"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Ouvrir le menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Agrandir l\'écran"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Aligner l\'écran"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Impossible de redimensionner cette appli"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Impossible de déplacer l\'appli ici"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Agrandir"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Épingler à gauche"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Épingler à droite"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml index 8f4e58f99a13..b2a6f16733b3 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problèmes d\'appareil photo ?\nAppuyez pour réajuster"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problème non résolu ?\nAppuyez pour rétablir"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Aucun problème d\'appareil photo ? Appuyez pour ignorer."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Appuyer pour ouvrir le menu de l\'appli"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Appuyer pour afficher plusieurs applis simultanément"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Revenir en plein écran depuis le menu de l\'appli"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Voir et interagir plus"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Faites glisser une autre appli pour utiliser l\'écran partagé"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Appuyez deux fois en dehors d\'une appli pour la repositionner"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Gérer les fenêtres"</string> <string name="close_text" msgid="4986518933445178928">"Fermer"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Fermer le menu"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Ouvrir le menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Mettre en plein écran"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Fractionner l\'écran"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Impossible de redimensionner cette appli"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Impossible de déplacer l\'appli ici"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Agrandir"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Ancrer à gauche"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Ancrer à droite"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml index 5c0aa074b329..ab972f94af22 100644 --- a/libs/WindowManager/Shell/res/values-gl/strings.xml +++ b/libs/WindowManager/Shell/res/values-gl/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Tes problemas coa cámara?\nToca para reaxustala"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Non se solucionaron os problemas?\nToca para reverter o seu tratamento"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Non hai problemas coa cámara? Tocar para ignorar."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Toca para abrir o menú da aplicación"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Toca para mostrar varias aplicacións xuntas"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Volve á pantalla completa desde o menú da aplicación"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Ver e facer máis"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Arrastra outra aplicación para usar a pantalla dividida"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toca dúas veces fóra da aplicación para cambiala de posición"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Xestionar as ventás"</string> <string name="close_text" msgid="4986518933445178928">"Pechar"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Pechar o menú"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Abrir o menú"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizar pantalla"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Encaixar pantalla"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Non se pode cambiar o tamaño desta aplicación"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Non se pode mover aquí a aplicación"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximizar"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Axustar á esquerda"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Axustar á dereita"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml index a382d0b41652..0dc2f73f1134 100644 --- a/libs/WindowManager/Shell/res/values-gu/strings.xml +++ b/libs/WindowManager/Shell/res/values-gu/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"કૅમેરામાં સમસ્યાઓ છે?\nફરીથી ફિટ કરવા માટે ટૅપ કરો"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"સુધારો નથી થયો?\nપહેલાંના પર પાછું ફેરવવા માટે ટૅપ કરો"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"કૅમેરામાં કોઈ સમસ્યા નથી? છોડી દેવા માટે ટૅપ કરો."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"ઍપ મેનૂ ખોલવા માટે ટૅપ કરો"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"એકથી વધુ ઍપ એકસાથે બતાવવા માટે ટૅપ કરો"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"ઍપ મેનૂમાંથી પૂર્ણસ્ક્રીન પર પાછા ફરો"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"જુઓ અને બીજું ઘણું કરો"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"વિભાજિત સ્ક્રીન માટે કોઈ અન્ય ઍપમાં ખેંચો"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"કોઈ ઍપની જગ્યા બદલવા માટે, તેની બહાર બે વાર ટૅપ કરો"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"વિન્ડો મેનેજ કરો"</string> <string name="close_text" msgid="4986518933445178928">"બંધ કરો"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"મેનૂ બંધ કરો"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"મેનૂ ખોલો"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"સ્ક્રીન કરો મોટી કરો"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"સ્ક્રીન સ્નૅપ કરો"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"આ ઍપના કદમાં વધઘટ કરી શકાતો નથી"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ઍપ અહીં ખસેડી શકાતી નથી"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"મોટું કરો"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ડાબે સ્નૅપ કરો"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"જમણે સ્નૅપ કરો"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml index 37608207b721..679d800a4dd2 100644 --- a/libs/WindowManager/Shell/res/values-hi/strings.xml +++ b/libs/WindowManager/Shell/res/values-hi/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"क्या कैमरे से जुड़ी कोई समस्या है?\nफिर से फ़िट करने के लिए टैप करें"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"क्या समस्या ठीक नहीं हुई?\nपहले जैसा करने के लिए टैप करें"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"क्या कैमरे से जुड़ी कोई समस्या नहीं है? खारिज करने के लिए टैप करें."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"ऐप्लिकेशन मेन्यू खोलने के लिए टैप करें"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"कई ऐप्लिकेशन एक साथ दिखाने के लिए टैप करें"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"ऐप्लिकेशन मेन्यू से फ़ुलस्क्रीन मोड पर वापस जाएं"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"पूरी जानकारी लेकर, बेहतर तरीके से काम करें"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"स्प्लिट स्क्रीन का इस्तेमाल करने के लिए, किसी अन्य ऐप्लिकेशन को खींचें और छोड़ें"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"किसी ऐप्लिकेशन की जगह बदलने के लिए, उसके बाहर दो बार टैप करें"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"मेन्यू खोलें"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"स्क्रीन को बड़ा करें"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"स्नैप स्क्रीन"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"इस ऐप्लिकेशन का साइज़ नहीं बदला जा सकता"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ऐप्लिकेशन को यहां मूव नहीं किया जा सकता"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"बड़ा करें"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"बाईं ओर स्नैप करें"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"दाईं ओर स्नैप करें"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml index f233c029c752..1e5ffc858b86 100644 --- a/libs/WindowManager/Shell/res/values-hr/strings.xml +++ b/libs/WindowManager/Shell/res/values-hr/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi s fotoaparatom?\nDodirnite za popravak"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problem nije riješen?\nDodirnite za vraćanje"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemate problema s fotoaparatom? Dodirnite za odbacivanje."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Dodirnite za otvaranje izbornika aplikacije"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Dodirnite za prikaz više aplikacija zajedno"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Vratite se na cijeli zaslon iz izbornika aplikacije"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Gledajte i učinite više"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Povucite drugu aplikaciju unutra da biste podijelili zaslon"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvaput dodirnite izvan aplikacije da biste je premjestili"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Upravljanje prozorima"</string> <string name="close_text" msgid="4986518933445178928">"Zatvorite"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite izbornik"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otvaranje izbornika"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimalno povećaj zaslon"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Izradi snimku zaslona"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Nije moguće promijeniti veličinu aplikacije"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikacija se ne može premjestiti ovdje"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimiziraj"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Poravnaj lijevo"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Poravnaj desno"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml index fb44cd855a7b..7c90a1924214 100644 --- a/libs/WindowManager/Shell/res/values-hu/strings.xml +++ b/libs/WindowManager/Shell/res/values-hu/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamerával kapcsolatos problémába ütközött?\nKoppintson a megoldáshoz."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nem sikerült a hiba kijavítása?\nKoppintson a visszaállításhoz."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nincsenek problémái kamerával? Koppintson az elvetéshez."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Koppintson az alkalmazásmenü megnyitásához"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Koppintson több alkalmazás együttes megjelenítéséhez"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"A teljes képernyőre az alkalmazásmenüben térhet vissza"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Több mindent láthat és tehet"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Húzzon ide egy másik alkalmazást az osztott képernyő használatához"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Koppintson duplán az alkalmazáson kívül az áthelyezéséhez"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Menü megnyitása"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Képernyő méretének maximalizálása"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Igazodás a képernyő adott részéhez"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Ezt az alkalmazást nem lehet átméretezni"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Az alkalmazás nem helyezhető át ide"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Teljes méret"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Balra igazítás"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Jobbra igazítás"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml index cd21faab45c2..e8ed4ac9c9a4 100644 --- a/libs/WindowManager/Shell/res/values-hy/strings.xml +++ b/libs/WindowManager/Shell/res/values-hy/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Տեսախցիկի հետ կապված խնդիրնե՞ր կան։\nՀպեք՝ վերակարգավորելու համար։"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Չհաջողվե՞ց շտկել։\nՀպեք՝ փոփոխությունները չեղարկելու համար։"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Տեսախցիկի հետ կապված խնդիրներ չկա՞ն։ Փակելու համար հպեք։"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Հպեք՝ հավելվածի ընտրացանկը բացելու համար"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Հպեք՝ էկրանին մի քանի հավելված միասին դիտելու համար"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Հավելվածի ընտրացանկից վերադառնալ լիաէկրան ռեժիմ"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Միաժամանակ կատարեք մի քանի առաջադրանք"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Քաշեք մյուս հավելվածի մեջ՝ էկրանի տրոհումն օգտագործելու համար"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Կրկնակի հպեք հավելվածի կողքին՝ այն տեղափոխելու համար"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Կառավարել պատուհանները"</string> <string name="close_text" msgid="4986518933445178928">"Փակել"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Փակել ընտրացանկը"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Բացել ընտրացանկը"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ծավալել էկրանը"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ծալել էկրանը"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Այս հավելվածի չափը հնարավոր չէ փոխել"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Հավելվածը հնարավոր չէ տեղափոխել այստեղ"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Ծավալել"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Ամրացնել ձախ կողմում"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Ամրացնել աջ կողմում"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml index ba0683deecd8..06b1634917e9 100644 --- a/libs/WindowManager/Shell/res/values-in/strings.xml +++ b/libs/WindowManager/Shell/res/values-in/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Masalah kamera?\nKetuk untuk memperbaiki"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Tidak dapat diperbaiki?\nKetuk untuk mengembalikan"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Tidak ada masalah kamera? Ketuk untuk menutup."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Ketuk untuk membuka menu aplikasi"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Ketuk untuk menampilkan beberapa aplikasi secara bersamaan"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Kembali ke layar penuh dari menu aplikasi"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Lihat dan lakukan lebih banyak hal"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Tarik aplikasi lain untuk menggunakan layar terpisah"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Ketuk dua kali di luar aplikasi untuk mengubah posisinya"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Kelola Jendela"</string> <string name="close_text" msgid="4986518933445178928">"Tutup"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Tutup Menu"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Buka Menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Perbesar Layar"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Gabungkan Layar"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Ukuran aplikasi ini tidak dapat diubah"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikasi tidak dapat dipindahkan ke sini"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimalkan"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Maksimalkan ke kiri"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Maksimalkan ke kanan"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml index b427eaf23290..2d447771de25 100644 --- a/libs/WindowManager/Shell/res/values-is/strings.xml +++ b/libs/WindowManager/Shell/res/values-is/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Myndavélavesen?\nÝttu til að breyta stærð"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ennþá vesen?\nÝttu til að afturkalla"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ekkert myndavélavesen? Ýttu til að hunsa."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Ýttu til að opna forritavalmyndina"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Ýttu til að sjá mörg forrit saman"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Opnaðu allan skjáinn aftur á forritavalmyndinni"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Sjáðu og gerðu meira"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Dragðu annað forrit inn til að nota skjáskiptingu"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Ýttu tvisvar utan við forrit til að færa það"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Stjórna gluggum"</string> <string name="close_text" msgid="4986518933445178928">"Loka"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Loka valmynd"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Opna valmynd"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Stækka skjá"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Smelluskjár"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Ekki er hægt að breyta stærð þessa forrits"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Ekki er hægt að færa forritið hingað"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Stækka"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Smella til vinstri"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Smella til hægri"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index 9eb9d4e3a403..b56424594f29 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi con la fotocamera?\nTocca per risolverli"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Il problema non si è risolto?\nTocca per ripristinare"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nessun problema con la fotocamera? Tocca per ignorare."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Tocca per aprire il menu dell\'app"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Tocca per mostrare più app insieme"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Torna allo schermo intero dal menu dell\'app"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Visualizza più contenuti e fai di più"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Trascina in un\'altra app per usare lo schermo diviso"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Tocca due volte fuori da un\'app per riposizionarla"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Gestisci finestre"</string> <string name="close_text" msgid="4986518933445178928">"Chiudi"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Chiudi il menu"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Apri il menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Massimizza schermo"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Aggancia schermo"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Non è possibile ridimensionare questa app"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Impossibile spostare l\'app qui"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Ingrandisci"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Aggancia a sinistra"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Aggancia a destra"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml index 3e82198201b9..fa072639f089 100644 --- a/libs/WindowManager/Shell/res/values-iw/strings.xml +++ b/libs/WindowManager/Shell/res/values-iw/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"בעיות במצלמה?\nאפשר להקיש כדי לבצע התאמה מחדש"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"הבעיה לא נפתרה?\nאפשר להקיש כדי לחזור לגרסה הקודמת"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"אין בעיות במצלמה? אפשר להקיש כדי לסגור."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"צריך להקיש כדי לפתוח את תפריט האפליקציה"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"אפשר להקיש כדי להציג כמה אפליקציות יחד"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"חזרה למסך מלא מתפריט האפליקציה"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"רוצה לראות ולעשות יותר?"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"צריך לגרור אפליקציה אחרת כדי להשתמש במסך המפוצל"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"צריך להקיש הקשה כפולה מחוץ לאפליקציה כדי למקם אותה מחדש"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"ניהול החלונות"</string> <string name="close_text" msgid="4986518933445178928">"סגירה"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"סגירת התפריט"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"פתיחת התפריט"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"הגדלת המסך"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"כיווץ המסך"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"לא ניתן לשנות את גודל החלון של האפליקציה הזו"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"לא ניתן להעביר את האפליקציה לכאן"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"הגדלה"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"הצמדה לשמאל"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"הצמדה לימין"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml index 1225b62c96d9..91667c00ce12 100644 --- a/libs/WindowManager/Shell/res/values-ja/strings.xml +++ b/libs/WindowManager/Shell/res/values-ja/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"カメラに関する問題の場合は、\nタップすると修正できます"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"修正されなかった場合は、\nタップすると元に戻ります"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"カメラに関する問題でない場合は、タップすると閉じます。"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"タップするとアプリメニューが開きます"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"タップすると複数のアプリが同時に表示されます"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"アプリメニューから全画面表示に戻ります"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"表示を拡大して機能を強化"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"分割画面にするにはもう 1 つのアプリをドラッグしてください"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"位置を変えるにはアプリの外側をダブルタップしてください"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"メニューを開く"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"画面の最大化"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"画面のスナップ"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"このアプリはサイズ変更できません"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"アプリはここに移動できません"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"最大化"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"左にスナップ"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"右にスナップ"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml index 3e1f726ca0ef..2208348485af 100644 --- a/libs/WindowManager/Shell/res/values-ka/strings.xml +++ b/libs/WindowManager/Shell/res/values-ka/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"კამერად პრობლემები აქვს?\nშეეხეთ გამოსასწორებლად"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"არ გამოსწორდა?\nშეეხეთ წინა ვერსიის დასაბრუნებლად"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"კამერას პრობლემები არ აქვს? შეეხეთ უარყოფისთვის."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"შეეხეთ აპის მენიუს გასახსნელად"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"შეეხეთ რამდენიმე აპის ერთად საჩვენებლად"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"სრულეკრანიან რეჟიმზე დაბრუნდით აპის მენიუდან"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"მეტის ნახვა და გაკეთება"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"ეკრანის გასაყოფად ჩავლებით გადაიტანეთ სხვა აპში"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ორმაგად შეეხეთ აპის გარშემო სივრცეს, რათა ის სხვაგან გადაიტანოთ"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"მენიუს გახსნა"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"აპლიკაციის გაშლა სრულ ეკრანზე"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"აპლიკაციის დაპატარავება ეკრანზე"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"აპის ზომის შეცვლა შეუძლებელია"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"აპის აქ გადატანა შეუძლებელია"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"მაქსიმალურად გაშლა"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"მარცხნივ გადატანა"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"მარჯვნივ გადატანა"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml index dd4e5c94fc27..416a84c86281 100644 --- a/libs/WindowManager/Shell/res/values-kk/strings.xml +++ b/libs/WindowManager/Shell/res/values-kk/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерада қателер шықты ма?\nЖөндеу үшін түртіңіз."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Жөнделмеді ме?\nҚайтару үшін түртіңіз."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерада қателер шықпады ма? Жабу үшін түртіңіз."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Қолданба мәзірін ашу үшін түртіңіз"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Бірнеше қолданбаны қатар көрсету үшін түртіңіз"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Қолданба мәзірінен толық экран режиміне қайту"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Қосымша ақпаратты қарап, әрекеттер жасау"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Экранды бөлу үшін басқа қолданбаға өтіңіз."</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Қолданбаның орнын өзгерту үшін одан тыс жерді екі рет түртіңіз."</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Терезелерді басқару"</string> <string name="close_text" msgid="4986518933445178928">"Жабу"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Мәзірді жабу"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Мәзірді ашу"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Экранды ұлғайту"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Экранды бөлу"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Бұл қолданбаның өлшемі өзгертілмейді."</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Қолданба бұл жерге қойылмайды."</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Жаю"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Солға тіркеу"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Оңға тіркеу"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml index 96fe62e4f034..b074d65700f4 100644 --- a/libs/WindowManager/Shell/res/values-km/strings.xml +++ b/libs/WindowManager/Shell/res/values-km/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"មានបញ្ហាពាក់ព័ន្ធនឹងកាមេរ៉ាឬ?\nចុចដើម្បីដោះស្រាយ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"មិនបានដោះស្រាយបញ្ហានេះទេឬ?\nចុចដើម្បីត្រឡប់"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"មិនមានបញ្ហាពាក់ព័ន្ធនឹងកាមេរ៉ាទេឬ? ចុចដើម្បីច្រានចោល។"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"ចុចដើម្បីបើកម៉ឺនុយកម្មវិធី"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"ចុចដើម្បីបង្ហាញកម្មវិធីច្រើនរួមគ្នា"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"ត្រឡប់ទៅអេក្រង់ពេញវិញពីម៉ឺនុយកម្មវិធី"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"មើលឃើញ និងធ្វើបានកាន់តែច្រើន"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"អូសកម្មវិធីមួយទៀតចូល ដើម្បីប្រើមុខងារបំបែកអេក្រង់"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ចុចពីរដងនៅក្រៅកម្មវិធី ដើម្បីប្ដូរទីតាំងកម្មវិធីនោះ"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"គ្រប់គ្រងវិនដូ"</string> <string name="close_text" msgid="4986518933445178928">"បិទ"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"បិទម៉ឺនុយ"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"បើកម៉ឺនុយ"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ពង្រីកអេក្រង់"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ថតអេក្រង់"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"មិនអាចប្ដូរទំហំកម្មវិធីនេះបានទេ"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"មិនអាចផ្លាស់ទីកម្មវិធីមកទីនេះបានទេ"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"ពង្រីក"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ផ្លាស់ទីទៅឆ្វេង"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ផ្លាស់ទីទៅស្ដាំ"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml index b38f74411db2..9c22241f5037 100644 --- a/libs/WindowManager/Shell/res/values-kn/strings.xml +++ b/libs/WindowManager/Shell/res/values-kn/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ಕ್ಯಾಮರಾ ಸಮಸ್ಯೆಗಳಿವೆಯೇ?\nಮರುಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ಅದನ್ನು ಸರಿಪಡಿಸಲಿಲ್ಲವೇ?\nಹಿಂತಿರುಗಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ಕ್ಯಾಮರಾ ಸಮಸ್ಯೆಗಳಿಲ್ಲವೇ? ವಜಾಗೊಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"ಆ್ಯಪ್ ಮೆನುವನ್ನು ತೆರೆಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"ಅನೇಕ ಆ್ಯಪ್ಗಳನ್ನು ಒಟ್ಟಿಗೆ ತೋರಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"ಆ್ಯಪ್ ಮೆನುವಿನಿಂದ ಫುಲ್ಸ್ಕ್ರೀನ್ಗೆ ಹಿಂತಿರುಗಿ"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ನೋಡಿ ಮತ್ತು ಹೆಚ್ಚಿನದನ್ನು ಮಾಡಿ"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ಗಾಗಿ ಮತ್ತೊಂದು ಆ್ಯಪ್ನಲ್ಲಿ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ಆ್ಯಪ್ ಒಂದರ ಸ್ಥಾನವನ್ನು ಬದಲಾಯಿಸಲು ಅದರ ಹೊರಗೆ ಡಬಲ್-ಟ್ಯಾಪ್ ಮಾಡಿ"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"ವಿಂಡೋಗಳನ್ನು ನಿರ್ವಹಿಸಿ"</string> <string name="close_text" msgid="4986518933445178928">"ಮುಚ್ಚಿ"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"ಮೆನು ಮುಚ್ಚಿ"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"ಮೆನು ತೆರೆಯಿರಿ"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ಸ್ಕ್ರೀನ್ ಅನ್ನು ಮ್ಯಾಕ್ಸಿಮೈಸ್ ಮಾಡಿ"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ಸ್ನ್ಯಾಪ್ ಸ್ಕ್ರೀನ್"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ಆ್ಯಪ್ ಅನ್ನು ಇಲ್ಲಿಗೆ ಸರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"ಮ್ಯಾಕ್ಸಿಮೈಸ್ ಮಾಡಿ"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ಎಡಕ್ಕೆ ಸ್ನ್ಯಾಪ್ ಮಾಡಿ"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ಬಲಕ್ಕೆ ಸ್ನ್ಯಾಪ್ ಮಾಡಿ"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml index 421d4666911e..58dd6f8e7e99 100644 --- a/libs/WindowManager/Shell/res/values-ko/strings.xml +++ b/libs/WindowManager/Shell/res/values-ko/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"카메라 문제가 있나요?\n해결하려면 탭하세요."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"해결되지 않았나요?\n되돌리려면 탭하세요."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"카메라에 문제가 없나요? 닫으려면 탭하세요."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"탭하여 앱 메뉴 열기"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"탭하여 여러 앱을 함께 표시하기"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"앱 메뉴에서 전체 화면으로 돌아가기"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"더 많은 정보를 보고 더 많은 작업을 처리하세요"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"화면 분할을 사용하려면 다른 앱을 드래그해 가져옵니다."</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"앱 위치를 조정하려면 앱 외부를 두 번 탭합니다."</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"창 관리"</string> <string name="close_text" msgid="4986518933445178928">"닫기"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"메뉴 닫기"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"메뉴 열기"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"화면 최대화"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"화면 분할"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"이 앱은 크기를 조절할 수 없습니다."</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"앱을 여기로 이동할 수 없음"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"최대화하기"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"왼쪽으로 맞추기"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"오른쪽으로 맞추기"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml index abafd7ac0330..75feedea1b89 100644 --- a/libs/WindowManager/Shell/res/values-ky/strings.xml +++ b/libs/WindowManager/Shell/res/values-ky/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерада маселелер келип чыктыбы?\nОңдоо үчүн таптаңыз"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Оңдолгон жокпу?\nАртка кайтаруу үчүн таптаңыз"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерада маселе жокпу? Этибарга албоо үчүн таптаңыз."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Колдонмонун менюсун ачуу үчүн таптап коюңуз"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Бир нече колдонмону чогуу көрүү үчүн таптап коюңуз"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Колдонмонун менюсунан толук экранга кайтыңыз"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Көрүп, көбүрөөк нерселерди жасаңыз"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Экранды бөлүү үчүн башка колдонмону сүйрөңүз"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Колдонмону жылдыруу үчүн сырт жагын эки жолу таптаңыз"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Терезелерди тескөө"</string> <string name="close_text" msgid="4986518933445178928">"Жабуу"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Менюну жабуу"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Менюну ачуу"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Экранды чоңойтуу"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Экранды сүрөткө тартып алуу"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Бул колдонмонун өлчөмүн өзгөртүүгө болбойт"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Колдонмону бул жерге жылдырууга болбойт"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Чоңойтуу"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Солго жылдыруу"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Оңго жылдыруу"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml index 4e10621c719b..8f28504b41b4 100644 --- a/libs/WindowManager/Shell/res/values-lo/strings.xml +++ b/libs/WindowManager/Shell/res/values-lo/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ມີບັນຫາກ້ອງຖ່າຍຮູບບໍ?\nແຕະເພື່ອປັບໃໝ່"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ບໍ່ໄດ້ແກ້ໄຂມັນບໍ?\nແຕະເພື່ອແປງກັບຄືນ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ບໍ່ມີບັນຫາກ້ອງຖ່າຍຮູບບໍ? ແຕະເພື່ອປິດໄວ້."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"ແຕະເພື່ອເປີດເມນູແອັບ"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"ແຕະເພື່ອສະແດງແອັບຫຼາຍລາຍການພ້ອມກັນ"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"ກັບຄືນໄປຫາໂໝດເຕັມຈໍຈາກເມນູແອັບ"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ເບິ່ງ ແລະ ເຮັດຫຼາຍຂຶ້ນ"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"ລາກໄປໄວ້ໃນແອັບອື່ນເພື່ອແບ່ງໜ້າຈໍ"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ແຕະສອງເທື່ອໃສ່ນອກແອັບໃດໜຶ່ງເພື່ອຈັດຕຳແໜ່ງຂອງມັນຄືນໃໝ່"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"ເປີດເມນູ"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ປັບຈໍໃຫຍ່ສຸດ"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ສະແນັບໜ້າຈໍ"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"ບໍ່ສາມາດປັບຂະໜາດແອັບນີ້ໄດ້"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ບໍ່ສາມາດຍ້າຍແອັບມາບ່ອນນີ້ໄດ້"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"ຂະຫຍາຍໃຫຍ່ສຸດ"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ແນບຊ້າຍ"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ແນບຂວາ"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml index 6d3c58cf01bb..b97b8787ed10 100644 --- a/libs/WindowManager/Shell/res/values-lt/strings.xml +++ b/libs/WindowManager/Shell/res/values-lt/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Iškilo problemų dėl kameros?\nPalieskite, kad pritaikytumėte iš naujo"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nepavyko pataisyti?\nPalieskite, kad grąžintumėte"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nėra jokių problemų dėl kameros? Palieskite, kad atsisakytumėte."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Palieskite, kad atidarytumėte programos meniu"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Palieskite, kad būtų rodomos kelios programos kartu"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Grįžkite į viso ekrano režimą iš programos meniu"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Daugiau turinio ir funkcijų"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Vilkite kitoje programoje, kad galėtumėte naudoti išskaidyto ekrano režimą"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dukart palieskite už programos ribų, kad pakeistumėte jos poziciją"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Atidaryti meniu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Išskleisti ekraną"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Sutraukti ekraną"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Negalima keisti šios programos dydžio"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Programos negalima perkelti čia"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Padidinti"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Pritraukti kairėje"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Pritraukti dešinėje"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml index 2f235babd721..de200d816e7a 100644 --- a/libs/WindowManager/Shell/res/values-lv/strings.xml +++ b/libs/WindowManager/Shell/res/values-lv/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Vai ir problēmas ar kameru?\nPieskarieties, lai tās novērstu."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Vai problēma netika novērsta?\nPieskarieties, lai atjaunotu."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Vai nav problēmu ar kameru? Pieskarieties, lai nerādītu."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Lai atvērtu lietotnes izvēlni, pieskarieties."</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Lai parādītu vairākas lietotnes kopā, pieskarieties."</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Varat atgriezties pilnekrāna režīmā no lietotnes izvēlnes."</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Uzziniet un paveiciet vairāk"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Lai izmantotu sadalītu ekrānu, ievelciet vēl vienu lietotni"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Lai pārvietotu lietotni, veiciet dubultskārienu ārpus lietotnes"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Pārvaldīt logus"</string> <string name="close_text" msgid="4986518933445178928">"Aizvērt"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Aizvērt izvēlni"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Atvērt izvēlni"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimizēt ekrānu"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Fiksēt ekrānu"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Šīs lietotnes loga lielumu nevar mainīt."</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Lietotni nevar pārvietot šeit."</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimizēt"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Piestiprināt pa kreisi"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Piestiprināt pa labi"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml index e58d8fc945f4..4922d042c6ac 100644 --- a/libs/WindowManager/Shell/res/values-mk/strings.xml +++ b/libs/WindowManager/Shell/res/values-mk/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблеми со камерата?\nДопрете за да се совпадне повторно"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не се поправи?\nДопрете за враќање"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нема проблеми со камерата? Допрете за отфрлање."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Допрете за да го отворите менито со апликации"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Допрете за да се прикажат повеќе апликации заедно"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Вратете се на цел екран од менито со апликации"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Погледнете и направете повеќе"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Повлечете друга апликација за поделен екран"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Допрете двапати надвор од некоја апликација за да ја преместите"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Управувајте со прозорци"</string> <string name="close_text" msgid="4986518933445178928">"Затворете"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Затворете го менито"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Отвори го менито"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Максимизирај го екранот"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Подели го екранот на половина"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Не може да се промени големината на апликацијава"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Апликацијата не може да се премести овде"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Максимизирај"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Фотографирај лево"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Фотографирај десно"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml index a48df0b71b1b..61277d6765fd 100644 --- a/libs/WindowManager/Shell/res/values-ml/strings.xml +++ b/libs/WindowManager/Shell/res/values-ml/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ക്യാമറ പ്രശ്നങ്ങളുണ്ടോ?\nശരിയാക്കാൻ ടാപ്പ് ചെയ്യുക"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"അത് പരിഹരിച്ചില്ലേ?\nപുനഃസ്ഥാപിക്കാൻ ടാപ്പ് ചെയ്യുക"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ക്യാമറാ പ്രശ്നങ്ങളൊന്നുമില്ലേ? നിരസിക്കാൻ ടാപ്പ് ചെയ്യുക."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"ആപ്പ് മെനു തുറക്കാൻ ടാപ്പ് ചെയ്യുക"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"ഒന്നിലധികം ആപ്പുകൾ ഒരുമിച്ച് കാണിക്കാൻ ടാപ്പ് ചെയ്യുക"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"ആപ്പ് മെനുവിൽ നിന്ന് പൂർണ്ണസ്ക്രീനിലേക്ക് മടങ്ങുക"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"കൂടുതൽ കാണുക, ചെയ്യുക"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"സ്ക്രീൻ വിഭജന മോഡിന്, മറ്റൊരു ആപ്പ് വലിച്ചിടുക"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ആപ്പിന്റെ സ്ഥാനം മാറ്റാൻ അതിന് പുറത്ത് ഡബിൾ ടാപ്പ് ചെയ്യുക"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"മെനു തുറക്കുക"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"സ്ക്രീൻ വലുതാക്കുക"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"സ്ക്രീൻ സ്നാപ്പ് ചെയ്യുക"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"ഈ ആപ്പിന്റെ വലുപ്പം മാറ്റാനാകില്ല"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ആപ്പ് ഇവിടേക്ക് നീക്കാനാകില്ല"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"വലുതാക്കുക"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ഇടതുവശത്തേക്ക് സ്നാപ്പ് ചെയ്യുക"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"വലതുവശത്തേക്ക് സ്നാപ്പ് ചെയ്യുക"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml index f7e6a6c87890..2b313a2be17c 100644 --- a/libs/WindowManager/Shell/res/values-mn/strings.xml +++ b/libs/WindowManager/Shell/res/values-mn/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерын асуудал гарсан уу?\nДахин тааруулахын тулд товшино уу"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Үүнийг засаагүй юу?\nБуцаахын тулд товшино уу"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерын асуудал байхгүй юу? Хаахын тулд товшино уу."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Аппын цэсийг нээхийн тулд товшино уу"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Олон аппыг хамтад нь харуулахын товшино уу"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Аппын цэсээс бүтэн дэлгэц рүү буцна уу"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Харж илүү ихийг хий"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Дэлгэц хуваах горимд ашиглахын тулд өөр аппыг чирнэ үү"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Аппыг дахин байрлуулахын тулд гадна талд нь хоёр товшино"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Windows-г удирдах"</string> <string name="close_text" msgid="4986518933445178928">"Хаах"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Цэсийг хаах"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Цэсийг нээх"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Дэлгэцийг томруулах"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Дэлгэцийг таллах"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Энэ аппын хэмжээг өөрчлөх боломжгүй"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Аппыг ийш зөөх боломжгүй"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Томруулах"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Зүүн тийш зэрэгцүүлэх"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Баруун тийш зэрэгцүүлэх"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml index 483228424d44..9778dcd0a166 100644 --- a/libs/WindowManager/Shell/res/values-mr/strings.xml +++ b/libs/WindowManager/Shell/res/values-mr/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"कॅमेराशी संबंधित काही समस्या आहेत का?\nपुन्हा फिट करण्यासाठी टॅप करा"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"निराकरण झाले नाही?\nरिव्हर्ट करण्यासाठी कृपया टॅप करा"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"कॅमेराशी संबंधित कोणत्याही समस्या नाहीत का? डिसमिस करण्यासाठी टॅप करा."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"अॅप मेनू उघडण्यासाठी टॅप करा"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"एकाहून अधिक ॲप्स एकत्र दाखवण्यासाठी टॅप करा"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"ॲप मेनूमधून फुलस्क्रीनवर परत या"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"पहा आणि आणखी बरेच काही करा"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"स्प्लिट स्क्रीन वापरण्यासाठी दुसरे ॲप ड्रॅग करा"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ॲपची स्थिती पुन्हा बदलण्यासाठी, त्याच्या बाहेर दोनदा टॅप करा"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"विंडो व्यवस्थापित करा"</string> <string name="close_text" msgid="4986518933445178928">"बंद करा"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"मेनू बंद करा"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"मेनू उघडा"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"स्क्रीन मोठी करा"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"स्क्रीन स्नॅप करा"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"या अॅपचा आकार बदलला जाऊ शकत नाही"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"अॅप इथे हलवू शकत नाही"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"मोठे करा"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"डावीकडे स्नॅप करा"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"उजवीकडे स्नॅप करा"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml index 15ccfbbad39f..0ee439657e2a 100644 --- a/libs/WindowManager/Shell/res/values-ms/strings.xml +++ b/libs/WindowManager/Shell/res/values-ms/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Isu kamera?\nKetik untuk memuatkan semula"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Isu tidak dibetulkan?\nKetik untuk kembali"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Tiada isu kamera? Ketik untuk mengetepikan."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Ketik untuk membuka menu apl"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Ketik untuk memaparkan berbilang apl serentak"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Kembali kepada skrin penuh daripada menu apl"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Lihat dan lakukan lebih"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Seret masuk apl lain untuk menggunakan skrin pisah"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Ketik dua kali di luar apl untuk menempatkan semula apl itu"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Buka Menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimumkan Skrin"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Tangkap Skrin"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Apl ini tidak boleh diubah saiz"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Apl tidak boleh dialihkan ke sini"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimumkan"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Autojajar ke kiri"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Autojajar ke kanan"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml index aac6f8420d7a..57d09500b3bf 100644 --- a/libs/WindowManager/Shell/res/values-my/strings.xml +++ b/libs/WindowManager/Shell/res/values-my/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ကင်မရာပြဿနာလား။\nပြင်ဆင်ရန် တို့ပါ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ကောင်းမသွားဘူးလား။\nပြန်ပြောင်းရန် တို့ပါ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ကင်မရာပြဿနာ မရှိဘူးလား။ ပယ်ရန် တို့ပါ။"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"အက်ပ်မီနူးကိုဖွင့်ရန် တို့ပါ"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"အက်ပ်များစွာကို အတူတကွပြရန် တို့ပါ"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"အက်ပ်မီနူးမှ ဖန်သားပြင်အပြည့်သို့ ပြန်သွားပါ"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ကြည့်ပြီး ပိုမိုလုပ်ဆောင်ပါ"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"မျက်နှာပြင် ခွဲ၍ပြသခြင်းအတွက် အက်ပ်နောက်တစ်ခုကို ဖိဆွဲပါ"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"နေရာပြန်ချရန် အက်ပ်အပြင်ဘက်ကို နှစ်ချက်တို့ပါ"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"ဝင်းဒိုးများ စီမံရန်"</string> <string name="close_text" msgid="4986518933445178928">"ပိတ်ရန်"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"မီနူး ပိတ်ရန်"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"မီနူး ဖွင့်ရန်"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"စခရင်ကို ချဲ့မည်"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"စခရင်ကို ချုံ့မည်"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"ဤအက်ပ်ကို အရွယ်ပြင်၍ မရပါ"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"အက်ပ်ကို ဤနေရာသို့ ရွှေ့၍မရပါ"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"ချဲ့ရန်"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ဘယ်တွင် ချဲ့ရန်"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ညာတွင် ချဲ့ရန်"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml index 175133d1744a..eb505ec43a65 100644 --- a/libs/WindowManager/Shell/res/values-nb/strings.xml +++ b/libs/WindowManager/Shell/res/values-nb/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Har du kameraproblemer?\nTrykk for å tilpasse"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ble ikke problemet løst?\nTrykk for å gå tilbake"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Har du ingen kameraproblemer? Trykk for å lukke."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Trykk for å åpne appmenyen"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Trykk for å vise flere apper sammen"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Gå tilbake til fullskjerm fra appmenyen"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Se og gjør mer"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Dra inn en annen app for å bruke delt skjerm"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dobbelttrykk utenfor en app for å flytte den"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Administrer vinduene"</string> <string name="close_text" msgid="4986518933445178928">"Lukk"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Lukk menyen"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Åpne menyen"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimer skjermen"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Fest skjermen"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Du kan ikke endre størrelse på denne appen"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Appen kan ikke flyttes hit"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimer"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Fest til venstre"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Fest til høyre"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml index d3a7e12c0df4..47d66d5deec8 100644 --- a/libs/WindowManager/Shell/res/values-ne/strings.xml +++ b/libs/WindowManager/Shell/res/values-ne/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"क्यामेरासम्बन्धी समस्या देखियो?\nसमस्या हल गर्न ट्याप गर्नुहोस्"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"समस्या हल भएन?\nपहिलेको जस्तै बनाउन ट्याप गर्नुहोस्"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"क्यामेरासम्बन्धी कुनै पनि समस्या छैन? खारेज गर्न ट्याप गर्नुहोस्।"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"एपको मेनु खोल्न ट्याप गर्नुहोस्"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"एकभन्दा बढी एपहरू सँगै देखाउन ट्याप गर्नुहोस्"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"एपको मेनुबाट फुल स्क्रिनमा फर्कनुहोस्"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"थप कुरा हेर्नुहोस् र गर्नुहोस्"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"स्प्लिट स्क्रिन मोड प्रयोग गर्न अर्को एप ड्रयाग एन्ड ड्रप गर्नुहोस्"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"तपाईं जुन एपको स्थिति मिलाउन चाहनुहुन्छ सोही एपको बाहिर डबल ट्याप गर्नुहोस्"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"विन्डोहरू व्यवस्थापन गर्नुहोस्"</string> <string name="close_text" msgid="4986518933445178928">"बन्द गर्नुहोस्"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"मेनु बन्द गर्नुहोस्"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"मेनु खोल्नुहोस्"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"स्क्रिन ठुलो बनाउनुहोस्"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"स्क्रिन स्न्याप गर्नुहोस्"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"यो एपको आकार बदल्न मिल्दैन"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"एप सारेर यहाँ ल्याउन सकिएन"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"ठुलो बनाउनुहोस्"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"बायाँतिर स्न्याप गर्नुहोस्"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"दायाँतिर स्न्याप गर्नुहोस्"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml index 747afe3eb034..e3e344124e0b 100644 --- a/libs/WindowManager/Shell/res/values-nl/strings.xml +++ b/libs/WindowManager/Shell/res/values-nl/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Cameraproblemen?\nTik om opnieuw passend te maken."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Is dit geen oplossing?\nTik om terug te zetten."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Geen cameraproblemen? Tik om te sluiten."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Tik om het app-menu te openen"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Tik om meerdere apps tegelijk te tonen"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Terug naar volledig scherm vanuit het app-menu"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Zie en doe meer"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Sleep een andere app hier naartoe om het scherm te splitsen"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dubbeltik naast een app om deze opnieuw te positioneren"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Vensters beheren"</string> <string name="close_text" msgid="4986518933445178928">"Sluiten"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Menu sluiten"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Menu openen"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Scherm maximaliseren"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Scherm halveren"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Het formaat van deze app kan niet worden aangepast"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Kan de app niet hierheen verplaatsen"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximaliseren"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Links uitlijnen"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Rechts uitlijnen"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml index a5adcbe36db1..baf009e8f28c 100644 --- a/libs/WindowManager/Shell/res/values-or/strings.xml +++ b/libs/WindowManager/Shell/res/values-or/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"କ୍ୟାମେରାରେ ସମସ୍ୟା ଅଛି?\nପୁଣି ଫିଟ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ଏହାର ସମାଧାନ ହୋଇନାହିଁ?\nଫେରିଯିବା ପାଇଁ ଟାପ କରନ୍ତୁ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"କ୍ୟାମେରାରେ କିଛି ସମସ୍ୟା ନାହିଁ? ଖାରଜ କରିବାକୁ ଟାପ କରନ୍ତୁ।"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"ଆପ ମେନୁ ଖୋଲିବାକୁ ଟାପ କରନ୍ତୁ"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"ଏକାଠି ଏକାଧିକ ଆପ୍ସ ଦେଖାଇବା ପାଇଁ ଟାପ କରନ୍ତୁ"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"ଆପ ମେନୁରୁ ପୂର୍ଣ୍ଣସ୍କ୍ରିନକୁ ଫେରନ୍ତୁ"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ଦେଖନ୍ତୁ ଏବଂ ଆହୁରି ଅନେକ କିଛି କରନ୍ତୁ"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ପାଇଁ ଅନ୍ୟ ଏକ ଆପକୁ ଡ୍ରାଗ କରନ୍ତୁ"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ଏକ ଆପକୁ ରିପୋଜିସନ କରିବା ପାଇଁ ଏହାର ବାହାରେ ଦୁଇଥର-ଟାପ କରନ୍ତୁ"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"ୱିଣ୍ଡୋଗୁଡ଼ିକୁ ପରିଚାଳନା କରନ୍ତୁ"</string> <string name="close_text" msgid="4986518933445178928">"ବନ୍ଦ କରନ୍ତୁ"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"ମେନୁ ବନ୍ଦ କରନ୍ତୁ"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"ମେନୁ ଖୋଲନ୍ତୁ"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ସ୍କ୍ରିନକୁ ବଡ଼ କରନ୍ତୁ"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ସ୍କ୍ରିନକୁ ସ୍ନାପ କରନ୍ତୁ"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"ଏହି ଆପକୁ ରିସାଇଜ କରାଯାଇପାରିବ ନାହିଁ"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ଆପକୁ ଏଠାକୁ ମୁଭ କରାଯାଇପାରିବ ନାହିଁ"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"ବଡ଼ କରନ୍ତୁ"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ବାମରେ ସ୍ନାପ କରନ୍ତୁ"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ଡାହାଣରେ ସ୍ନାପ କରନ୍ତୁ"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml index e11cc1c1f76d..2c29c7f80411 100644 --- a/libs/WindowManager/Shell/res/values-pa/strings.xml +++ b/libs/WindowManager/Shell/res/values-pa/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ਕੀ ਕੈਮਰੇ ਸੰਬੰਧੀ ਸਮੱਸਿਆਵਾਂ ਹਨ?\nਮੁੜ-ਫਿੱਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ਕੀ ਇਹ ਠੀਕ ਨਹੀਂ ਹੋਈ?\nਵਾਪਸ ਉਹੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ਕੀ ਕੈਮਰੇ ਸੰਬੰਧੀ ਕੋਈ ਸਮੱਸਿਆ ਨਹੀਂ ਹੈ? ਖਾਰਜ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"ਐਪ ਮੀਨੂ ਨੂੰ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"ਕਈ ਐਪਾਂ ਇਕੱਠੀਆਂ ਦਿਖਾਉਣ ਲਈ ਟੈਪ ਕਰੋ"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"ਐਪ ਮੀਨੂ ਤੋਂ ਪੂਰੀ-ਸਕ੍ਰੀਨ ਮੋਡ \'ਤੇ ਵਾਪਸ ਜਾਓ"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ਦੇਖੋ ਅਤੇ ਹੋਰ ਬਹੁਤ ਕੁਝ ਕਰੋ"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੇ ਲਈ ਕਿਸੇ ਹੋਰ ਐਪ ਵਿੱਚ ਘਸੀਟੋ"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ਕਿਸੇ ਐਪ ਦੀ ਜਗ੍ਹਾ ਬਦਲਣ ਲਈ ਉਸ ਦੇ ਬਾਹਰ ਡਬਲ ਟੈਪ ਕਰੋ"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"ਮੀਨੂ ਖੋਲ੍ਹੋ"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ਸਕ੍ਰੀਨ ਦਾ ਆਕਾਰ ਵਧਾਓ"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ਸਕ੍ਰੀਨ ਨੂੰ ਸਨੈਪ ਕਰੋ"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"ਇਸ ਐਪ ਦਾ ਆਕਾਰ ਬਦਲਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ਐਪ ਨੂੰ ਇੱਥੇ ਨਹੀਂ ਲਿਜਾਇਆ ਜਾ ਸਕਦਾ"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"ਵੱਡਾ ਕਰੋ"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ਖੱਬੇ ਪਾਸੇ ਸਨੈਪ ਕਰੋ"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"ਸੱਜੇ ਪਾਸੇ ਸਨੈਪ ਕਰੋ"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml index 2640c0f368a8..1e7b18117812 100644 --- a/libs/WindowManager/Shell/res/values-pl/strings.xml +++ b/libs/WindowManager/Shell/res/values-pl/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemy z aparatem?\nKliknij, aby dopasować"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Naprawa się nie udała?\nKliknij, aby cofnąć"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Brak problemów z aparatem? Kliknij, aby zamknąć"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Kliknij, aby otworzyć menu aplikacji"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Kliknij, aby wyświetlić jednocześnie kilka aplikacji"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Wróć do trybu pełnoekranowego z menu aplikacji"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Zobacz i zrób więcej"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Aby podzielić ekran, przeciągnij drugą aplikację"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Kliknij dwukrotnie poza aplikacją, aby ją przenieść"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otwórz menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksymalizuj ekran"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Przyciągnij ekran"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Nie można zmienić rozmiaru tej aplikacji"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Nie można przenieść aplikacji tutaj"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksymalizuj"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Przyciągnij do lewej"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Przyciągnij do prawej"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml index 18048ff045b5..7d728a03b4ec 100644 --- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml @@ -97,12 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmera?\nToque para ajustar o enquadramento"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"O problema não foi corrigido?\nToque para reverter"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Não tem problemas com a câmera? Toque para dispensar."</string> - <!-- no translation found for windowing_app_handle_education_tooltip (6398482412956375783) --> - <skip /> - <!-- no translation found for windowing_desktop_mode_image_button_education_tooltip (6285279585554484957) --> - <skip /> - <!-- no translation found for windowing_desktop_mode_exit_education_tooltip (6685429075790085337) --> - <skip /> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Toque para abrir o menu do app"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Toque para mostrar vários apps juntos"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Volte para a tela cheia no menu do app"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Veja e faça mais"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Arraste outro app para dividir a tela"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toque duas vezes fora de um app para reposicionar"</string> @@ -135,9 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Abrir o menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ampliar tela"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ajustar tela"</string> - <!-- no translation found for desktop_mode_non_resizable_snap_text (3771776422751387878) --> - <skip /> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Não é possível mover o app para cá"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximizar"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Ajustar à esquerda"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Ajustar à direita"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml index 46f8b38dd621..752fd6fb8970 100644 --- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmara?\nToque aqui para reajustar"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Não foi corrigido?\nToque para reverter"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nenhum problema com a câmara? Toque para ignorar."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Toque para abrir o menu de apps"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Toque para mostrar várias apps em conjunto"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Regresse ao ecrã inteiro a partir do menu de apps"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Veja e faça mais"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Arraste outra app para usar o ecrã dividido"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toque duas vezes fora de uma app para a reposicionar"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Abrir menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizar ecrã"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Encaixar ecrã"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Não é possível redimensionar esta app"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Não é possível mover a app para aqui"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximizar"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Encaixar à esquerda"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Encaixar à direita"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml index 75c445c6f35c..7d728a03b4ec 100644 --- a/libs/WindowManager/Shell/res/values-pt/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmera?\nToque para ajustar o enquadramento"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"O problema não foi corrigido?\nToque para reverter"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Não tem problemas com a câmera? Toque para dispensar."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Toque para abrir o menu do app"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Toque para mostrar vários apps juntos"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Volte para a tela cheia no menu do app"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Veja e faça mais"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Arraste outro app para dividir a tela"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toque duas vezes fora de um app para reposicionar"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Gerenciar janelas"</string> <string name="close_text" msgid="4986518933445178928">"Fechar"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Abrir o menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ampliar tela"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ajustar tela"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Não é possível redimensionar o app"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Não é possível mover o app para cá"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximizar"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Ajustar à esquerda"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Ajustar à direita"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml index 3c763ea8a6a4..3985d9bc792a 100644 --- a/libs/WindowManager/Shell/res/values-ro/strings.xml +++ b/libs/WindowManager/Shell/res/values-ro/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Ai probleme cu camera foto?\nAtinge pentru a reîncadra"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nu ai remediat problema?\nAtinge pentru a reveni"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nu ai probleme cu camera foto? Atinge pentru a închide."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Atinge pentru a deschide meniul aplicației"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Atinge pentru a afișa mai multe aplicații împreună"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Revino la ecranul complet din meniul aplicației"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Vezi și fă mai multe"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Trage în altă aplicație pentru a folosi ecranul împărțit"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Atinge de două ori lângă o aplicație pentru a o repoziționa"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Gestionează ferestrele"</string> <string name="close_text" msgid="4986518933445178928">"Închide"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Închide meniul"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Deschide meniul"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximizează fereastra"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Micșorează fereastra și fixeaz-o"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Aplicația nu poate fi redimensionată"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplicația nu poate fi mutată aici"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximizează"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Trage la stânga"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Trage la dreapta"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml index affd0cb0853a..58a196b4eecb 100644 --- a/libs/WindowManager/Shell/res/values-ru/strings.xml +++ b/libs/WindowManager/Shell/res/values-ru/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблемы с камерой?\nНажмите, чтобы исправить."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не помогло?\nНажмите, чтобы отменить изменения."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нет проблем с камерой? Нажмите, чтобы закрыть."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Нажмите, чтобы открыть меню приложения"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Нажмите, чтобы на экране размещались сразу несколько приложений"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Вернуться из меню приложения в режим полного экрана"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Выполняйте несколько задач одновременно"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Перетащите сюда другое приложение, чтобы использовать разделение экрана."</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Чтобы переместить приложение, дважды нажмите рядом с ним."</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Открыть меню"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Развернуть на весь экран"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Свернуть"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Изменить размер приложения нельзя."</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Приложение нельзя сюда переместить"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Развернуть"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Привязать слева"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Привязать справа"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml index ed762699bc49..6682b017f2cc 100644 --- a/libs/WindowManager/Shell/res/values-si/strings.xml +++ b/libs/WindowManager/Shell/res/values-si/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"කැමරා ගැටලුද?\nයළි සවි කිරීමට තට්ටු කරන්න"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"එය විසඳුවේ නැතිද?\nප්රතිවර්තනය කිරීමට තට්ටු කරන්න"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"කැමරා ගැටලු නොමැතිද? ඉවත දැමීමට තට්ටු කරන්න"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"යෙදුම් මෙනුව විවෘත කිරීමට තට්ටු කරන්න"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"යෙදුම් කිහිපයක් එකට පෙන්වීමට තට්ටු කරන්න"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"යෙදුම් මෙනුවෙන් පූර්ණ තිරය වෙත ආපසු යන්න"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"බලන්න සහ තවත් දේ කරන්න"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"බෙදුම් තිරය සඳහා වෙනත් යෙදුමකට අදින්න"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"යෙදුමක් නැවත ස්ථානගත කිරීමට පිටතින් දෙවරක් තට්ටු කරන්න"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"කවුළු කළමනාකරණය කරන්න"</string> <string name="close_text" msgid="4986518933445178928">"වසන්න"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"මෙනුව වසන්න"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"මෙනුව විවෘත කරන්න"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"තිරය උපරිම කරන්න"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"ස්නැප් තිරය"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"මෙම යෙදුම ප්රතිප්රමාණ කළ නොහැක"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"යෙදුම මෙතැනට ගෙන යා නොහැක"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"විහිදන්න"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"වමට ස්නැප් කරන්න"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"දකුණට ස්නැප් කරන්න"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml index 529a6932c9ce..96e54f1caa68 100644 --- a/libs/WindowManager/Shell/res/values-sk/strings.xml +++ b/libs/WindowManager/Shell/res/values-sk/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problémy s kamerou?\nKlepnutím znova upravte."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nevyriešilo sa to?\nKlepnutím sa vráťte."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemáte problémy s kamerou? Klepnutím zatvoríte."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Klepnúť a otvoriť tak ponuku aplikácií"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Klepnúť a zobraziť tak viacero aplikácií naraz"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Prejsť späť na celú obrazovku z ponuky aplikácií"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Zobrazte si a zvládnite toho viac"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Rozdelenú obrazovku môžete použiť presunutím do inej aplikácie"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvojitým klepnutím mimo aplikácie zmeníte jej pozíciu"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Správa okien"</string> <string name="close_text" msgid="4986518933445178928">"Zavrieť"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Zavrieť ponuku"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Otvoriť ponuku"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximalizovať obrazovku"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Zobraziť polovicu obrazovky"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Veľkosť tejto aplikácie sa nedá zmeniť"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikácia sa sem nedá presunúť"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maximalizovať"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Prichytiť vľavo"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Prichytiť vpravo"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml index 280346d0559a..66c9b26de54e 100644 --- a/libs/WindowManager/Shell/res/values-sl/strings.xml +++ b/libs/WindowManager/Shell/res/values-sl/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Težave s fotoaparatom?\nDotaknite se za vnovično prilagoditev"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"To ni odpravilo težave?\nDotaknite se za povrnitev"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nimate težav s fotoaparatom? Dotaknite se za opustitev."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Dotaknite se, če želite odpreti meni aplikacije"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Dotaknite se, če želite prikazati več aplikacij hkrati"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Nazaj v celozaslonski način iz menija aplikacije"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Oglejte si in naredite več"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Za razdeljeni zaslon povlecite sem še eno aplikacijo."</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvakrat se dotaknite zunaj aplikacije, če jo želite prestaviti."</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Odpri meni"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimiraj zaslon"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Pripni zaslon"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Velikosti te aplikacije ni mogoče spremeniti"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikacije ni mogoče premakniti sem"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimiraj"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Pripni levo"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Pripni desno"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml index a4a7e744c426..6e49999545a8 100644 --- a/libs/WindowManager/Shell/res/values-sq/strings.xml +++ b/libs/WindowManager/Shell/res/values-sq/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Ka probleme me kamerën?\nTrokit për ta ripërshtatur"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nuk u rregullua?\nTrokit për ta rikthyer"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nuk ka probleme me kamerën? Trokit për ta shpërfillur."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Trokit për të hapur menynë e aplikacionit"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Trokit për të shfaqur disa aplikacone bashkë"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Kthehu tek ekrani i plotë nga menyja e aplikacionit"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Shiko dhe bëj më shumë"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Zvarrite në një aplikacion tjetër për ekranin e ndarë"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Trokit dy herë jashtë një aplikacioni për ta ripozicionuar"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Menaxho dritaret"</string> <string name="close_text" msgid="4986518933445178928">"Mbyll"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Mbyll menynë"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Hap menynë"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maksimizo ekranin"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Regjistro ekranin"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Përmasat e këtij aplikacioni nuk mund të ndryshohen"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Aplikacioni nuk mund të zhvendoset këtu"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Maksimizo"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Zhvendos majtas"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Zhvendos djathtas"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml index 9545ccf7a810..bd2fb8c442f3 100644 --- a/libs/WindowManager/Shell/res/values-sr/strings.xml +++ b/libs/WindowManager/Shell/res/values-sr/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Имате проблема са камером?\nДодирните да бисте поново уклопили"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Проблем није решен?\nДодирните да бисте вратили"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Немате проблема са камером? Додирните да бисте одбацили."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Додирните да бисте отворили мени апликације"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Додирните да бисте приказали више апликација заједно"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Вратите се из менија апликације на приказ преко целог екрана"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Видите и урадите више"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Превуците другу апликацију да бисте користили подељени екран"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Двапут додирните изван апликације да бисте променили њену позицију"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Управљајте прозорима"</string> <string name="close_text" msgid="4986518933445178928">"Затворите"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Затворите мени"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Отворите мени"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Повећај екран"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Уклопи екран"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Величина ове апликације не може да се промени"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Апликација не може да се премести овде"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Увећајте"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Прикачите лево"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Прикачите десно"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml index aa74bdef0140..2184ac6bfca7 100644 --- a/libs/WindowManager/Shell/res/values-sv/strings.xml +++ b/libs/WindowManager/Shell/res/values-sv/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problem med kameran?\nTryck för att anpassa på nytt"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Löstes inte problemet?\nTryck för att återställa"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Inga problem med kameran? Tryck för att ignorera."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Tryck för att öppna appmenyn"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Tryck för att visa flera appar tillsammans"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Återgå till helskärm från appmenyn"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Se och gör mer"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Dra till en annan app för att dela upp skärmen"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Tryck snabbt två gånger utanför en app för att flytta den"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Öppna menyn"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Maximera skärmen"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Fäst skärmen"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Det går inte att ändra storlek på appen"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Det går inte att flytta appen hit"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Utöka"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Fäst till vänster"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Fäst till höger"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml index c6ce023a5ca7..6068bf00a6df 100644 --- a/libs/WindowManager/Shell/res/values-sw/strings.xml +++ b/libs/WindowManager/Shell/res/values-sw/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Je, kuna hitilafu za kamera?\nGusa ili urekebishe"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Umeshindwa kurekebisha?\nGusa ili urejeshe nakala ya awali"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Je, hakuna hitilafu za kamera? Gusa ili uondoe."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Gusa ili ufungue menyu ya programu"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Gusa ili uonyeshe programu nyingi kwa pamoja"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Rudi kwenye skrini nzima katika menyu ya programu"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Angalia na ufanye zaidi"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Buruta katika programu nyingine ili utumie skrini iliyogawanywa"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Gusa mara mbili nje ya programu ili uihamishe"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Dhibiti Windows"</string> <string name="close_text" msgid="4986518933445178928">"Funga"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Funga Menyu"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Fungua Menyu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Panua Dirisha kwenye Skrini"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Panga Madirisha kwenye Skrini"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Huwezi kubadilisha ukubwa wa programu hii"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Imeshindwa kuhamishia programu hapa"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Panua"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Telezesha kushoto"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Telezesha kulia"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml index 2c2f31978b0f..a14abac75245 100644 --- a/libs/WindowManager/Shell/res/values-ta/strings.xml +++ b/libs/WindowManager/Shell/res/values-ta/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"கேமரா தொடர்பான சிக்கல்களா?\nமீண்டும் பொருத்த தட்டவும்"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"சிக்கல்கள் சரிசெய்யப்படவில்லையா?\nமாற்றியமைக்க தட்டவும்"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"கேமரா தொடர்பான சிக்கல்கள் எதுவும் இல்லையா? நிராகரிக்க தட்டவும்."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"ஆப்ஸ் மெனுவைத் திறக்க தட்டவும்"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"பல ஆப்ஸை ஒன்றாகக் காட்ட தட்டவும்"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"ஆப்ஸ் மெனுவில் இருந்து முழுத்திரைக்குச் செல்லும்"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"பலவற்றைப் பார்த்தல் மற்றும் செய்தல்"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"திரைப் பிரிப்புக்கு மற்றொரு ஆப்ஸை இழுக்கலாம்"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ஆப்ஸை இடம் மாற்ற அதன் வெளியில் இருமுறை தட்டலாம்"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"சாளரங்களை நிர்வகிக்கலாம்"</string> <string name="close_text" msgid="4986518933445178928">"மூடும்"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"மெனுவை மூடும்"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"மெனுவைத் திறக்கும்"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"திரையைப் பெரிதாக்கு"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"திரையை ஸ்னாப் செய்"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"இந்த ஆப்ஸின் அளவை மாற்ற முடியாது"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ஆப்ஸை இங்கே நகர்த்த முடியாது"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"பெரிதாக்கும்"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"இடதுபுறம் நகர்த்தும்"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"வலதுபுறம் நகர்த்தும்"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml index 8691c9d5aa26..84e76a8cc361 100644 --- a/libs/WindowManager/Shell/res/values-te/strings.xml +++ b/libs/WindowManager/Shell/res/values-te/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"కెమెరా సమస్యలు ఉన్నాయా?\nరీఫిట్ చేయడానికి ట్యాప్ చేయండి"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"దాని సమస్యను పరిష్కరించలేదా?\nపూర్వస్థితికి మార్చడానికి ట్యాప్ చేయండి"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"కెమెరా సమస్యలు లేవా? తీసివేయడానికి ట్యాప్ చేయండి."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"యాప్ మెనూని తెరవడానికి ట్యాప్ చేయండి"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"పలు యాప్లను కలిపి చూడటానికి ట్యాప్ చేయండి"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"యాప్ మెనూ నుండి ఫుల్ స్క్రీన్కు తిరిగి రండి"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"చూసి, మరిన్ని చేయండి"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"స్ప్లిట్ స్క్రీన్ కోసం మరొక యాప్లోకి లాగండి"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"యాప్ స్థానాన్ని మార్చడానికి దాని వెలుపల డబుల్-ట్యాప్ చేయండి"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"విండోలను మేనేజ్ చేయండి"</string> <string name="close_text" msgid="4986518933445178928">"మూసివేయండి"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"మెనూను మూసివేయండి"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"మెనూను తెరవండి"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"స్క్రీన్ సైజ్ను పెంచండి"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"స్క్రీన్ను స్నాప్ చేయండి"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"ఈ యాప్ సైజ్ను మార్చడం సాధ్యపడదు"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"యాప్ను ఇక్కడకి తరలించడం సాధ్యం కాదు"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"మ్యాగ్జిమైజ్ చేయండి"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"ఎడమ వైపున స్నాప్ చేయండి"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"కుడి వైపున స్నాప్ చేయండి"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml index 07e141601d08..856893f83955 100644 --- a/libs/WindowManager/Shell/res/values-th/strings.xml +++ b/libs/WindowManager/Shell/res/values-th/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"หากพบปัญหากับกล้อง\nแตะเพื่อแก้ไข"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"หากไม่ได้แก้ไข\nแตะเพื่อเปลี่ยนกลับ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"หากไม่พบปัญหากับกล้อง แตะเพื่อปิด"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"แตะเพื่อเปิดเมนูแอป"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"แตะเพื่อแสดงแอปหลายรายการพร้อมกัน"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"กลับไปที่เต็มหน้าจอจากเมนูแอป"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"รับชมและทำสิ่งต่างๆ ได้มากขึ้น"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"ลากไปไว้ในแอปอื่นเพื่อแยกหน้าจอ"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"แตะสองครั้งด้านนอกแอปเพื่อเปลี่ยนตำแหน่ง"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"จัดการหน้าต่าง"</string> <string name="close_text" msgid="4986518933445178928">"ปิด"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"ปิดเมนู"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"เปิดเมนู"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"ขยายหน้าจอให้ใหญ่สุด"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"สแนปหน้าจอ"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"ปรับขนาดแอปนี้ไม่ได้"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ย้ายแอปมาที่นี่ไม่ได้"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"ขยายใหญ่สุด"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"จัดพอดีกับทางซ้าย"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"จัดพอดีกับทางขวา"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml index 477700e7bbdf..dc92efd8e18f 100644 --- a/libs/WindowManager/Shell/res/values-tl/strings.xml +++ b/libs/WindowManager/Shell/res/values-tl/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"May mga isyu sa camera?\nI-tap para i-refit"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Hindi ito naayos?\nI-tap para i-revert"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Walang isyu sa camera? I-tap para i-dismiss."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"I-tap para buksan ang menu ng app"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"I-tap para ipakita nang magkakasama ang maraming app"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Bumalik sa fullscreen mula sa menu ng app"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Tumingin at gumawa ng higit pa"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Mag-drag ng isa pang app para sa split screen"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Mag-double tap sa labas ng app para baguhin ang posisyon nito"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Pamahalaan ang Mga Window"</string> <string name="close_text" msgid="4986518933445178928">"Isara"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Isara ang Menu"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Buksan ang Menu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"I-maximize ang Screen"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"I-snap ang Screen"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Hindi nare-resize ang app na ito"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Hindi mailipat dito ang app"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"I-maximize"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"I-snap pakaliwa"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"I-snap pakanan"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml index b0c253965970..e206cd6cd10c 100644 --- a/libs/WindowManager/Shell/res/values-tr/strings.xml +++ b/libs/WindowManager/Shell/res/values-tr/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kameranızda sorun mu var?\nDüzeltmek için dokunun"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Bu işlem sorunu düzeltmedi mi?\nİşlemi geri almak için dokunun"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kameranızda sorun yok mu? Kapatmak için dokunun."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Uygulama menüsünü açmak için dokunun"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Birden fazla uygulamayı birlikte göstermek için dokunun"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Uygulama menüsünden tam ekrana dönün"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Daha fazlasını görün ve yapın"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Bölünmüş ekran için başka bir uygulamayı sürükleyin"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Yeniden konumlandırmak için uygulamanın dışına iki kez dokunun"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Pencereleri yönet"</string> <string name="close_text" msgid="4986518933445178928">"Kapat"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Menüyü kapat"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Menüyü aç"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ekranı Büyüt"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ekranın Yarısına Tuttur"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Bu uygulama yeniden boyutlandırılamaz"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Uygulama buraya taşınamıyor"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Ekranı kapla"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Sola tuttur"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Sağa tuttur"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml index dd64c6642104..90a3bc33b3e2 100644 --- a/libs/WindowManager/Shell/res/values-uk/strings.xml +++ b/libs/WindowManager/Shell/res/values-uk/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблеми з камерою?\nНатисніть, щоб пристосувати"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Проблему не вирішено?\nНатисніть, щоб скасувати зміни"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Немає проблем із камерою? Торкніться, щоб закрити."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Натисніть, щоб відкрити меню додатка"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Натисніть, щоб переглянути кілька додатків одночасно"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Повернутися з меню додатка в повноекранний режим"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Більше простору та можливостей"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Щоб перейти в режим розділення екрана, перетягніть сюди інший додаток"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Щоб перемістити додаток, двічі торкніться області поза ним"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Керувати вікнами"</string> <string name="close_text" msgid="4986518933445178928">"Закрити"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Закрити меню"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Відкрити меню"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Розгорнути екран"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Зафіксувати екран"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Розмір вікна цього додатка не можна змінити"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Сюди не можна перемістити додаток"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Розгорнути"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Закріпити ліворуч"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Закріпити праворуч"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml index aa311c2978c8..2006b0ba6929 100644 --- a/libs/WindowManager/Shell/res/values-ur/strings.xml +++ b/libs/WindowManager/Shell/res/values-ur/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"کیمرے کے مسائل؟\nدوبارہ فٹ کرنے کیلئے تھپتھپائیں"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"یہ حل نہیں ہوا؟\nلوٹانے کیلئے تھپتھپائیں"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"کوئی کیمرے کا مسئلہ نہیں ہے؟ برخاست کرنے کیلئے تھپتھپائیں۔"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"ایپ مینو کھولنے کیلئے تھپتھپائیں"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"متعدد ایپس ایک ساتھ دکھانے کیلئے تھپتھپائیں"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"ایپ مینو سے مکمل اسکرین پر واپس جائیں"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"دیکھیں اور بہت کچھ کریں"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"اسپلٹ اسکرین کے ليے دوسری ایپ میں گھسیٹیں"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"کسی ایپ کی پوزیشن تبدیل کرنے کے لیے اس ایپ کے باہر دو بار تھپتھپائیں"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Windows کا نظم کریں"</string> <string name="close_text" msgid="4986518933445178928">"بند کریں"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"مینیو بند کریں"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"مینو کھولیں"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"اسکرین کو بڑا کریں"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"اسکرین کا اسناپ شاٹ لیں"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"اس ایپ کا سائز تبدیل نہیں کیا جا سکتا"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"ایپ کو یہاں منتقل نہیں کیا جا سکتا"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"بڑا کریں"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"دائیں منتقل کریں"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"بائیں منتقل کریں"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml index cd0ca82ff563..4b163f79f970 100644 --- a/libs/WindowManager/Shell/res/values-uz/strings.xml +++ b/libs/WindowManager/Shell/res/values-uz/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamera nosozmi?\nQayta moslash uchun bosing"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Tuzatilmadimi?\nQaytarish uchun bosing"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kamera muammosizmi? Yopish uchun bosing."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Ilova menyusini ochish uchun bosing"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Bir nechta ilovani birga chiqarish uchun bosing"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Ilova menyusidan butun ekranga qayting"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Yana boshqa amallar"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Ekranni ikkiga ajratish uchun boshqa ilovani bu yerga torting"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Qayta joylash uchun ilova tashqarisiga ikki marta bosing"</string> @@ -129,8 +132,18 @@ <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Menyuni ochish"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Ekranni yoyish"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Ekranni biriktirish"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Bu ilova hajmini oʻzgartirish imkonsiz"</string> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Ilova bu yerga surilmaydi"</string> <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Yoyish"</string> <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Chapga tortish"</string> <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Oʻngga tortish"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> + <skip /> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> + <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml index abac3fe824bb..db86498130d8 100644 --- a/libs/WindowManager/Shell/res/values-vi/strings.xml +++ b/libs/WindowManager/Shell/res/values-vi/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Có vấn đề với máy ảnh?\nHãy nhấn để sửa lỗi"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Bạn chưa khắc phục vấn đề?\nHãy nhấn để hủy bỏ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Không có vấn đề với máy ảnh? Hãy nhấn để đóng."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Nhấn để mở trình đơn ứng dụng"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Nhấn để hiển thị nhiều ứng dụng cùng lúc"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Quay lại chế độ toàn màn hình từ trình đơn ứng dụng"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Xem và làm được nhiều việc hơn"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Kéo một ứng dụng khác vào để chia đôi màn hình"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Nhấn đúp bên ngoài ứng dụng để đặt lại vị trí"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Quản lý cửa sổ"</string> <string name="close_text" msgid="4986518933445178928">"Đóng"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Đóng trình đơn"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Mở Trình đơn"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Mở rộng màn hình"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Điều chỉnh kích thước màn hình"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Không thể đổi kích thước của ứng dụng này"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"Không di chuyển được ứng dụng đến đây"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Phóng to tối đa"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Di chuyển nhanh sang trái"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Di chuyển nhanh sang phải"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml index 5a61decdcfb9..ebf4b038b098 100644 --- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"相机有问题?\n点按即可整修"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"没有解决此问题?\n点按即可恢复"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"相机没有问题?点按即可忽略。"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"点按可打开应用菜单"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"点按可同时显示多个应用"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"从应用菜单可返回到全屏"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"查看和处理更多任务"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"拖入另一个应用,即可使用分屏模式"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"在某个应用外连续点按两次,即可调整它的位置"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"管理窗口"</string> <string name="close_text" msgid="4986518933445178928">"关闭"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"关闭菜单"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"打开菜单"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"最大化屏幕"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"屏幕快照"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"无法调整此应用的大小"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"无法将应用移至此处"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"最大化"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"贴靠左侧"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"贴靠右侧"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml index e1c303e198bb..f1d12fce0103 100644 --- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"相機有問題?\n輕按即可修正"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"未能修正問題?\n輕按即可還原"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"相機冇問題?㩒一下就可以即可閂咗佢。"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"輕按即可開啟應用程式選單"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"輕按即可同時顯示多個應用程式"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"從應用程式選單返回全螢幕"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"瀏覽更多內容及執行更多操作"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"拖入另一個應用程式即可分割螢幕"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"在應用程式外輕按兩下即可調整位置"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"管理視窗"</string> <string name="close_text" msgid="4986518933445178928">"關閉"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"關閉選單"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"打開選單"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"畫面最大化"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"貼齊畫面"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"此應用程式無法調整大小"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"應用程式無法移至這裡"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"最大化"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"貼齊左邊"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"貼齊右邊"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml index 97e36c300a4a..b5c28d347acb 100644 --- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"相機有問題嗎?\n輕觸即可修正"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"未修正問題嗎?\n輕觸即可還原"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"相機沒問題嗎?輕觸即可關閉。"</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"輕觸即可開啟應用程式選單"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"輕觸即可一次顯示多個應用程式"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"從應用程式選單返回全螢幕"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"瀏覽更多內容及執行更多操作"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"拖進另一個應用程式即可使用分割畫面模式"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"在應用程式外輕觸兩下即可調整位置"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"管理視窗"</string> <string name="close_text" msgid="4986518933445178928">"關閉"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"關閉選單"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"開啟選單"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"畫面最大化"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"貼齊畫面"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"這個應用程式無法調整大小"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"應用程式無法移至此處"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"最大化"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"靠左對齊"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"靠右對齊"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml index 74c7169fefa3..f54d0ed01ea8 100644 --- a/libs/WindowManager/Shell/res/values-zu/strings.xml +++ b/libs/WindowManager/Shell/res/values-zu/strings.xml @@ -97,6 +97,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Izinkinga zekhamera?\nThepha ukuze uyilinganise kabusha"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Akuyilungisanga?\nThepha ukuze ubuyele"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Azikho izinkinga zekhamera? Thepha ukuze ucashise."</string> + <string name="windowing_app_handle_education_tooltip" msgid="6398482412956375783">"Thepha ukuze uvule imenyu ye-app"</string> + <string name="windowing_desktop_mode_image_button_education_tooltip" msgid="6285279585554484957">"Thepha ukuze ubonise ama-app amaningi ndawonye"</string> + <string name="windowing_desktop_mode_exit_education_tooltip" msgid="6685429075790085337">"Buyela esikrinini esigcwele ukusuka kumenyu ye-app"</string> <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Bona futhi wenze okuningi"</string> <string name="letterbox_education_split_screen_text" msgid="449233070804658627">"Hudula kwenye i-app mayelana nokuhlukanisa isikrini"</string> <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Thepha kabili ngaphandle kwe-app ukuze uyimise kabusha"</string> @@ -126,15 +129,21 @@ <string name="manage_windows_text" msgid="5567366688493093920">"Phatha Amawindi"</string> <string name="close_text" msgid="4986518933445178928">"Vala"</string> <string name="collapse_menu_text" msgid="7515008122450342029">"Vala Imenyu"</string> - <!-- no translation found for desktop_mode_app_header_chip_text (6366422614991687237) --> - <skip /> + <string name="desktop_mode_app_header_chip_text" msgid="6366422614991687237">"Vula Imenyu"</string> <string name="desktop_mode_maximize_menu_maximize_text" msgid="3275717276171114411">"Khulisa Isikrini Sifike Ekugcineni"</string> <string name="desktop_mode_maximize_menu_snap_text" msgid="2065251022783880154">"Thwebula Isikrini"</string> - <string name="desktop_mode_non_resizable_snap_text" msgid="1049800446363800707">"Le app ayikwazi ukushintshwa usayizi"</string> - <!-- no translation found for desktop_mode_maximize_menu_maximize_button_text (3090199175564175845) --> + <string name="desktop_mode_non_resizable_snap_text" msgid="3771776422751387878">"I-app ayikwazi ukuhanjiswa lapha"</string> + <string name="desktop_mode_maximize_menu_maximize_button_text" msgid="3090199175564175845">"Khulisa"</string> + <string name="desktop_mode_maximize_menu_snap_left_button_text" msgid="8077452201179893424">"Chofoza kwesobunxele"</string> + <string name="desktop_mode_maximize_menu_snap_right_button_text" msgid="7117751068945657304">"Chofoza kwesokudla"</string> + <!-- no translation found for open_by_default_settings_text (2526548548598185500) --> + <skip /> + <!-- no translation found for open_by_default_dialog_subheader_text (1729599730664063881) --> + <skip /> + <!-- no translation found for open_by_default_dialog_in_app_text (6978022419634199806) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_left_button_text (8077452201179893424) --> + <!-- no translation found for open_by_default_dialog_in_browser_text (8042769465958497081) --> <skip /> - <!-- no translation found for desktop_mode_maximize_menu_snap_right_button_text (7117751068945657304) --> + <!-- no translation found for open_by_default_dialog_dismiss_button_text (3487238795534582291) --> <skip /> </resources> diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml index c7109f5be132..1f1565160965 100644 --- a/libs/WindowManager/Shell/res/values/dimen.xml +++ b/libs/WindowManager/Shell/res/values/dimen.xml @@ -624,4 +624,12 @@ <!-- The offset from the left edge of the entering page for the cross-activity animation --> <dimen name="cross_activity_back_entering_start_offset">96dp</dimen> + <!-- The open by default settings dialog menu width. --> + <dimen name="open_by_default_settings_dialog_width">348dp</dimen> + <!-- The open by default settings dialog menu height. --> + <dimen name="open_by_default_settings_dialog_height">380dp</dimen> + <!-- The height of radio buttons in the open by default settings dialog. --> + <dimen name="open_by_default_settings_dialog_radio_button_height">64dp</dimen> + <!-- The width of radio buttons in the open by default settings dialog. --> + <dimen name="open_by_default_settings_dialog_radio_button_width">316dp</dimen> </resources> diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml index 56f25dae3df2..5ef843210bbf 100644 --- a/libs/WindowManager/Shell/res/values/strings.xml +++ b/libs/WindowManager/Shell/res/values/strings.xml @@ -323,4 +323,15 @@ <string name="desktop_mode_maximize_menu_snap_left_button_text">Snap left</string> <!-- Accessibility text for the Maximize Menu's snap right button [CHAR LIMIT=NONE] --> <string name="desktop_mode_maximize_menu_snap_right_button_text">Snap right</string> + + <!-- Accessibility text for open by default settings button [CHAR LIMIT=NONE] --> + <string name="open_by_default_settings_text">Open by default settings</string> + <!-- Subheader for open by default menu string. --> + <string name="open_by_default_dialog_subheader_text">Choose how to open web links for this app</string> + <!-- Text for open by default settings dialog option. --> + <string name="open_by_default_dialog_in_app_text">In the app</string> + <!-- Text for open by default settings dialog option. --> + <string name="open_by_default_dialog_in_browser_text">In your browser</string> + <!-- Text for open by default settings dialog dismiss button. --> + <string name="open_by_default_dialog_dismiss_button_text">OK</string> </resources> diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/BubbleInfo.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/BubbleInfo.java index 58766826bd3b..85dabce8ac20 100644 --- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/BubbleInfo.java +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/BubbleInfo.java @@ -30,29 +30,32 @@ import java.util.Objects; */ public class BubbleInfo implements Parcelable { - private String mKey; // Same key as the Notification + private final String mKey; // Same key as the Notification private int mFlags; // Flags from BubbleMetadata @Nullable - private String mShortcutId; - private int mUserId; - private String mPackageName; + private final String mShortcutId; + private final int mUserId; + private final String mPackageName; /** * All notification bubbles require a shortcut to be set on the notification, however, the * app could still specify an Icon and PendingIntent to use for the bubble. In that case * this icon will be populated. If the bubble is entirely shortcut based, this will be null. */ @Nullable - private Icon mIcon; + private final Icon mIcon; @Nullable - private String mTitle; + private final String mTitle; @Nullable - private String mAppName; - private boolean mIsImportantConversation; - private boolean mShowAppBadge; + private final String mAppName; + private final boolean mIsImportantConversation; + private final boolean mShowAppBadge; + @Nullable + private final ParcelableFlyoutMessage mParcelableFlyoutMessage; public BubbleInfo(String key, int flags, @Nullable String shortcutId, @Nullable Icon icon, int userId, String packageName, @Nullable String title, @Nullable String appName, - boolean isImportantConversation, boolean showAppBadge) { + boolean isImportantConversation, boolean showAppBadge, + @Nullable ParcelableFlyoutMessage flyoutMessage) { mKey = key; mFlags = flags; mShortcutId = shortcutId; @@ -63,6 +66,7 @@ public class BubbleInfo implements Parcelable { mAppName = appName; mIsImportantConversation = isImportantConversation; mShowAppBadge = showAppBadge; + mParcelableFlyoutMessage = flyoutMessage; } private BubbleInfo(Parcel source) { @@ -76,6 +80,8 @@ public class BubbleInfo implements Parcelable { mAppName = source.readString(); mIsImportantConversation = source.readBoolean(); mShowAppBadge = source.readBoolean(); + mParcelableFlyoutMessage = source.readParcelable( + ParcelableFlyoutMessage.class.getClassLoader(), ParcelableFlyoutMessage.class); } public String getKey() { @@ -122,6 +128,11 @@ public class BubbleInfo implements Parcelable { return mShowAppBadge; } + @Nullable + public ParcelableFlyoutMessage getParcelableFlyoutMessage() { + return mParcelableFlyoutMessage; + } + /** * Whether this bubble is currently being hidden from the stack. */ @@ -180,6 +191,7 @@ public class BubbleInfo implements Parcelable { parcel.writeString(mAppName); parcel.writeBoolean(mIsImportantConversation); parcel.writeBoolean(mShowAppBadge); + parcel.writeParcelable(mParcelableFlyoutMessage, flags); } @NonNull diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/FlyoutDrawableLoader.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/FlyoutDrawableLoader.kt new file mode 100644 index 000000000000..5a1733094019 --- /dev/null +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/FlyoutDrawableLoader.kt @@ -0,0 +1,47 @@ +/* + * 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.shared.bubbles + +import android.content.Context +import android.content.Intent +import android.graphics.drawable.Drawable +import android.graphics.drawable.Icon +import android.util.Log + +object FlyoutDrawableLoader { + + private const val TAG = "FlyoutDrawableLoader" + + /** Loads the flyout icon as a [Drawable]. */ + @JvmStatic + fun Icon?.loadFlyoutDrawable(context: Context): Drawable? { + if (this == null) return null + try { + if (this.type == Icon.TYPE_URI || this.type == Icon.TYPE_URI_ADAPTIVE_BITMAP) { + context.grantUriPermission( + context.packageName, + this.uri, + Intent.FLAG_GRANT_READ_URI_PERMISSION + ) + } + return loadDrawable(context) + } catch (e: Exception) { + Log.w(TAG, "loadFlyoutDrawable failed: ${e.message}") + return null + } + } +} diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/ParcelableFlyoutMessage.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/ParcelableFlyoutMessage.kt new file mode 100644 index 000000000000..294d5e552684 --- /dev/null +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/bubbles/ParcelableFlyoutMessage.kt @@ -0,0 +1,55 @@ +/* + * 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.shared.bubbles + +import android.graphics.drawable.Icon +import android.os.Parcel +import android.os.Parcelable + +/** The contents of the flyout message to be passed to launcher for rendering in the bubble bar. */ +class ParcelableFlyoutMessage( + val icon: Icon?, + val title: String?, + val message: String?, +) : Parcelable { + + constructor( + parcel: Parcel + ) : this( + icon = parcel.readParcelable(Icon::class.java.classLoader), + title = parcel.readString(), + message = parcel.readString(), + ) + + override fun writeToParcel(parcel: Parcel, flags: Int) { + parcel.writeParcelable(icon, flags) + parcel.writeString(title) + parcel.writeString(message) + } + + override fun describeContents() = 0 + + companion object { + @JvmField + val CREATOR = + object : Parcelable.Creator<ParcelableFlyoutMessage> { + override fun createFromParcel(parcel: Parcel) = ParcelableFlyoutMessage(parcel) + + override fun newArray(size: Int) = arrayOfNulls<ParcelableFlyoutMessage>(size) + } + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/EventLogTags.logtags b/libs/WindowManager/Shell/src/com/android/wm/shell/EventLogTags.logtags new file mode 100644 index 000000000000..db960d15c526 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/EventLogTags.logtags @@ -0,0 +1,11 @@ +# See system/logging/logcat/event.logtags for a description of the format of this file. + +option java_package com.android.wm.shell + +# Do not change these names without updating the checkin_events setting in +# google3/googledata/wireless/android/provisioning/gservices.config !! +# + +38500 wm_shell_enter_desktop_mode (EnterReason|1|5),(SessionId|1|5) +38501 wm_shell_exit_desktop_mode (ExitReason|1|5),(SessionId|1|5) +38502 wm_shell_desktop_mode_task_update (TaskEvent|1|5),(InstanceId|1|5),(uid|1|5),(TaskHeight|1),(TaskWidth|1),(TaskX|1),(TaskY|1),(SessionId|1|5),(MinimiseReason|1|5),(UnminimiseReason|1|5),(VisibleTaskCount|1) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OpenByDefaultDialog.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OpenByDefaultDialog.kt new file mode 100644 index 000000000000..4926cbdbe9fb --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OpenByDefaultDialog.kt @@ -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 com.android.wm.shell.apptoweb + +import android.app.ActivityManager.RunningTaskInfo +import android.app.TaskInfo +import android.content.Context +import android.graphics.Bitmap +import android.graphics.PixelFormat +import android.view.LayoutInflater +import android.view.SurfaceControl +import android.view.SurfaceControlViewHost +import android.view.WindowManager +import android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE +import android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL +import android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL +import android.view.WindowlessWindowManager +import android.widget.ImageView +import android.widget.TextView +import android.window.TaskConstants +import com.android.wm.shell.R +import com.android.wm.shell.common.DisplayController +import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer +import java.util.function.Supplier + + +/** + * Window manager for the open by default settings dialog + */ +internal class OpenByDefaultDialog( + private val context: Context, + private val taskInfo: TaskInfo, + private val taskSurface: SurfaceControl, + private val displayController: DisplayController, + private val surfaceControlTransactionSupplier: Supplier<SurfaceControl.Transaction>, + private val listener: DialogLifecycleListener, + appIconBitmap: Bitmap?, + appName: CharSequence? +) { + private lateinit var dialog: OpenByDefaultDialogView + private lateinit var viewHost: SurfaceControlViewHost + private lateinit var dialogSurfaceControl: SurfaceControl + private var dialogContainer: AdditionalViewHostViewContainer? = null + private lateinit var appIconView: ImageView + private lateinit var appNameView: TextView + + init { + createDialog() + bindAppInfo(appIconBitmap, appName) + } + + /** Creates an open by default settings dialog. */ + fun createDialog() { + val t = SurfaceControl.Transaction() + val taskBounds = taskInfo.configuration.windowConfiguration.bounds + + dialog = LayoutInflater.from(context) + .inflate( + R.layout.open_by_default_settings_dialog, + null /* root */ + ) as OpenByDefaultDialogView + appIconView = dialog.requireViewById(R.id.application_icon) + appNameView = dialog.requireViewById(R.id.application_name) + + val display = displayController.getDisplay(taskInfo.displayId) + val builder: SurfaceControl.Builder = SurfaceControl.Builder() + dialogSurfaceControl = builder + .setName("Open by Default Dialog of Task=" + taskInfo.taskId) + .setContainerLayer() + .setParent(taskSurface) + .setCallsite("OpenByDefaultDialog#createDialog") + .build() + t.setPosition(dialogSurfaceControl, 0f, 0f) + .setWindowCrop(dialogSurfaceControl, taskBounds.width(), taskBounds.height()) + .setLayer(dialogSurfaceControl, TaskConstants.TASK_CHILD_LAYER_SETTINGS_DIALOG) + .show(dialogSurfaceControl) + val lp = WindowManager.LayoutParams( + taskBounds.width(), + taskBounds.height(), + TYPE_APPLICATION_PANEL, + FLAG_NOT_FOCUSABLE or FLAG_NOT_TOUCH_MODAL, + PixelFormat.TRANSLUCENT) + lp.title = "Open by default settings dialog of task=" + taskInfo.taskId + lp.setTrustedOverlay() + val windowManager = WindowlessWindowManager( + taskInfo.configuration, + dialogSurfaceControl, null /* hostInputToken */ + ) + viewHost = SurfaceControlViewHost(context, display, windowManager, "Dialog").apply { + setView(dialog, lp) + rootSurfaceControl.applyTransactionOnDraw(t) + } + dialogContainer = AdditionalViewHostViewContainer( + dialogSurfaceControl, viewHost, surfaceControlTransactionSupplier) + + dialog.setDismissOnClickListener{ + closeMenu() + } + + listener.onDialogCreated() + } + + private fun closeMenu() { + dialogContainer?.releaseView() + dialogContainer = null + listener.onDialogDismissed() + } + + private fun bindAppInfo( + appIconBitmap: Bitmap?, + appName: CharSequence? + ) { + appIconView.setImageBitmap(appIconBitmap) + appNameView.text = appName + } + + /** + * Relayout the dialog to the new task bounds. + */ + fun relayout( + taskInfo: RunningTaskInfo, + ) { + val t = surfaceControlTransactionSupplier.get() + val taskBounds = taskInfo.configuration.windowConfiguration.bounds + t.setWindowCrop(dialogSurfaceControl, taskBounds.width(), taskBounds.height()) + viewHost.rootSurfaceControl.applyTransactionOnDraw(t) + viewHost.relayout(taskBounds.width(), taskBounds.height()) + } + + /** + * Defines interface for classes that can listen to lifecycle events of open by default settings + * dialog. + */ + interface DialogLifecycleListener { + /** Called when open by default dialog view has been created. */ + fun onDialogCreated() + + /** Called when open by default dialog view has been released. */ + fun onDialogDismissed() + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OpenByDefaultDialogView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OpenByDefaultDialogView.kt new file mode 100644 index 000000000000..d03a38e8699a --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OpenByDefaultDialogView.kt @@ -0,0 +1,55 @@ +/* + * 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.apptoweb +import android.content.Context +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import android.widget.Button +import androidx.constraintlayout.widget.ConstraintLayout +import com.android.wm.shell.R + +/** View for open by default settings dialog for an application which allows the user to change + * where links will open by default, in the default browser or in the application. */ +class OpenByDefaultDialogView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + defStyleRes: Int = 0 +) : ConstraintLayout(context, attrs, defStyleAttr, defStyleRes) { + + private lateinit var dialogContainer: View + private lateinit var backgroundDim: Drawable + + fun setDismissOnClickListener(callback: (View) -> Unit) { + val dismissButton = dialogContainer.requireViewById<Button>( + R.id.open_by_default_settings_dialog_dismiss_button) + dismissButton.setOnClickListener(callback) + // Clicks on the background dim should also dismiss the dialog. + setOnClickListener(callback) + // We add a no-op on-click listener to the dialog container so that clicks on it won't + // propagate to the listener of the layout (which represents the background dim). + dialogContainer.setOnClickListener { } + } + + override fun onFinishInflate() { + super.onFinishInflate() + dialogContainer = requireViewById(R.id.open_by_default_dialog_container) + backgroundDim = background.mutate() + backgroundDim.alpha = 128 + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java index df80946a99aa..7c5f71647843 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java @@ -33,8 +33,6 @@ public interface BackAnimation { * * @param touchX the X touch position of the {@link MotionEvent}. * @param touchY the Y touch position of the {@link MotionEvent}. - * @param velocityX the X velocity computed from the {@link MotionEvent}. - * @param velocityY the Y velocity computed from the {@link MotionEvent}. * @param keyAction the original {@link KeyEvent#getAction()} when the event was dispatched to * the process. This is forwarded separately because the input pipeline may mutate * the {#event} action state later. @@ -43,8 +41,6 @@ public interface BackAnimation { void onBackMotion( float touchX, float touchY, - float velocityX, - float velocityY, int keyAction, @BackEvent.SwipeEdge int swipeEdge); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java index 5836085e0ddc..b90e6e2fab8a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java @@ -352,16 +352,12 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont public void onBackMotion( float touchX, float touchY, - float velocityX, - float velocityY, int keyAction, @BackEvent.SwipeEdge int swipeEdge ) { mShellExecutor.execute(() -> onMotionEvent( /* touchX = */ touchX, /* touchY = */ touchY, - /* velocityX = */ velocityX, - /* velocityY = */ velocityY, /* keyAction = */ keyAction, /* swipeEdge = */ swipeEdge)); } @@ -500,14 +496,12 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont public void onMotionEvent( float touchX, float touchY, - float velocityX, - float velocityY, int keyAction, @BackEvent.SwipeEdge int swipeEdge) { BackTouchTracker activeTouchTracker = getActiveTracker(); if (activeTouchTracker != null) { - activeTouchTracker.update(touchX, touchY, velocityX, velocityY); + activeTouchTracker.update(touchX, touchY); } // two gestures are waiting to be processed at the moment, skip any further user touches diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java index 169361ad5f6b..e3fc5c2273e2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java @@ -56,6 +56,7 @@ import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.shared.annotations.ShellBackgroundThread; import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.shared.bubbles.BubbleInfo; +import com.android.wm.shell.shared.bubbles.ParcelableFlyoutMessage; import java.io.PrintWriter; import java.util.List; @@ -350,7 +351,22 @@ public class Bubble implements BubbleViewProvider { getTitle(), getAppName(), isImportantConversation(), - !isAppLaunchIntent()); + !isAppLaunchIntent(), + getParcelableFlyoutMessage()); + } + + /** Creates a parcelable flyout message to send to launcher. */ + @Nullable + private ParcelableFlyoutMessage getParcelableFlyoutMessage() { + if (mFlyoutMessage == null) { + return null; + } + // the icon is only used in group chats + Icon icon = mFlyoutMessage.isGroupChat ? mFlyoutMessage.senderIcon : null; + String title = + mFlyoutMessage.senderName == null ? null : mFlyoutMessage.senderName.toString(); + String message = mFlyoutMessage.message == null ? null : mFlyoutMessage.message.toString(); + return new ParcelableFlyoutMessage(icon, title, message); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index af4a0c55f28d..a8a8c2a80974 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -274,7 +274,8 @@ public class BubbleController implements ConfigurationChangeListener, private final DragAndDropController mDragAndDropController; /** Used to send bubble events to launcher. */ private Bubbles.BubbleStateListener mBubbleStateListener; - + /** Used to track previous navigation mode to detect switch to buttons navigation. */ + private boolean mIsPrevNavModeGestures; /** Used to send updates to the views from {@link #mBubbleDataListener}. */ private BubbleViewCallback mBubbleViewCallback; @@ -356,6 +357,7 @@ public class BubbleController implements ConfigurationChangeListener, } }; mExpandedViewManager = BubbleExpandedViewManager.fromBubbleController(this); + mIsPrevNavModeGestures = ContextUtils.isGestureNavigationMode(mContext); } private void registerOneHandedState(OneHandedController oneHanded) { @@ -589,6 +591,13 @@ public class BubbleController implements ConfigurationChangeListener, */ private void sendInitialListenerUpdate() { if (mBubbleStateListener != null) { + boolean isCurrentNavModeGestures = ContextUtils.isGestureNavigationMode(mContext); + if (mIsPrevNavModeGestures && !isCurrentNavModeGestures) { + BubbleBarLocation navButtonsLocation = ContextUtils.isRtl(mContext) + ? BubbleBarLocation.RIGHT : BubbleBarLocation.LEFT; + mBubblePositioner.setBubbleBarLocation(navButtonsLocation); + } + mIsPrevNavModeGestures = isCurrentNavModeGestures; BubbleBarUpdate update = mBubbleData.getInitialStateForBubbleBar(); mBubbleStateListener.onBubbleStateChange(update); } @@ -2001,6 +2010,10 @@ public class BubbleController implements ConfigurationChangeListener, // in bubble bar mode, let the request to show the expanded view come from launcher. // only collapse here if we're collapsing. if (mLayerView != null && !isExpanded) { + if (mBubblePositioner.isImeVisible()) { + // If we're collapsing, hide the IME + hideCurrentInputMethod(); + } mLayerView.collapse(); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index 2795881f0938..35a0d07a63b2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -61,7 +61,6 @@ import android.view.ViewOutlineProvider; import android.view.ViewPropertyAnimator; import android.view.ViewTreeObserver; import android.view.WindowManager; -import android.view.WindowManagerPolicyConstants; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.widget.FrameLayout; @@ -91,10 +90,10 @@ import com.android.wm.shell.bubbles.animation.PhysicsAnimationLayout; import com.android.wm.shell.bubbles.animation.StackAnimationController; import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.shared.bubbles.DismissView; -import com.android.wm.shell.shared.bubbles.RelativeTouchListener; import com.android.wm.shell.shared.animation.Interpolators; import com.android.wm.shell.shared.animation.PhysicsAnimator; +import com.android.wm.shell.shared.bubbles.DismissView; +import com.android.wm.shell.shared.bubbles.RelativeTouchListener; import com.android.wm.shell.shared.magnetictarget.MagnetizedObject; import java.io.PrintWriter; @@ -2276,7 +2275,7 @@ public class BubbleStackView extends FrameLayout void startMonitoringSwipeUpGesture() { stopMonitoringSwipeUpGestureInternal(); - if (isGestureNavEnabled()) { + if (ContextUtils.isGestureNavigationMode(mContext)) { mBubblesNavBarGestureTracker = new BubblesNavBarGestureTracker(mContext, mPositioner); mBubblesNavBarGestureTracker.start(mSwipeUpListener); setOnTouchListener(mContainerSwipeListener); @@ -2311,12 +2310,6 @@ public class BubbleStackView extends FrameLayout } } - private boolean isGestureNavEnabled() { - return mContext.getResources().getInteger( - com.android.internal.R.integer.config_navBarInteractionMode) - == WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; - } - /** * Stop monitoring for swipe up gesture */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java index 3982a237dd3b..39fb2f49c1ee 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java @@ -21,11 +21,10 @@ import static com.android.wm.shell.bubbles.BadgedImageView.WHITE_SCRIM_ALPHA; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BUBBLES; +import static com.android.wm.shell.shared.bubbles.FlyoutDrawableLoader.loadFlyoutDrawable; -import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; -import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ShortcutInfo; @@ -34,7 +33,6 @@ import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Path; import android.graphics.drawable.Drawable; -import android.graphics.drawable.Icon; import android.util.Log; import android.util.PathParser; import android.view.LayoutInflater; @@ -51,7 +49,6 @@ import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.shared.handles.RegionSamplingHelper; import java.lang.ref.WeakReference; -import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; @@ -274,7 +271,7 @@ public class BubbleViewInfoTask { @Nullable BubbleExpandedView expandedView; int dotColor; Path dotPath; - @Nullable Bubble.FlyoutMessage flyoutMessage; + Bubble.FlyoutMessage flyoutMessage; Bitmap bubbleBitmap; Bitmap badgeBitmap; @@ -300,6 +297,10 @@ public class BubbleViewInfoTask { return null; } + // set the flyout message but don't load the avatar because we can't pass it on the + // binder to launcher + info.flyoutMessage = b.getFlyoutMessage(); + return info; } @@ -336,7 +337,7 @@ public class BubbleViewInfoTask { info.flyoutMessage = b.getFlyoutMessage(); if (info.flyoutMessage != null) { info.flyoutMessage.senderAvatar = - loadSenderAvatar(c, info.flyoutMessage.senderIcon); + loadFlyoutDrawable(info.flyoutMessage.senderIcon, c); } return info; } @@ -418,21 +419,4 @@ public class BubbleViewInfoTask { Color.WHITE, WHITE_SCRIM_ALPHA); return true; } - - @Nullable - static Drawable loadSenderAvatar(@NonNull final Context context, @Nullable final Icon icon) { - Objects.requireNonNull(context); - if (icon == null) return null; - try { - if (icon.getType() == Icon.TYPE_URI - || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) { - context.grantUriPermission(context.getPackageName(), - icon.getUri(), Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - return icon.loadDrawable(context); - } catch (Exception e) { - Log.w(TAG, "loadSenderAvatar failed: " + e.getMessage()); - return null; - } - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java index 1b7bb0db6516..e9a593392dc2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java @@ -20,11 +20,10 @@ import static com.android.wm.shell.bubbles.BadgedImageView.DEFAULT_PATH_SIZE; import static com.android.wm.shell.bubbles.BadgedImageView.WHITE_SCRIM_ALPHA; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.wm.shell.shared.bubbles.FlyoutDrawableLoader.loadFlyoutDrawable; -import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; -import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ShortcutInfo; @@ -33,7 +32,6 @@ import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Path; import android.graphics.drawable.Drawable; -import android.graphics.drawable.Icon; import android.os.AsyncTask; import android.util.Log; import android.util.PathParser; @@ -50,7 +48,6 @@ import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.shared.handles.RegionSamplingHelper; import java.lang.ref.WeakReference; -import java.util.Objects; import java.util.concurrent.Executor; /** @@ -181,7 +178,7 @@ public class BubbleViewInfoTaskLegacy extends @Nullable BubbleExpandedView expandedView; int dotColor; Path dotPath; - @Nullable Bubble.FlyoutMessage flyoutMessage; + Bubble.FlyoutMessage flyoutMessage; Bitmap bubbleBitmap; Bitmap badgeBitmap; @@ -221,6 +218,10 @@ public class BubbleViewInfoTaskLegacy extends return null; } + // set the flyout message but don't load the avatar because we can't pass it on the + // binder to launcher + info.flyoutMessage = b.getFlyoutMessage(); + return info; } @@ -260,7 +261,7 @@ public class BubbleViewInfoTaskLegacy extends info.flyoutMessage = b.getFlyoutMessage(); if (info.flyoutMessage != null) { info.flyoutMessage.senderAvatar = - loadSenderAvatar(c, info.flyoutMessage.senderIcon); + loadFlyoutDrawable(info.flyoutMessage.senderIcon, c); } return info; } @@ -342,21 +343,4 @@ public class BubbleViewInfoTaskLegacy extends Color.WHITE, WHITE_SCRIM_ALPHA); return true; } - - @Nullable - static Drawable loadSenderAvatar(@NonNull final Context context, @Nullable final Icon icon) { - Objects.requireNonNull(context); - if (icon == null) return null; - try { - if (icon.getType() == Icon.TYPE_URI - || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) { - context.grantUriPermission(context.getPackageName(), - icon.getUri(), Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - return icon.loadDrawable(context); - } catch (Exception e) { - Log.w(TAG, "loadSenderAvatar failed: " + e.getMessage()); - return null; - } - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/ContextUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/ContextUtils.kt new file mode 100644 index 000000000000..0b36f452348a --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/ContextUtils.kt @@ -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. + */ + +package com.android.wm.shell.bubbles + +import android.content.Context +import android.view.View +import android.view.WindowManagerPolicyConstants +import com.android.internal.R + +/** Simplifies accessing context fields. */ +object ContextUtils { + + /** Gets navigation mode. */ + @JvmStatic + val Context.navigationMode: Int + get() = resources.getInteger(R.integer.config_navBarInteractionMode) + + /** Returns whether the navigation mode is gestures. */ + @JvmStatic + val Context.isGestureNavigationMode: Boolean + get() = navigationMode == WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL + + /** Returns whether layout direction is rtl. */ + @JvmStatic + val Context.isRtl: Boolean + get() = resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL +} 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 ec235a5d84ab..2a9001728cc2 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 @@ -353,6 +353,11 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView if (isDragging != mIsDragging) { mIsDragging = isDragging; updateSamplingState(); + + if (isDragging && mPositioner.isImeVisible()) { + // Hide the IME when dragging begins + mManager.hideCurrentInputMethod(); + } } } 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 0047ec503504..38087c066918 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 @@ -157,6 +157,14 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } } + private void dispatchImeRequested(int displayId, boolean isRequested) { + synchronized (mPositionProcessors) { + for (ImePositionProcessor pp : mPositionProcessors) { + pp.onImeRequested(displayId, isRequested); + } + } + } + @ImePositionProcessor.ImeAnimationFlags private int dispatchStartPositioning(int displayId, int hiddenTop, int shownTop, boolean show, boolean isFloating, SurfaceControl.Transaction t) { @@ -398,6 +406,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged public void setImeInputTargetRequestedVisibility(boolean visible) { if (android.view.inputmethod.Flags.refactorInsetsController()) { mImeRequestedVisible = visible; + dispatchImeRequested(mDisplayId, mImeRequestedVisible); + // In the case that the IME becomes visible, but we have the control with leash // already (e.g., when focussing an editText in activity B, while and editText in // activity A is focussed), we will not get a call of #insetsControlChanged, and @@ -446,6 +456,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged if (imeSource == null || mImeSourceControl == null) { return; } + // TODO(b/353463205): For hide: this still has the statsToken from the previous show + // request final var statsToken = mImeSourceControl.getImeStatsToken(); startAnimation(show, forceRestart, statsToken); @@ -706,6 +718,14 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } /** + * Called when the IME was requested by an app + * + * @param isRequested {@code true} if the IME was requested to be visible + */ + default void onImeRequested(int displayId, boolean isRequested) { + } + + /** * Called when the IME position is starting to animate. * * @param hiddenTop The y position of the top of the IME surface when it is hidden. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java index 4b55fd0f5527..83ffaf473999 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java @@ -1106,6 +1106,11 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange default void onDoubleTappedDivider() { } + /** + * Sets the excludedInsetsTypes for the IME in the root WindowContainer. + */ + void setExcludeImeInsets(boolean exclude); + /** Returns split position of the token. */ @SplitPosition int getSplitItemPosition(WindowContainerToken token); @@ -1305,6 +1310,14 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } @Override + public void onImeRequested(int displayId, boolean isRequested) { + if (displayId != mDisplayId) return; + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "IME was set to requested=%s", + isRequested); + mSplitLayoutHandler.setExcludeImeInsets(true); + } + + @Override public int onImeStartPositioning(int displayId, int hiddenTop, int shownTop, boolean showing, boolean isFloating, SurfaceControl.Transaction t) { if (displayId != mDisplayId || !mInitialized) { @@ -1356,6 +1369,12 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange setDividerInteractive(!mImeShown || !mHasImeFocus || isFloating, true, "onImeStartPositioning"); + if (android.view.inputmethod.Flags.refactorInsetsController()) { + if (mImeShown) { + mSplitLayoutHandler.setExcludeImeInsets(false); + } + } + return mTargetYOffset != mLastYOffset ? IME_ANIMATION_NO_ALPHA : 0; } @@ -1374,6 +1393,16 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange "Split IME animation ending, canceled=%b", cancel); onProgress(1.0f); mSplitLayoutHandler.onLayoutPositionChanging(SplitLayout.this); + if (android.view.inputmethod.Flags.refactorInsetsController()) { + if (!mImeShown) { + // The IME hide animation is started immediately and at that point, the IME + // insets are not yet set to hidden. Therefore only resetting the + // excludedTypes at the end of the animation. Note: InsetsPolicy will only + // set the IME height to zero, when it is visible. When it becomes invisible, + // we dispatch the insets (the height there is zero as well) + mSplitLayoutHandler.setExcludeImeInsets(false); + } + } } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java index 4227a6e2903f..2a5a519272c7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java @@ -87,7 +87,7 @@ import com.android.wm.shell.compatui.impl.DefaultCompatUIHandler; import com.android.wm.shell.compatui.impl.DefaultCompatUIRepository; import com.android.wm.shell.compatui.impl.DefaultComponentIdGenerator; import com.android.wm.shell.desktopmode.DesktopMode; -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.displayareahelper.DisplayAreaHelper; import com.android.wm.shell.displayareahelper.DisplayAreaHelperController; @@ -267,7 +267,7 @@ public abstract class WMShellBaseModule { Lazy<CompatUIShellCommandHandler> compatUIShellCommandHandler, Lazy<AccessibilityManager> accessibilityManager, CompatUIRepository compatUIRepository, - Optional<DesktopModeTaskRepository> desktopModeTaskRepository, + Optional<DesktopRepository> desktopRepository, @NonNull CompatUIState compatUIState, @NonNull CompatUIComponentIdGenerator componentIdGenerator, @NonNull CompatUIComponentFactory compatUIComponentFactory, @@ -281,7 +281,7 @@ public abstract class WMShellBaseModule { componentIdGenerator, compatUIComponentFactory, mainExecutor)); } final IntPredicate inDesktopModePredicate = - desktopModeTaskRepository.<IntPredicate>map(modeTaskRepository -> displayId -> + desktopRepository.<IntPredicate>map(modeTaskRepository -> displayId -> modeTaskRepository.getVisibleTaskCount(displayId) > 0) .orElseGet(() -> displayId -> false); return Optional.of( @@ -707,14 +707,14 @@ public abstract class WMShellBaseModule { ShellCommandHandler shellCommandHandler, TaskStackListenerImpl taskStackListener, ActivityTaskManager activityTaskManager, - Optional<DesktopModeTaskRepository> desktopModeTaskRepository, + Optional<DesktopRepository> desktopRepository, TaskStackTransitionObserver taskStackTransitionObserver, @ShellMainThread ShellExecutor mainExecutor ) { return Optional.ofNullable( RecentTasksController.create(context, shellInit, shellController, shellCommandHandler, taskStackListener, activityTaskManager, - desktopModeTaskRepository, taskStackTransitionObserver, mainExecutor)); + desktopRepository, taskStackTransitionObserver, mainExecutor)); } @BindsOptionalOf @@ -1003,16 +1003,16 @@ public abstract class WMShellBaseModule { @BindsOptionalOf @DynamicOverride - abstract DesktopModeTaskRepository optionalDesktopModeTaskRepository(); + abstract DesktopRepository optionalDesktopRepository(); @WMSingleton @Provides - static Optional<DesktopModeTaskRepository> provideDesktopTaskRepository(Context context, - @DynamicOverride Optional<Lazy<DesktopModeTaskRepository>> desktopModeTaskRepository) { + static Optional<DesktopRepository> provideDesktopRepository(Context context, + @DynamicOverride Optional<Lazy<DesktopRepository>> desktopRepository) { // Use optional-of-lazy for the dependency that this provider relies on. // Lazy ensures that this provider will not be the cause the dependency is created // when it will not be returned due to the condition below. - return desktopModeTaskRepository.flatMap((lazy) -> { + return desktopRepository.flatMap((lazy) -> { if (DesktopModeStatus.canEnterDesktopMode(context)) { return Optional.of(lazy.get()); } 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 8ce3884d7477..79c31e01e365 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 @@ -65,14 +65,16 @@ import com.android.wm.shell.dagger.pip.PipModule; import com.android.wm.shell.desktopmode.CloseDesktopTaskTransitionHandler; import com.android.wm.shell.desktopmode.DefaultDragToDesktopTransitionHandler; import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler; +import com.android.wm.shell.desktopmode.DesktopFullImmersiveTransitionHandler; import com.android.wm.shell.desktopmode.DesktopMixedTransitionHandler; import com.android.wm.shell.desktopmode.DesktopModeDragAndDropTransitionHandler; import com.android.wm.shell.desktopmode.DesktopModeEventLogger; import com.android.wm.shell.desktopmode.DesktopModeLoggerTransitionObserver; -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.desktopmode.DesktopTasksLimiter; import com.android.wm.shell.desktopmode.DesktopTasksTransitionObserver; +import com.android.wm.shell.desktopmode.DesktopTaskChangeListener; import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler; import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler; import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler; @@ -90,6 +92,7 @@ import com.android.wm.shell.freeform.FreeformComponents; import com.android.wm.shell.freeform.FreeformTaskListener; import com.android.wm.shell.freeform.FreeformTaskTransitionHandler; import com.android.wm.shell.freeform.FreeformTaskTransitionObserver; +import com.android.wm.shell.freeform.TaskChangeListener; import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; import com.android.wm.shell.freeform.FreeformTaskTransitionStarterInitializer; import com.android.wm.shell.keyguard.KeyguardTransitionHandler; @@ -245,7 +248,7 @@ public abstract class WMShellModule { IWindowManager windowManager, ShellCommandHandler shellCommandHandler, ShellTaskOrganizer taskOrganizer, - @DynamicOverride DesktopModeTaskRepository desktopRepository, + @DynamicOverride DesktopRepository desktopRepository, DisplayController displayController, ShellController shellController, DisplayInsetsController displayInsetsController, @@ -352,7 +355,8 @@ public abstract class WMShellModule { Context context, ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, - Optional<DesktopModeTaskRepository> desktopModeTaskRepository, + Optional<DesktopRepository> desktopRepository, + Optional<DesktopTasksController> desktopTasksController, LaunchAdjacentController launchAdjacentController, WindowDecorViewModel windowDecorViewModel) { // TODO(b/238217847): Temporarily add this check here until we can remove the dynamic @@ -361,7 +365,8 @@ public abstract class WMShellModule { ? shellInit : null; return new FreeformTaskListener(context, init, shellTaskOrganizer, - desktopModeTaskRepository, launchAdjacentController, windowDecorViewModel); + desktopRepository, desktopTasksController, launchAdjacentController, + windowDecorViewModel); } @WMSingleton @@ -384,9 +389,12 @@ public abstract class WMShellModule { Context context, ShellInit shellInit, Transitions transitions, - WindowDecorViewModel windowDecorViewModel) { + Optional<DesktopFullImmersiveTransitionHandler> desktopImmersiveTransitionHandler, + WindowDecorViewModel windowDecorViewModel, + Optional<TaskChangeListener> taskChangeListener) { return new FreeformTaskTransitionObserver( - context, shellInit, transitions, windowDecorViewModel); + context, shellInit, transitions, desktopImmersiveTransitionHandler, + windowDecorViewModel, taskChangeListener); } @WMSingleton @@ -410,7 +418,6 @@ public abstract class WMShellModule { // One handed mode // - // Needs the shell main handler for ContentObserver callbacks @WMSingleton @Provides @@ -620,7 +627,8 @@ public abstract class WMShellModule { DesktopModeDragAndDropTransitionHandler desktopModeDragAndDropTransitionHandler, ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler, DragToDesktopTransitionHandler dragToDesktopTransitionHandler, - @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository, + @DynamicOverride DesktopRepository desktopRepository, + Optional<DesktopFullImmersiveTransitionHandler> desktopFullImmersiveTransitionHandler, DesktopModeLoggerTransitionObserver desktopModeLoggerTransitionObserver, LaunchAdjacentController launchAdjacentController, RecentsTransitionHandler recentsTransitionHandler, @@ -636,7 +644,8 @@ public abstract class WMShellModule { returnToDragStartAnimator, enterDesktopTransitionHandler, exitDesktopTransitionHandler, desktopModeDragAndDropTransitionHandler, toggleResizeDesktopTaskTransitionHandler, - dragToDesktopTransitionHandler, desktopModeTaskRepository, + dragToDesktopTransitionHandler, desktopFullImmersiveTransitionHandler.get(), + desktopRepository, desktopModeLoggerTransitionObserver, launchAdjacentController, recentsTransitionHandler, multiInstanceHelper, mainExecutor, desktopTasksLimiter, recentTasksController.orElse(null), interactionJankMonitor, mainHandler); @@ -644,10 +653,20 @@ public abstract class WMShellModule { @WMSingleton @Provides + static Optional<TaskChangeListener> provideDesktopTaskChangeListener(Context context) { + if (Flags.enableWindowingTransitionHandlersObservers() && + DesktopModeStatus.canEnterDesktopMode(context)) { + return Optional.of(new DesktopTaskChangeListener()); + } + return Optional.empty(); + } + + @WMSingleton + @Provides static Optional<DesktopTasksLimiter> provideDesktopTasksLimiter( Context context, Transitions transitions, - @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository, + @DynamicOverride DesktopRepository desktopRepository, ShellTaskOrganizer shellTaskOrganizer, InteractionJankMonitor interactionJankMonitor, @ShellMainThread Handler handler) { @@ -660,7 +679,7 @@ public abstract class WMShellModule { return Optional.of( new DesktopTasksLimiter( transitions, - desktopModeTaskRepository, + desktopRepository, shellTaskOrganizer, maxTaskLimit, interactionJankMonitor, @@ -671,6 +690,19 @@ public abstract class WMShellModule { @WMSingleton @Provides + static Optional<DesktopFullImmersiveTransitionHandler> provideDesktopImmersiveHandler( + Context context, + Transitions transitions, + @DynamicOverride DesktopRepository desktopRepository) { + if (DesktopModeStatus.canEnterDesktopMode(context)) { + return Optional.of( + new DesktopFullImmersiveTransitionHandler(transitions, desktopRepository)); + } + return Optional.empty(); + } + + @WMSingleton + @Provides static ReturnToDragStartAnimator provideReturnToDragStartAnimator( Context context, InteractionJankMonitor interactionJankMonitor) { return new ReturnToDragStartAnimator(context, interactionJankMonitor); @@ -739,13 +771,14 @@ public abstract class WMShellModule { @WMSingleton @Provides @DynamicOverride - static DesktopModeTaskRepository provideDesktopModeTaskRepository( + + static DesktopRepository provideDesktopRepository( Context context, ShellInit shellInit, DesktopPersistentRepository desktopPersistentRepository, @ShellMainThread CoroutineScope mainScope ) { - return new DesktopModeTaskRepository(context, shellInit, desktopPersistentRepository, + return new DesktopRepository(context, shellInit, desktopPersistentRepository, mainScope); } @@ -757,12 +790,12 @@ public abstract class WMShellModule { ShellTaskOrganizer shellTaskOrganizer, TaskStackListenerImpl taskStackListener, ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler, - @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository + @DynamicOverride DesktopRepository desktopRepository ) { if (DesktopModeStatus.canEnterDesktopMode(context)) { return Optional.of(new DesktopActivityOrientationChangeHandler( context, shellInit, shellTaskOrganizer, taskStackListener, - toggleResizeDesktopTaskTransitionHandler, desktopModeTaskRepository)); + toggleResizeDesktopTaskTransitionHandler, desktopRepository)); } return Optional.empty(); } @@ -771,12 +804,12 @@ public abstract class WMShellModule { @Provides static Optional<DesktopTasksTransitionObserver> provideDesktopTasksTransitionObserver( Context context, - Optional<DesktopModeTaskRepository> desktopModeTaskRepository, + Optional<DesktopRepository> desktopRepository, Transitions transitions, ShellTaskOrganizer shellTaskOrganizer, ShellInit shellInit ) { - return desktopModeTaskRepository.flatMap(repository -> + return desktopRepository.flatMap(repository -> Optional.of(new DesktopTasksTransitionObserver( context, repository, transitions, shellTaskOrganizer, shellInit)) ); @@ -787,7 +820,7 @@ public abstract class WMShellModule { static Optional<DesktopMixedTransitionHandler> provideDesktopMixedTransitionHandler( Context context, Transitions transitions, - @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository, + @DynamicOverride DesktopRepository desktopRepository, FreeformTaskTransitionHandler freeformTaskTransitionHandler, CloseDesktopTaskTransitionHandler closeDesktopTaskTransitionHandler, InteractionJankMonitor interactionJankMonitor, @@ -801,7 +834,7 @@ public abstract class WMShellModule { new DesktopMixedTransitionHandler( context, transitions, - desktopModeTaskRepository, + desktopRepository, freeformTaskTransitionHandler, closeDesktopTaskTransitionHandler, interactionJankMonitor, @@ -851,10 +884,11 @@ public abstract class WMShellModule { static DesktopWindowingEducationTooltipController provideDesktopWindowingEducationTooltipController( Context context, - AdditionalSystemViewContainer.Factory additionalSystemViewContainerFactory + AdditionalSystemViewContainer.Factory additionalSystemViewContainerFactory, + DisplayController displayController ) { return new DesktopWindowingEducationTooltipController(context, - additionalSystemViewContainerFactory); + additionalSystemViewContainerFactory, displayController); } @OptIn(markerClass = ExperimentalCoroutinesApi.class) 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 3464fef07f33..3508ecee6d51 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 @@ -77,10 +77,12 @@ public abstract class Pip2Module { PipTaskListener pipTaskListener, @NonNull PipScheduler pipScheduler, @NonNull PipTransitionState pipStackListenerController, + @NonNull PipDisplayLayoutState pipDisplayLayoutState, @NonNull PipUiStateChangeController pipUiStateChangeController) { return new PipTransition(context, shellInit, shellTaskOrganizer, transitions, pipBoundsState, null, pipBoundsAlgorithm, pipTaskListener, - pipScheduler, pipStackListenerController, pipUiStateChangeController); + pipScheduler, pipStackListenerController, pipDisplayLayoutState, + pipUiStateChangeController); } @WMSingleton @@ -125,11 +127,9 @@ public abstract class Pip2Module { @Provides static PipScheduler providePipScheduler(Context context, PipBoundsState pipBoundsState, - PhonePipMenuController pipMenuController, @ShellMainThread ShellExecutor mainExecutor, PipTransitionState pipTransitionState) { - return new PipScheduler(context, pipBoundsState, pipMenuController, - mainExecutor, pipTransitionState); + return new PipScheduler(context, pipBoundsState, mainExecutor, pipTransitionState); } @WMSingleton @@ -138,10 +138,13 @@ public abstract class Pip2Module { PipBoundsState pipBoundsState, PipMediaController pipMediaController, SystemWindows systemWindows, PipUiEventLogger pipUiEventLogger, + PipTaskListener pipTaskListener, + @NonNull PipTransitionState pipTransitionState, @ShellMainThread ShellExecutor mainExecutor, @ShellMainThread Handler mainHandler) { return new PhonePipMenuController(context, pipBoundsState, pipMediaController, - systemWindows, pipUiEventLogger, mainExecutor, mainHandler); + systemWindows, pipUiEventLogger, pipTaskListener, pipTransitionState, mainExecutor, + mainHandler); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandler.kt index 59e006879da8..606aa6cd3353 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandler.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandler.kt @@ -39,7 +39,7 @@ class DesktopActivityOrientationChangeHandler( private val shellTaskOrganizer: ShellTaskOrganizer, private val taskStackListener: TaskStackListenerImpl, private val resizeHandler: ToggleResizeDesktopTaskTransitionHandler, - private val taskRepository: DesktopModeTaskRepository, + private val taskRepository: DesktopRepository, ) { init { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandler.kt new file mode 100644 index 000000000000..f749aa1edd92 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandler.kt @@ -0,0 +1,245 @@ +/* + * 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.animation.RectEvaluator +import android.animation.ValueAnimator +import android.app.ActivityManager.RunningTaskInfo +import android.graphics.Rect +import android.os.IBinder +import android.view.SurfaceControl +import android.view.WindowManager.TRANSIT_CHANGE +import android.view.animation.DecelerateInterpolator +import android.window.TransitionInfo +import android.window.TransitionRequestInfo +import android.window.WindowContainerTransaction +import androidx.core.animation.addListener +import com.android.internal.protolog.ProtoLog +import com.android.wm.shell.protolog.ShellProtoLogGroup +import com.android.wm.shell.transition.Transitions +import com.android.wm.shell.transition.Transitions.TransitionHandler +import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener + +/** + * A [TransitionHandler] to move a task in/out of desktop's full immersive state where the task + * remains freeform while being able to take fullscreen bounds and have its App Header visibility + * be transient below the status bar like in fullscreen immersive mode. + */ +class DesktopFullImmersiveTransitionHandler( + private val transitions: Transitions, + private val desktopRepository: DesktopRepository, + private val transactionSupplier: () -> SurfaceControl.Transaction, +) : TransitionHandler { + + constructor( + transitions: Transitions, + desktopRepository: DesktopRepository, + ) : this(transitions, desktopRepository, { SurfaceControl.Transaction() }) + + private var state: TransitionState? = null + + /** Whether there is an immersive transition that hasn't completed yet. */ + private val inProgress: Boolean + get() = state != null + + private val rectEvaluator = RectEvaluator() + + /** A listener to invoke on animation changes during entry/exit. */ + var onTaskResizeAnimationListener: OnTaskResizeAnimationListener? = null + + /** Starts a transition to enter full immersive state inside the desktop. */ + fun enterImmersive(taskInfo: RunningTaskInfo, wct: WindowContainerTransaction) { + if (inProgress) { + ProtoLog.v( + ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "FullImmersive: cannot start entry because transition already in progress." + ) + return + } + + val transition = transitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ this) + state = TransitionState( + transition = transition, + displayId = taskInfo.displayId, + taskId = taskInfo.taskId, + direction = Direction.ENTER + ) + } + + fun exitImmersive(taskInfo: RunningTaskInfo, wct: WindowContainerTransaction) { + if (inProgress) { + ProtoLog.v( + ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "$TAG: cannot start exit because transition already in progress." + ) + return + } + + val transition = transitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ this) + state = TransitionState( + transition = transition, + displayId = taskInfo.displayId, + taskId = taskInfo.taskId, + direction = Direction.EXIT + ) + } + + override fun startAnimation( + transition: IBinder, + info: TransitionInfo, + startTransaction: SurfaceControl.Transaction, + finishTransaction: SurfaceControl.Transaction, + finishCallback: Transitions.TransitionFinishCallback + ): Boolean { + val state = requireState() + if (transition != state.transition) return false + animateResize( + transitionState = state, + info = info, + startTransaction = startTransaction, + finishTransaction = finishTransaction, + finishCallback = finishCallback + ) + return true + } + + private fun animateResize( + transitionState: TransitionState, + info: TransitionInfo, + startTransaction: SurfaceControl.Transaction, + finishTransaction: SurfaceControl.Transaction, + finishCallback: Transitions.TransitionFinishCallback + ) { + val change = info.changes.first { c -> + val taskInfo = c.taskInfo + return@first taskInfo != null && taskInfo.taskId == transitionState.taskId + } + val leash = change.leash + val startBounds = change.startAbsBounds + val endBounds = change.endAbsBounds + + val updateTransaction = transactionSupplier() + ValueAnimator.ofObject(rectEvaluator, startBounds, endBounds).apply { + duration = FULL_IMMERSIVE_ANIM_DURATION_MS + interpolator = DecelerateInterpolator() + addListener( + onStart = { + startTransaction + .setPosition(leash, startBounds.left.toFloat(), startBounds.top.toFloat()) + .setWindowCrop(leash, startBounds.width(), startBounds.height()) + .show(leash) + onTaskResizeAnimationListener + ?.onAnimationStart(transitionState.taskId, startTransaction, startBounds) + ?: startTransaction.apply() + }, + onEnd = { + finishTransaction + .setPosition(leash, endBounds.left.toFloat(), endBounds.top.toFloat()) + .setWindowCrop(leash, endBounds.width(), endBounds.height()) + .apply() + onTaskResizeAnimationListener?.onAnimationEnd(transitionState.taskId) + finishCallback.onTransitionFinished(null /* wct */) + clearState() + } + ) + addUpdateListener { animation -> + val rect = animation.animatedValue as Rect + updateTransaction + .setPosition(leash, rect.left.toFloat(), rect.top.toFloat()) + .setWindowCrop(leash, rect.width(), rect.height()) + .apply() + onTaskResizeAnimationListener + ?.onBoundsChange(transitionState.taskId, updateTransaction, rect) + ?: updateTransaction.apply() + } + start() + } + } + + override fun handleRequest( + transition: IBinder, + request: TransitionRequestInfo + ): WindowContainerTransaction? = null + + override fun onTransitionConsumed( + transition: IBinder, + aborted: Boolean, + finishTransaction: SurfaceControl.Transaction? + ) { + val state = this.state ?: return + if (transition == state.transition && aborted) { + clearState() + } + super.onTransitionConsumed(transition, aborted, finishTransaction) + } + + /** + * Called when any transition in the system is ready to play. This is needed to update the + * repository state before window decorations are drawn (which happens immediately after + * |onTransitionReady|, before this transition actually animates) because drawing decorations + * depends in whether the task is in full immersive state or not. + */ + fun onTransitionReady(transition: IBinder) { + val state = this.state ?: return + // TODO: b/369443668 - this assumes invoking the exit transition is the only way to exit + // immersive, which isn't realistic. The app could crash, the user could dismiss it from + // overview, etc. This (or its caller) should search all transitions to look for any + // immersive task exiting that state to keep the repository properly updated. + if (transition == state.transition) { + when (state.direction) { + Direction.ENTER -> { + desktopRepository.setTaskInFullImmersiveState( + displayId = state.displayId, + taskId = state.taskId, + immersive = true + ) + } + Direction.EXIT -> { + desktopRepository.setTaskInFullImmersiveState( + displayId = state.displayId, + taskId = state.taskId, + immersive = false + ) + } + } + } + } + + private fun clearState() { + state = null + } + + private fun requireState(): TransitionState = + state ?: error("Expected non-null transition state") + + /** The state of the currently running transition. */ + private data class TransitionState( + val transition: IBinder, + val displayId: Int, + val taskId: Int, + val direction: Direction + ) + + private enum class Direction { + ENTER, EXIT + } + + private companion object { + private const val TAG = "FullImmersiveHandler" + + private const val FULL_IMMERSIVE_ANIM_DURATION_MS = 336L + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt index ec3f8c5fc2f8..435019929cbd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt @@ -40,7 +40,7 @@ import com.android.wm.shell.transition.Transitions class DesktopMixedTransitionHandler( private val context: Context, private val transitions: Transitions, - private val desktopTaskRepository: DesktopModeTaskRepository, + private val desktopRepository: DesktopRepository, private val freeformTaskTransitionHandler: FreeformTaskTransitionHandler, private val closeDesktopTaskTransitionHandler: CloseDesktopTaskTransitionHandler, private val interactionJankMonitor: InteractionJankMonitor, @@ -138,7 +138,7 @@ class DesktopMixedTransitionHandler( private fun isLastDesktopTask(change: TransitionInfo.Change): Boolean = change.taskInfo?.let { - desktopTaskRepository.getActiveNonMinimizedTaskCount(it.displayId) == 1 + desktopRepository.getActiveNonMinimizedTaskCount(it.displayId) == 1 } ?: false private fun findCloseDesktopTaskChange(info: TransitionInfo): TransitionInfo.Change? { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java index cca750014fc1..73e55b2c4792 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java @@ -36,7 +36,7 @@ public interface DesktopMode { * @param listener the listener to add. * @param callbackExecutor the executor to call the listener on. */ - void addVisibleTasksListener(DesktopModeTaskRepository.VisibleTasksListener listener, + void addVisibleTasksListener(DesktopRepository.VisibleTasksListener listener, Executor callbackExecutor); /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt index 02cbe01d0a03..5a277316ffd4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt @@ -19,6 +19,8 @@ package com.android.wm.shell.desktopmode import com.android.internal.annotations.VisibleForTesting import com.android.internal.protolog.ProtoLog import com.android.internal.util.FrameworkStatsLog +import com.android.window.flags.Flags +import com.android.wm.shell.EventLogTags import com.android.wm.shell.protolog.ShellProtoLogGroup /** Event logger for logging desktop mode session events */ @@ -41,6 +43,7 @@ class DesktopModeEventLogger { /* exitReason */ 0, /* session_id */ sessionId ) + EventLogTags.writeWmShellEnterDesktopMode(enterReason.reason, sessionId) } /** @@ -61,6 +64,7 @@ class DesktopModeEventLogger { /* exitReason */ exitReason.reason, /* session_id */ sessionId ) + EventLogTags.writeWmShellExitDesktopMode(exitReason.reason, sessionId) } /** @@ -76,7 +80,8 @@ class DesktopModeEventLogger { ) logTaskUpdate( FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_ADDED, - sessionId, taskUpdate) + sessionId, taskUpdate + ) } /** @@ -92,7 +97,8 @@ class DesktopModeEventLogger { ) logTaskUpdate( FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_REMOVED, - sessionId, taskUpdate) + sessionId, taskUpdate + ) } /** @@ -108,7 +114,46 @@ class DesktopModeEventLogger { ) logTaskUpdate( FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED, - sessionId, taskUpdate) + sessionId, taskUpdate + ) + } + + /** + * Logs that a task resize event is starting with [taskSizeUpdate] within a + * Desktop mode [sessionId]. + */ + fun logTaskResizingStarted(sessionId: Int, taskSizeUpdate: TaskSizeUpdate) { + if (!Flags.enableResizingMetrics()) return + + ProtoLog.v( + ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "DesktopModeLogger: Logging task resize is starting, session: %s taskId: %s", + sessionId, + taskSizeUpdate.instanceId + ) + logTaskSizeUpdated( + FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__START_RESIZING_STAGE, + sessionId, taskSizeUpdate + ) + } + + /** + * Logs that a task resize event is ending with [taskSizeUpdate] within a + * Desktop mode [sessionId]. + */ + fun logTaskResizingEnded(sessionId: Int, taskSizeUpdate: TaskSizeUpdate) { + if (!Flags.enableResizingMetrics()) return + + ProtoLog.v( + ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "DesktopModeLogger: Logging task resize is ending, session: %s taskId: %s", + sessionId, + taskSizeUpdate.instanceId + ) + logTaskSizeUpdated( + FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__END_RESIZING_STAGE, + sessionId, taskSizeUpdate + ) } private fun logTaskUpdate(taskEvent: Int, sessionId: Int, taskUpdate: TaskUpdate) { @@ -135,6 +180,56 @@ class DesktopModeEventLogger { /* visible_task_count */ taskUpdate.visibleTaskCount ) + EventLogTags.writeWmShellDesktopModeTaskUpdate( + /* task_event */ + taskEvent, + /* instance_id */ + taskUpdate.instanceId, + /* uid */ + taskUpdate.uid, + /* task_height */ + taskUpdate.taskHeight, + /* task_width */ + taskUpdate.taskWidth, + /* task_x */ + taskUpdate.taskX, + /* task_y */ + taskUpdate.taskY, + /* session_id */ + sessionId, + taskUpdate.minimizeReason?.reason ?: UNSET_MINIMIZE_REASON, + taskUpdate.unminimizeReason?.reason ?: UNSET_UNMINIMIZE_REASON, + /* visible_task_count */ + taskUpdate.visibleTaskCount + ) + } + + private fun logTaskSizeUpdated( + resizingStage: Int, + sessionId: Int, + taskSizeUpdate: TaskSizeUpdate + ) { + FrameworkStatsLog.write( + DESKTOP_MODE_TASK_SIZE_UPDATED_ATOM_ID, + /* resize_trigger */ + taskSizeUpdate.resizeTrigger?.trigger ?: ResizeTrigger.UNKNOWN_RESIZE_TRIGGER.trigger, + /* resizing_stage */ + resizingStage, + /* input_method */ + taskSizeUpdate.inputMethod?.method ?: InputMethod.UNKNOWN_INPUT_METHOD.method, + /* desktop_mode_session_id */ + sessionId, + /* instance_id */ + taskSizeUpdate.instanceId, + /* uid */ + taskSizeUpdate.uid, + /* task_height */ + taskSizeUpdate.taskHeight, + /* task_width */ + taskSizeUpdate.taskWidth, + /* display_area */ + taskSizeUpdate.displayArea + ) } companion object { @@ -163,13 +258,35 @@ class DesktopModeEventLogger { val visibleTaskCount: Int, ) + /** + * Describes a task size update (resizing, snapping or maximizing to + * stable bounds). + * + * @property resizeTrigger the trigger for task resize + * @property inputMethod the input method for resizing this task + * @property instanceId instance id of the task + * @property uid uid of the app associated with the task + * @property taskHeight height of the task in dp + * @property taskWidth width of the task in dp + * @property displayArea the display size of the screen in dp + */ + data class TaskSizeUpdate( + val resizeTrigger: ResizeTrigger? = null, + val inputMethod: InputMethod? = null, + val instanceId: Int, + val uid: Int, + val taskHeight: Int, + val taskWidth: Int, + val displayArea: Int, + ) + // Default value used when the task was not minimized. @VisibleForTesting const val UNSET_MINIMIZE_REASON = FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__UNSET_MINIMIZE /** The reason a task was minimized. */ - enum class MinimizeReason (val reason: Int) { + enum class MinimizeReason(val reason: Int) { TASK_LIMIT( FrameworkStatsLog .DESKTOP_MODE_SESSION_TASK_UPDATE__MINIMIZE_REASON__MINIMIZE_TASK_LIMIT @@ -186,7 +303,7 @@ class DesktopModeEventLogger { FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__UNMINIMIZE_REASON__UNSET_UNMINIMIZE /** The reason a task was unminimized. */ - enum class UnminimizeReason (val reason: Int) { + enum class UnminimizeReason(val reason: Int) { UNKNOWN( FrameworkStatsLog .DESKTOP_MODE_SESSION_TASK_UPDATE__UNMINIMIZE_REASON__UNMINIMIZE_UNKNOWN @@ -250,8 +367,88 @@ class DesktopModeEventLogger { SCREEN_OFF(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__SCREEN_OFF) } + /** + * Enum ResizeTrigger mapped to the ResizeTrigger definition in + * stats/atoms/desktopmode/desktopmode_extensions_atoms.proto + */ + enum class ResizeTrigger(val trigger: Int) { + UNKNOWN_RESIZE_TRIGGER( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER + ), + CORNER( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__CORNER_RESIZE_TRIGGER + ), + EDGE( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__EDGE_RESIZE_TRIGGER + ), + TILING_DIVIDER( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__TILING_DIVIDER_RESIZE_TRIGGER + ), + MAXIMIZE_BUTTON( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__MAXIMIZE_BUTTON_RESIZE_TRIGGER + ), + DOUBLE_TAP_APP_HEADER( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__DOUBLE_TAP_APP_HEADER_RESIZE_TRIGGER + ), + DRAG_LEFT( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__DRAG_LEFT_RESIZE_TRIGGER + ), + DRAG_RIGHT( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__DRAG_RIGHT_RESIZE_TRIGGER + ), + SNAP_LEFT_MENU( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__SNAP_LEFT_MENU_RESIZE_TRIGGER + ), + SNAP_RIGHT_MENU( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__SNAP_RIGHT_MENU_RESIZE_TRIGGER + ), + } + + /** + * Enum InputMethod mapped to the InputMethod definition in + * stats/atoms/desktopmode/desktopmode_extensions_atoms.proto + */ + enum class InputMethod(val method: Int) { + UNKNOWN_INPUT_METHOD( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__UNKNOWN_INPUT_METHOD + ), + TOUCH( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__TOUCH_INPUT_METHOD + ), + STYLUS( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__STYLUS_INPUT_METHOD + ), + MOUSE( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__MOUSE_INPUT_METHOD + ), + TOUCHPAD( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__TOUCHPAD_INPUT_METHOD + ), + KEYBOARD( + FrameworkStatsLog + .DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__KEYBOARD_INPUT_METHOD + ), + } + private const val DESKTOP_MODE_ATOM_ID = FrameworkStatsLog.DESKTOP_MODE_UI_CHANGED private const val DESKTOP_MODE_TASK_UPDATE_ATOM_ID = FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE + private const val DESKTOP_MODE_TASK_SIZE_UPDATED_ATOM_ID = + FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt index 063747494a82..b8507e3b2764 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt @@ -68,9 +68,7 @@ class DesktopModeLoggerTransitionObserver( private val idSequence: InstanceIdSequence by lazy { InstanceIdSequence(Int.MAX_VALUE) } init { - if ( - Transitions.ENABLE_SHELL_TRANSITIONS && DesktopModeStatus.canEnterDesktopMode(context) - ) { + if (DesktopModeStatus.canEnterDesktopMode(context)) { shellInit.addInitCallback(this::onInit, this) } } @@ -101,6 +99,9 @@ class DesktopModeLoggerTransitionObserver( fun onInit() { transitions.registerObserver(this) + SystemProperties.set( + VISIBLE_TASKS_COUNTER_SYSTEM_PROPERTY, + VISIBLE_TASKS_COUNTER_SYSTEM_PROPERTY_DEFAULT_VALUE) } override fun onTransitionReady( @@ -441,5 +442,6 @@ class DesktopModeLoggerTransitionObserver( @VisibleForTesting const val VISIBLE_TASKS_COUNTER_SYSTEM_PROPERTY = "debug.tracing." + VISIBLE_TASKS_COUNTER_NAME + const val VISIBLE_TASKS_COUNTER_SYSTEM_PROPERTY_DEFAULT_VALUE = "0" } } 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 72619195fb3f..52b92a89abdf 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 @@ -21,6 +21,12 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; +import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR; +import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR; +import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR; +import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR; +import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.RectEvaluator; @@ -125,7 +131,7 @@ public class DesktopModeVisualIndicator { mContext = context; mTaskSurface = taskSurface; mRootTdaOrganizer = taskDisplayAreaOrganizer; - mCurrentType = IndicatorType.NO_INDICATOR; + mCurrentType = NO_INDICATOR; mDragStartState = dragStartState; } @@ -136,8 +142,16 @@ public class DesktopModeVisualIndicator { @NonNull IndicatorType updateIndicatorType(PointF inputCoordinates) { final DisplayLayout layout = mDisplayController.getDisplayLayout(mTaskInfo.displayId); + // Perform a quick check first: any input off the left edge of the display should be split + // left, and split right for the right edge. This is universal across all drag event types. + if (inputCoordinates.x < 0) return TO_SPLIT_LEFT_INDICATOR; + if (inputCoordinates.x > layout.width()) return TO_SPLIT_RIGHT_INDICATOR; // If we are in freeform, we don't want a visible indicator in the "freeform" drag zone. - IndicatorType result = IndicatorType.NO_INDICATOR; + // In drags not originating on a freeform caption, we should default to a TO_DESKTOP + // indicator. + IndicatorType result = mDragStartState == DragStartState.FROM_FREEFORM + ? NO_INDICATOR + : TO_DESKTOP_INDICATOR; final int transitionAreaWidth = mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.desktop_mode_transition_region_thickness); // Because drags in freeform use task position for indicator calculation, we need to @@ -149,10 +163,8 @@ public class DesktopModeVisualIndicator { captionHeight); final Region splitRightRegion = calculateSplitRightRegion(layout, transitionAreaWidth, captionHeight); - final Region toDesktopRegion = calculateToDesktopRegion(layout, splitLeftRegion, - splitRightRegion, fullscreenRegion); if (fullscreenRegion.contains((int) inputCoordinates.x, (int) inputCoordinates.y)) { - result = IndicatorType.TO_FULLSCREEN_INDICATOR; + result = TO_FULLSCREEN_INDICATOR; } if (splitLeftRegion.contains((int) inputCoordinates.x, (int) inputCoordinates.y)) { result = IndicatorType.TO_SPLIT_LEFT_INDICATOR; @@ -160,9 +172,6 @@ public class DesktopModeVisualIndicator { if (splitRightRegion.contains((int) inputCoordinates.x, (int) inputCoordinates.y)) { result = IndicatorType.TO_SPLIT_RIGHT_INDICATOR; } - if (toDesktopRegion.contains((int) inputCoordinates.x, (int) inputCoordinates.y)) { - result = IndicatorType.TO_DESKTOP_INDICATOR; - } if (mDragStartState != DragStartState.DRAGGED_INTENT) { transitionIndicator(result); } @@ -182,7 +191,7 @@ public class DesktopModeVisualIndicator { R.dimen.desktop_mode_fullscreen_region_scale); final float toFullscreenWidth = (layout.width() * toFullscreenScale); region.union(new Rect((int) ((layout.width() / 2f) - (toFullscreenWidth / 2f)), - -captionHeight, + Short.MIN_VALUE, (int) ((layout.width() / 2f) + (toFullscreenWidth / 2f)), transitionHeight)); } @@ -192,7 +201,7 @@ public class DesktopModeVisualIndicator { || mDragStartState == DragStartState.DRAGGED_INTENT ) { region.union(new Rect(0, - -captionHeight, + Short.MIN_VALUE, layout.width(), transitionHeight)); } @@ -200,21 +209,6 @@ public class DesktopModeVisualIndicator { } @VisibleForTesting - Region calculateToDesktopRegion(DisplayLayout layout, - Region splitLeftRegion, Region splitRightRegion, - Region toFullscreenRegion) { - final Region region = new Region(); - // If in desktop, we need no region. Otherwise it's the same for all windowing modes. - if (mDragStartState != DragStartState.FROM_FREEFORM) { - region.union(new Rect(0, 0, layout.width(), layout.height())); - region.op(splitLeftRegion, Region.Op.DIFFERENCE); - region.op(splitRightRegion, Region.Op.DIFFERENCE); - region.op(toFullscreenRegion, Region.Op.DIFFERENCE); - } - return region; - } - - @VisibleForTesting Region calculateSplitLeftRegion(DisplayLayout layout, int transitionEdgeWidth, int captionHeight) { final Region region = new Region(); @@ -311,7 +305,7 @@ public class DesktopModeVisualIndicator { } }); } - mCurrentType = IndicatorType.NO_INDICATOR; + mCurrentType = NO_INDICATOR; } /** @@ -322,9 +316,9 @@ public class DesktopModeVisualIndicator { if (mView == null) { createView(); } - if (mCurrentType == IndicatorType.NO_INDICATOR) { + if (mCurrentType == NO_INDICATOR) { fadeInIndicator(newType); - } else if (newType == IndicatorType.NO_INDICATOR) { + } else if (newType == NO_INDICATOR) { fadeOutIndicator(null /* finishCallback */); } else { final VisualIndicatorAnimator animator = VisualIndicatorAnimator.animateIndicatorType( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt index 985224e30a51..7b2a5d343861 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt @@ -42,8 +42,8 @@ import java.util.function.Consumer import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch -/** Tracks task data for Desktop Mode. */ -class DesktopModeTaskRepository ( +/** Tracks desktop data for Android Desktop Windowing. */ +class DesktopRepository ( private val context: Context, shellInit: ShellInit, private val persistentRepository: DesktopPersistentRepository, @@ -467,10 +467,9 @@ class DesktopModeTaskRepository ( } } - internal fun dump(pw: PrintWriter, prefix: String) { val innerPrefix = "$prefix " - pw.println("${prefix}DesktopModeTaskRepository") + pw.println("${prefix}DesktopRepository") dumpDesktopTaskData(pw, innerPrefix) pw.println("${innerPrefix}activeTasksListeners=${activeTasksListeners.size}") pw.println("${innerPrefix}visibleTasksListeners=${visibleTasksListeners.size}") @@ -512,10 +511,9 @@ class DesktopModeTaskRepository ( } companion object { - private const val TAG = "DesktopModeTaskRepository" + private const val TAG = "DesktopRepository" } } private fun <T> Iterable<T>.toDumpString(): String = joinToString(separator = ", ", prefix = "[", postfix = "]") - diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt new file mode 100644 index 000000000000..1ee2de958e55 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTaskChangeListener.kt @@ -0,0 +1,44 @@ +/* + * 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.ActivityManager.RunningTaskInfo +import com.android.wm.shell.freeform.TaskChangeListener + +/** Manages tasks handling specific to Android Desktop Mode. */ +class DesktopTaskChangeListener: TaskChangeListener { + + override fun onTaskOpening(taskInfo: RunningTaskInfo) { + // TODO: b/367268953 - Connect this with DesktopRepository. + } + + override fun onTaskChanging(taskInfo: RunningTaskInfo) { + // TODO: b/367268953 - Connect this with DesktopRepository. + } + + override fun onTaskMovingToFront(taskInfo: RunningTaskInfo) { + // TODO: b/367268953 - Connect this with DesktopRepository. + } + + override fun onTaskMovingToBack(taskInfo: RunningTaskInfo) { + // TODO: b/367268953 - Connect this with DesktopRepository. + } + + override fun onTaskClosing(taskInfo: RunningTaskInfo) { + // TODO: b/367268953 - Connect this with DesktopRepository. + } +} 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 b8bb73ba4148..b65ef6d81b13 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 @@ -73,7 +73,7 @@ import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SingleInstanceRemoteListener import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener +import com.android.wm.shell.desktopmode.DesktopRepository.VisibleTasksListener import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.DragStartState import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.DragToDesktopStateListener @@ -110,6 +110,7 @@ import com.android.wm.shell.windowdecor.OnTaskRepositionAnimationListener import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener import com.android.wm.shell.windowdecor.extension.isFullscreen import com.android.wm.shell.windowdecor.extension.isMultiWindow +import com.android.wm.shell.windowdecor.extension.requestingImmersive import java.io.PrintWriter import java.util.Optional import java.util.concurrent.Executor @@ -134,7 +135,8 @@ class DesktopTasksController( private val desktopModeDragAndDropTransitionHandler: DesktopModeDragAndDropTransitionHandler, private val toggleResizeDesktopTaskTransitionHandler: ToggleResizeDesktopTaskTransitionHandler, private val dragToDesktopTransitionHandler: DragToDesktopTransitionHandler, - private val taskRepository: DesktopModeTaskRepository, + private val immersiveTransitionHandler: DesktopFullImmersiveTransitionHandler, + private val taskRepository: DesktopRepository, private val desktopModeLoggerTransitionObserver: DesktopModeLoggerTransitionObserver, private val launchAdjacentController: LaunchAdjacentController, private val recentsTransitionHandler: RecentsTransitionHandler, @@ -231,6 +233,7 @@ class DesktopTasksController( toggleResizeDesktopTaskTransitionHandler.setOnTaskResizeAnimationListener(listener) enterDesktopTaskTransitionHandler.setOnTaskResizeAnimationListener(listener) dragToDesktopTransitionHandler.onTaskResizeAnimationListener = listener + immersiveTransitionHandler.onTaskResizeAnimationListener = listener } fun setOnTaskRepositionAnimationListener(listener: OnTaskRepositionAnimationListener) { @@ -258,17 +261,12 @@ class DesktopTasksController( val wct = WindowContainerTransaction() bringDesktopAppsToFront(displayId, wct) - if (Transitions.ENABLE_SHELL_TRANSITIONS) { - val transitionType = transitionType(remoteTransition) - val handler = - remoteTransition?.let { - OneShotRemoteHandler(transitions.mainExecutor, remoteTransition) - } - transitions.startTransition(transitionType, wct, handler).also { t -> - handler?.setTransition(t) - } - } else { - shellTaskOrganizer.applyTransaction(wct) + val transitionType = transitionType(remoteTransition) + val handler = remoteTransition?.let { + OneShotRemoteHandler(transitions.mainExecutor, remoteTransition) + } + transitions.startTransition(transitionType, wct, handler).also { t -> + handler?.setTransition(t) } } @@ -385,12 +383,8 @@ class DesktopTasksController( bringDesktopAppsToFrontBeforeShowingNewTask(task.displayId, wct, task.taskId) addMoveToDesktopChanges(wct, task) - if (Transitions.ENABLE_SHELL_TRANSITIONS) { - val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) - addPendingMinimizeTransition(transition, taskToMinimize) - } else { - shellTaskOrganizer.applyTransaction(wct) - } + val transition = enterDesktopTaskTransitionHandler.moveToDesktop(wct, transitionSource) + addPendingMinimizeTransition(transition, taskToMinimize) } /** @@ -406,7 +400,7 @@ class DesktopTasksController( interactionJankMonitor.begin(taskSurface, context, handler, CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_HOLD) dragToDesktopTransitionHandler.startDragToDesktopTransition( - taskInfo.taskId, + taskInfo, dragToDesktopValueAnimator ) } @@ -496,11 +490,9 @@ class DesktopTasksController( // Rather than set windowing mode to multi-window at task level, set it to // undefined and inherit from split stage. wct.setWindowingMode(task.token, WINDOWING_MODE_UNDEFINED) - if (Transitions.ENABLE_SHELL_TRANSITIONS) { - transitions.startTransition(TRANSIT_CHANGE, wct, null /* handler */) - } else { - shellTaskOrganizer.applyTransaction(wct) - } + + transitions.startTransition(TRANSIT_CHANGE, wct, null /* handler */) + } private fun exitSplitIfApplicable(wct: WindowContainerTransaction, taskInfo: RunningTaskInfo) { @@ -534,17 +526,12 @@ class DesktopTasksController( val wct = WindowContainerTransaction() addMoveToFullscreenChanges(wct, task) - if (Transitions.ENABLE_SHELL_TRANSITIONS) { - exitDesktopTaskTransitionHandler.startTransition( + exitDesktopTaskTransitionHandler.startTransition( transitionSource, wct, position, mOnAnimationFinishedCallback ) - } else { - shellTaskOrganizer.applyTransaction(wct) - releaseVisualIndicator() - } } /** Move a task to the front */ @@ -578,15 +565,12 @@ class DesktopTasksController( fun moveTaskToFront(taskInfo: RunningTaskInfo) { logV("moveTaskToFront taskId=%s", taskInfo.taskId) val wct = WindowContainerTransaction() - wct.reorder(taskInfo.token, true) + wct.reorder(taskInfo.token, true /* onTop */, true /* includingParents */) val taskToMinimize = addAndGetMinimizeChangesIfNeeded(taskInfo.displayId, wct, taskInfo.taskId) - if (Transitions.ENABLE_SHELL_TRANSITIONS) { - val transition = transitions.startTransition(TRANSIT_TO_FRONT, wct, null /* handler */) - addPendingMinimizeTransition(transition, taskToMinimize) - } else { - shellTaskOrganizer.applyTransaction(wct) - } + + val transition = transitions.startTransition(TRANSIT_TO_FRONT, wct, null /* handler */) + addPendingMinimizeTransition(transition, taskToMinimize) } /** @@ -642,11 +626,38 @@ class DesktopTasksController( val wct = WindowContainerTransaction() wct.reparent(task.token, displayAreaInfo.token, true /* onTop */) - if (Transitions.ENABLE_SHELL_TRANSITIONS) { - transitions.startTransition(TRANSIT_CHANGE, wct, null /* handler */) + + transitions.startTransition(TRANSIT_CHANGE, wct, null /* handler */) + + } + + /** Moves a task in/out of full immersive state within the desktop. */ + fun toggleDesktopTaskFullImmersiveState(taskInfo: RunningTaskInfo) { + if (taskRepository.isTaskInFullImmersiveState(taskInfo.taskId)) { + exitDesktopTaskFromFullImmersive(taskInfo) } else { - shellTaskOrganizer.applyTransaction(wct) + moveDesktopTaskToFullImmersive(taskInfo) + } + } + + private fun moveDesktopTaskToFullImmersive(taskInfo: RunningTaskInfo) { + check(taskInfo.isFreeform) { "Task must already be in freeform" } + val wct = WindowContainerTransaction().apply { + setBounds(taskInfo.token, Rect()) + } + immersiveTransitionHandler.enterImmersive(taskInfo, wct) + } + + private fun exitDesktopTaskFromFullImmersive(taskInfo: RunningTaskInfo) { + check(taskInfo.isFreeform) { "Task must already be in freeform" } + val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return + val stableBounds = Rect().apply { displayLayout.getStableBounds(this) } + val destinationBounds = getMaximizeBounds(taskInfo, stableBounds) + + val wct = WindowContainerTransaction().apply { + setBounds(taskInfo.token, destinationBounds) } + immersiveTransitionHandler.exitImmersive(taskInfo, wct) } /** @@ -685,18 +696,7 @@ class DesktopTasksController( // and toggle to the stable bounds. taskRepository.saveBoundsBeforeMaximize(taskInfo.taskId, currentTaskBounds) - if (taskInfo.isResizeable) { - // if resizable then expand to entire stable bounds (full display minus insets) - destinationBounds.set(stableBounds) - } else { - // if non-resizable then calculate max bounds according to aspect ratio - val activityAspectRatio = calculateAspectRatio(taskInfo) - val newSize = maximizeSizeGivenAspectRatio(taskInfo, - Size(stableBounds.width(), stableBounds.height()), activityAspectRatio) - val newBounds = centerInArea( - newSize, stableBounds, stableBounds.left, stableBounds.top) - destinationBounds.set(newBounds) - } + destinationBounds.set(getMaximizeBounds(taskInfo, stableBounds)) } @@ -712,10 +712,22 @@ class DesktopTasksController( taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(doesAnyTaskRequireTaskbarRounding) val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds) - if (Transitions.ENABLE_SHELL_TRANSITIONS) { - toggleResizeDesktopTaskTransitionHandler.startTransition(wct) + + toggleResizeDesktopTaskTransitionHandler.startTransition(wct) + + } + + private fun getMaximizeBounds(taskInfo: RunningTaskInfo, stableBounds: Rect): Rect { + if (taskInfo.isResizeable) { + // if resizable then expand to entire stable bounds (full display minus insets) + return Rect(stableBounds) } else { - shellTaskOrganizer.applyTransaction(wct) + // if non-resizable then calculate max bounds according to aspect ratio + val activityAspectRatio = calculateAspectRatio(taskInfo) + val newSize = maximizeSizeGivenAspectRatio(taskInfo, + Size(stableBounds.width(), stableBounds.height()), activityAspectRatio) + return centerInArea( + newSize, stableBounds, stableBounds.left, stableBounds.top) } } @@ -812,11 +824,9 @@ class DesktopTasksController( taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(true) val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds) - if (Transitions.ENABLE_SHELL_TRANSITIONS) { - toggleResizeDesktopTaskTransitionHandler.startTransition(wct, currentDragBounds) - } else { - shellTaskOrganizer.applyTransaction(wct) - } + + toggleResizeDesktopTaskTransitionHandler.startTransition(wct, currentDragBounds) + } @VisibleForTesting @@ -1594,7 +1604,7 @@ class DesktopTasksController( return } - val indicator = visualIndicator ?: return + val indicator = getVisualIndicator() ?: return val indicatorType = indicator.updateIndicatorType( PointF(inputCoordinate.x, currentDragBounds.top.toFloat()), @@ -1810,6 +1820,17 @@ class DesktopTasksController( userId = newUserId } + /** Called when a task's info changes. */ + fun onTaskInfoChanged(taskInfo: RunningTaskInfo) { + if (!Flags.enableFullyImmersiveInDesktop()) return + val inImmersive = taskRepository.isTaskInFullImmersiveState(taskInfo.taskId) + val requestingImmersive = taskInfo.requestingImmersive + if (inImmersive && !requestingImmersive) { + // Exit immersive if the app is no longer requesting it. + exitDesktopTaskFromFullImmersive(taskInfo) + } + } + private fun dump(pw: PrintWriter, prefix: String) { val innerPrefix = "$prefix " pw.println("${prefix}DesktopTasksController") 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 7e0741f1f859..37bec21730a6 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 @@ -24,6 +24,7 @@ import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_TO_BACK import android.window.TransitionInfo import android.window.WindowContainerTransaction +import android.window.flags.DesktopModeFlags import androidx.annotation.VisibleForTesting import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW import com.android.internal.jank.InteractionJankMonitor @@ -43,7 +44,7 @@ import com.android.wm.shell.transition.Transitions.TransitionObserver */ class DesktopTasksLimiter ( transitions: Transitions, - private val taskRepository: DesktopModeTaskRepository, + private val taskRepository: DesktopRepository, private val shellTaskOrganizer: ShellTaskOrganizer, private val maxTasksLimit: Int, private val interactionJankMonitor: InteractionJankMonitor, @@ -159,8 +160,10 @@ class DesktopTasksLimiter ( } @VisibleForTesting - inner class LeftoverMinimizedTasksRemover : DesktopModeTaskRepository.ActiveTasksListener { + inner class LeftoverMinimizedTasksRemover : DesktopRepository.ActiveTasksListener { override fun onActiveTasksChanged(displayId: Int) { + // If back navigation is enabled, we shouldn't remove the leftover tasks + if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()) return val wct = WindowContainerTransaction() removeLeftoverMinimizedTasks(displayId, wct) shellTaskOrganizer.applyTransaction(wct) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt index 4796c4d0655a..64ae35b620dc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt @@ -29,27 +29,26 @@ import android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ import com.android.internal.protolog.ProtoLog import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE +import com.android.wm.shell.shared.TransitionUtil import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.Transitions /** * A [Transitions.TransitionObserver] that observes shell transitions and updates the - * [DesktopModeTaskRepository] state TODO: b/332682201 This observes transitions related to desktop + * [DesktopRepository] state TODO: b/332682201 This observes transitions related to desktop * mode and other transitions that originate both within and outside shell. */ class DesktopTasksTransitionObserver( private val context: Context, - private val desktopModeTaskRepository: DesktopModeTaskRepository, + private val desktopRepository: DesktopRepository, private val transitions: Transitions, private val shellTaskOrganizer: ShellTaskOrganizer, shellInit: ShellInit ) : Transitions.TransitionObserver { init { - if ( - Transitions.ENABLE_SHELL_TRANSITIONS && DesktopModeStatus.canEnterDesktopMode(context) - ) { + if (DesktopModeStatus.canEnterDesktopMode(context)) { shellInit.addInitCallback(::onInit, this) } } @@ -67,9 +66,29 @@ class DesktopTasksTransitionObserver( ) { // TODO: b/332682201 Update repository state updateWallpaperToken(info) - if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()) { handleBackNavigation(info) + removeTaskIfNeeded(info) + } + } + + private fun removeTaskIfNeeded(info: TransitionInfo) { + // Since we are no longer removing all the tasks [onTaskVanished], we need to remove them by + // checking the transitions. + if (!TransitionUtil.isOpeningType(info.type)) return + // Remove a task from the repository if the app is launched outside of desktop. + for (change in info.changes) { + val taskInfo = change.taskInfo + if (taskInfo == null || taskInfo.taskId == -1) continue + + if (desktopRepository.isActiveTask(taskInfo.taskId) + && taskInfo.windowingMode != WINDOWING_MODE_FREEFORM + ) { + desktopRepository.removeFreeformTask( + taskInfo.displayId, + taskInfo.taskId + ) + } } } @@ -83,11 +102,11 @@ class DesktopTasksTransitionObserver( continue } - if (desktopModeTaskRepository.getVisibleTaskCount(taskInfo.displayId) > 0 && + if (desktopRepository.getVisibleTaskCount(taskInfo.displayId) > 0 && change.mode == TRANSIT_TO_BACK && taskInfo.windowingMode == WINDOWING_MODE_FREEFORM ) { - desktopModeTaskRepository.minimizeTask(taskInfo.displayId, taskInfo.taskId) + desktopRepository.minimizeTask(taskInfo.displayId, taskInfo.taskId) } } } @@ -114,7 +133,7 @@ class DesktopTasksTransitionObserver( if (DesktopWallpaperActivity.isWallpaperTask(taskInfo)) { when (change.mode) { WindowManager.TRANSIT_OPEN -> { - desktopModeTaskRepository.wallpaperActivityToken = taskInfo.token + desktopRepository.wallpaperActivityToken = taskInfo.token // After the task for the wallpaper is created, set it non-trimmable. // This is important to prevent recents from trimming and removing the // task. @@ -124,7 +143,7 @@ class DesktopTasksTransitionObserver( ) } WindowManager.TRANSIT_CLOSE -> - desktopModeTaskRepository.wallpaperActivityToken = null + desktopRepository.wallpaperActivityToken = null else -> {} } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt index 2bc01b2f310e..8e264b2410f7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt @@ -109,8 +109,8 @@ sealed class DragToDesktopTransitionHandler( * after one of the "end" or "cancel" transitions is merged into this transition. */ fun startDragToDesktopTransition( - taskId: Int, - dragToDesktopAnimator: MoveToDesktopAnimator, + taskInfo: RunningTaskInfo, + dragToDesktopAnimator: MoveToDesktopAnimator ) { if (inProgress) { ProtoLog.v( @@ -137,23 +137,26 @@ sealed class DragToDesktopTransitionHandler( ) val wct = WindowContainerTransaction() wct.sendPendingIntent(pendingIntent, launchHomeIntent, Bundle()) + // The home launch done above will result in an attempt to move the task to pip if + // applicable, resulting in a broken state. Prevent that here. + wct.setDoNotPip(taskInfo.token) val startTransitionToken = transitions.startTransition(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP, wct, this) transitionState = - if (isSplitTask(taskId)) { + if (isSplitTask(taskInfo.taskId)) { val otherTask = - getOtherSplitTask(taskId) + getOtherSplitTask(taskInfo.taskId) ?: throw IllegalStateException("Expected split task to have a counterpart.") TransitionState.FromSplit( - draggedTaskId = taskId, + draggedTaskId = taskInfo.taskId, dragAnimator = dragToDesktopAnimator, startTransitionToken = startTransitionToken, otherSplitTask = otherTask ) } else { TransitionState.FromFullscreen( - draggedTaskId = taskId, + draggedTaskId = taskInfo.taskId, dragAnimator = dragToDesktopAnimator, startTransitionToken = startTransitionToken ) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt index 68a250d02958..334dc5aca19d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/education/AppHandleEducationController.kt @@ -23,6 +23,7 @@ import android.content.res.Resources import android.graphics.Point import android.os.SystemProperties import android.util.Slog +import androidx.core.content.withStyledAttributes import com.android.window.flags.Flags import com.android.wm.shell.R import com.android.wm.shell.desktopmode.CaptionState @@ -32,8 +33,11 @@ import com.android.wm.shell.shared.annotations.ShellBackgroundThread import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.canEnterDesktopMode import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource +import com.android.wm.shell.windowdecor.common.DecorThemeUtil +import com.android.wm.shell.windowdecor.common.Theme import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController.EducationViewConfig +import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController.TooltipColorScheme import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.MainCoroutineDispatcher @@ -70,6 +74,7 @@ class AppHandleEducationController( @ShellMainThread private val applicationCoroutineScope: CoroutineScope, @ShellBackgroundThread private val backgroundDispatcher: MainCoroutineDispatcher, ) { + private val decorThemeUtil = DecorThemeUtil(context) private lateinit var openHandleMenuCallback: (Int) -> Unit private lateinit var toDesktopModeCallback: (Int, DesktopModeTransitionSource) -> Unit @@ -97,7 +102,9 @@ class AppHandleEducationController( } .flowOn(backgroundDispatcher) .collectLatest { captionState -> - showEducation(captionState) + val tooltipColorScheme = tooltipColorScheme(captionState) + + showEducation(captionState, tooltipColorScheme) // After showing first tooltip, mark education as viewed appHandleEducationDatastoreRepository.updateEducationViewedTimestampMillis(true) } @@ -123,7 +130,7 @@ class AppHandleEducationController( if (canEnterDesktopMode(context) && Flags.enableDesktopWindowingAppHandleEducation()) block() } - private fun showEducation(captionState: CaptionState) { + private fun showEducation(captionState: CaptionState, tooltipColorScheme: TooltipColorScheme) { val appHandleBounds = (captionState as CaptionState.AppHandle).globalAppHandleBounds val tooltipGlobalCoordinates = Point(appHandleBounds.left + appHandleBounds.width() / 2, appHandleBounds.bottom) @@ -132,14 +139,17 @@ class AppHandleEducationController( val appHandleTooltipConfig = EducationViewConfig( tooltipViewLayout = R.layout.desktop_windowing_education_top_arrow_tooltip, + tooltipColorScheme = tooltipColorScheme, tooltipViewGlobalCoordinates = tooltipGlobalCoordinates, tooltipText = getString(R.string.windowing_app_handle_education_tooltip), arrowDirection = DesktopWindowingEducationTooltipController.TooltipArrowDirection.UP, onEducationClickAction = { - launchWithExceptionHandling { showWindowingImageButtonTooltip() } + launchWithExceptionHandling { showWindowingImageButtonTooltip(tooltipColorScheme) } openHandleMenuCallback(captionState.runningTaskInfo.taskId) }, - onDismissAction = { launchWithExceptionHandling { showWindowingImageButtonTooltip() } }, + onDismissAction = { + launchWithExceptionHandling { showWindowingImageButtonTooltip(tooltipColorScheme) } + }, ) windowingEducationViewController.showEducationTooltip( @@ -147,7 +157,7 @@ class AppHandleEducationController( } /** Show tooltip that points to windowing image button in app handle menu */ - private suspend fun showWindowingImageButtonTooltip() { + private suspend fun showWindowingImageButtonTooltip(tooltipColorScheme: TooltipColorScheme) { val appInfoPillHeight = getSize(R.dimen.desktop_mode_handle_menu_app_info_pill_height) val windowingOptionPillHeight = getSize(R.dimen.desktop_mode_handle_menu_windowing_pill_height) val appHandleMenuWidth = @@ -188,18 +198,21 @@ class AppHandleEducationController( val windowingImageButtonTooltipConfig = EducationViewConfig( tooltipViewLayout = R.layout.desktop_windowing_education_left_arrow_tooltip, + tooltipColorScheme = tooltipColorScheme, tooltipViewGlobalCoordinates = tooltipGlobalCoordinates, tooltipText = getString(R.string.windowing_desktop_mode_image_button_education_tooltip), arrowDirection = DesktopWindowingEducationTooltipController.TooltipArrowDirection.LEFT, onEducationClickAction = { - launchWithExceptionHandling { showExitWindowingTooltip() } + launchWithExceptionHandling { showExitWindowingTooltip(tooltipColorScheme) } toDesktopModeCallback( captionState.runningTaskInfo.taskId, DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON) }, - onDismissAction = { launchWithExceptionHandling { showExitWindowingTooltip() } }, + onDismissAction = { + launchWithExceptionHandling { showExitWindowingTooltip(tooltipColorScheme) } + }, ) windowingEducationViewController.showEducationTooltip( @@ -209,7 +222,7 @@ class AppHandleEducationController( } /** Show tooltip that points to app chip button and educates user on how to exit desktop mode */ - private suspend fun showExitWindowingTooltip() { + private suspend fun showExitWindowingTooltip(tooltipColorScheme: TooltipColorScheme) { windowDecorCaptionHandleRepository.captionStateFlow // After the previous tooltip was dismissed, wait for 400 ms and see if the user entered // desktop mode. @@ -238,6 +251,7 @@ class AppHandleEducationController( val exitWindowingTooltipConfig = EducationViewConfig( tooltipViewLayout = R.layout.desktop_windowing_education_left_arrow_tooltip, + tooltipColorScheme = tooltipColorScheme, tooltipViewGlobalCoordinates = tooltipGlobalCoordinates, tooltipText = getString(R.string.windowing_desktop_mode_exit_education_tooltip), arrowDirection = @@ -254,6 +268,32 @@ class AppHandleEducationController( } } + private fun tooltipColorScheme(captionState: CaptionState): TooltipColorScheme { + context.withStyledAttributes( + set = null, + attrs = + intArrayOf( + com.android.internal.R.attr.materialColorOnTertiaryFixed, + com.android.internal.R.attr.materialColorTertiaryFixed, + com.android.internal.R.attr.materialColorTertiaryFixedDim), + defStyleAttr = 0, + defStyleRes = 0) { + val onTertiaryFixed = getColor(/* index= */ 0, /* defValue= */ 0) + val tertiaryFixed = getColor(/* index= */ 1, /* defValue= */ 0) + val tertiaryFixedDim = getColor(/* index= */ 2, /* defValue= */ 0) + val taskInfo = (captionState as CaptionState.AppHandle).runningTaskInfo + + val tooltipContainerColor = + if (decorThemeUtil.getAppTheme(taskInfo) == Theme.LIGHT) { + tertiaryFixed + } else { + tertiaryFixedDim + } + return TooltipColorScheme(tooltipContainerColor, onTertiaryFixed, onTertiaryFixed) + } + return TooltipColorScheme(0, 0, 0) + } + /** * Setup callbacks for app handle education tooltips. * 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 7f7f10519bb1..92e645d493ec 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 @@ -29,7 +29,8 @@ import android.window.flags.DesktopModeFlags; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.LaunchAdjacentController; -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.desktopmode.DesktopRepository; +import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.sysui.ShellInit; @@ -49,7 +50,8 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, private final Context mContext; private final ShellTaskOrganizer mShellTaskOrganizer; - private final Optional<DesktopModeTaskRepository> mDesktopModeTaskRepository; + private final Optional<DesktopRepository> mDesktopRepository; + private final Optional<DesktopTasksController> mDesktopTasksController; private final WindowDecorViewModel mWindowDecorationViewModel; private final LaunchAdjacentController mLaunchAdjacentController; @@ -64,13 +66,15 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, Context context, ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, - Optional<DesktopModeTaskRepository> desktopModeTaskRepository, + Optional<DesktopRepository> desktopRepository, + Optional<DesktopTasksController> desktopTasksController, LaunchAdjacentController launchAdjacentController, WindowDecorViewModel windowDecorationViewModel) { mContext = context; mShellTaskOrganizer = shellTaskOrganizer; mWindowDecorationViewModel = windowDecorationViewModel; - mDesktopModeTaskRepository = desktopModeTaskRepository; + mDesktopRepository = desktopRepository; + mDesktopTasksController = desktopTasksController; mLaunchAdjacentController = launchAdjacentController; if (shellInit != null) { shellInit.addInitCallback(this::onInit, this); @@ -95,14 +99,9 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, state.mTaskInfo = taskInfo; state.mLeash = leash; mTasks.put(taskInfo.taskId, state); - if (!Transitions.ENABLE_SHELL_TRANSITIONS) { - SurfaceControl.Transaction t = new SurfaceControl.Transaction(); - mWindowDecorationViewModel.onTaskOpening(taskInfo, leash, t, t); - t.apply(); - } if (DesktopModeStatus.canEnterDesktopMode(mContext)) { - mDesktopModeTaskRepository.ifPresent(repository -> { + mDesktopRepository.ifPresent(repository -> { repository.addOrMoveFreeformTaskToTop(taskInfo.displayId, taskInfo.taskId); if (taskInfo.isVisible) { repository.addActiveTask(taskInfo.displayId, taskInfo.taskId); @@ -121,7 +120,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, mTasks.remove(taskInfo.taskId); if (DesktopModeStatus.canEnterDesktopMode(mContext)) { - mDesktopModeTaskRepository.ifPresent(repository -> { + mDesktopRepository.ifPresent(repository -> { // TODO: b/370038902 - Handle Activity#finishAndRemoveTask. if (!DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue() || repository.isClosingTask(taskInfo.taskId)) { @@ -135,9 +134,6 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, }); } mWindowDecorationViewModel.onTaskVanished(taskInfo); - if (!Transitions.ENABLE_SHELL_TRANSITIONS) { - mWindowDecorationViewModel.destroyWindowDecoration(taskInfo); - } updateLaunchAdjacentController(); } @@ -147,10 +143,11 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d", taskInfo.taskId); + mDesktopTasksController.ifPresent(c -> c.onTaskInfoChanged(taskInfo)); mWindowDecorationViewModel.onTaskInfoChanged(taskInfo); state.mTaskInfo = taskInfo; if (DesktopModeStatus.canEnterDesktopMode(mContext)) { - mDesktopModeTaskRepository.ifPresent(repository -> { + mDesktopRepository.ifPresent(repository -> { if (taskInfo.isVisible) { repository.addActiveTask(taskInfo.displayId, taskInfo.taskId); } else if (repository.isClosingTask(taskInfo.taskId)) { @@ -182,7 +179,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, "Freeform Task Focus Changed: #%d focused=%b", taskInfo.taskId, taskInfo.isFocused); if (DesktopModeStatus.canEnterDesktopMode(mContext) && taskInfo.isFocused) { - mDesktopModeTaskRepository.ifPresent(repository -> { + mDesktopRepository.ifPresent(repository -> { repository.addOrMoveFreeformTaskToTop(taskInfo.displayId, taskInfo.taskId); }); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java index ffcc526eac40..c9eccc3ff534 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java @@ -27,6 +27,8 @@ import android.window.WindowContainerToken; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; +import com.android.window.flags.Flags; +import com.android.wm.shell.desktopmode.DesktopFullImmersiveTransitionHandler; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.windowdecor.WindowDecorViewModel; @@ -36,6 +38,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; /** * The {@link Transitions.TransitionHandler} that handles freeform task launches, closes, @@ -44,7 +47,9 @@ import java.util.Map; */ public class FreeformTaskTransitionObserver implements Transitions.TransitionObserver { private final Transitions mTransitions; + private final Optional<DesktopFullImmersiveTransitionHandler> mImmersiveTransitionHandler; private final WindowDecorViewModel mWindowDecorViewModel; + private final Optional<TaskChangeListener> mTaskChangeListener; private final Map<IBinder, List<ActivityManager.RunningTaskInfo>> mTransitionToTaskInfo = new HashMap<>(); @@ -53,10 +58,14 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs Context context, ShellInit shellInit, Transitions transitions, - WindowDecorViewModel windowDecorViewModel) { + Optional<DesktopFullImmersiveTransitionHandler> immersiveTransitionHandler, + WindowDecorViewModel windowDecorViewModel, + Optional<TaskChangeListener> taskChangeListener) { mTransitions = transitions; + mImmersiveTransitionHandler = immersiveTransitionHandler; mWindowDecorViewModel = windowDecorViewModel; - if (Transitions.ENABLE_SHELL_TRANSITIONS && FreeformComponents.isFreeformEnabled(context)) { + mTaskChangeListener = taskChangeListener; + if (FreeformComponents.isFreeformEnabled(context)) { shellInit.addInitCallback(this::onInit, this); } } @@ -72,6 +81,13 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startT, @NonNull SurfaceControl.Transaction finishT) { + if (Flags.enableFullyImmersiveInDesktop()) { + // TODO(b/367268953): Remove when DesktopTaskListener is introduced and the repository + // is updated from there **before** the |mWindowDecorViewModel| methods are invoked. + // Otherwise window decoration relayout won't run with the immersive state up to date. + mImmersiveTransitionHandler.ifPresent(h -> h.onTransitionReady(transition)); + } + final ArrayList<ActivityManager.RunningTaskInfo> taskInfoList = new ArrayList<>(); final ArrayList<WindowContainerToken> taskParents = new ArrayList<>(); for (TransitionInfo.Change change : info.getChanges()) { @@ -103,6 +119,9 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs case WindowManager.TRANSIT_TO_FRONT: onToFrontTransitionReady(change, startT, finishT); break; + case WindowManager.TRANSIT_TO_BACK: + onToBackTransitionReady(change, startT, finishT); + break; case WindowManager.TRANSIT_CLOSE: { taskInfoList.add(change.getTaskInfo()); onCloseTransitionReady(change, startT, finishT); @@ -120,29 +139,49 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs TransitionInfo.Change change, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { + mTaskChangeListener.ifPresent( + listener -> listener.onTaskOpening(change.getTaskInfo())); mWindowDecorViewModel.onTaskOpening( - change.getTaskInfo(), change.getLeash(), startT, finishT); + change.getTaskInfo(), change.getLeash(), startT, finishT); } private void onCloseTransitionReady( TransitionInfo.Change change, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { + mTaskChangeListener.ifPresent( + listener -> listener.onTaskClosing(change.getTaskInfo())); mWindowDecorViewModel.onTaskClosing(change.getTaskInfo(), startT, finishT); + } private void onChangeTransitionReady( TransitionInfo.Change change, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { + mTaskChangeListener.ifPresent(listener -> + listener.onTaskChanging(change.getTaskInfo())); mWindowDecorViewModel.onTaskChanging( change.getTaskInfo(), change.getLeash(), startT, finishT); } + private void onToFrontTransitionReady( TransitionInfo.Change change, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { + mTaskChangeListener.ifPresent( + listener -> listener.onTaskMovingToFront(change.getTaskInfo())); + mWindowDecorViewModel.onTaskChanging( + change.getTaskInfo(), change.getLeash(), startT, finishT); + } + + private void onToBackTransitionReady( + TransitionInfo.Change change, + SurfaceControl.Transaction startT, + SurfaceControl.Transaction finishT) { + mTaskChangeListener.ifPresent( + listener -> listener.onTaskMovingToBack(change.getTaskInfo())); mWindowDecorViewModel.onTaskChanging( change.getTaskInfo(), change.getLeash(), startT, finishT); } @@ -179,4 +218,4 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs mWindowDecorViewModel.destroyWindowDecoration(taskInfo.get(i)); } } -}
\ No newline at end of file +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/TaskChangeListener.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/TaskChangeListener.kt new file mode 100644 index 000000000000..f07c069bb420 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/TaskChangeListener.kt @@ -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. + */ + +package com.android.wm.shell.freeform + +import android.app.ActivityManager.RunningTaskInfo; + +/** + * Interface used by [FreeformTaskTransitionObserver] to manage freeform tasks. + * + * The implementations are responsible for handle all the task management. + */ +interface TaskChangeListener { + /** Notifies a task opening in freeform mode. */ + fun onTaskOpening(taskInfo: RunningTaskInfo) + + /** Notifies a task info update on the given task. */ + fun onTaskChanging(taskInfo: RunningTaskInfo) + + /** Notifies a task moving to the front. */ + fun onTaskMovingToFront(taskInfo: RunningTaskInfo) + + /** Notifies a task moving to the back. */ + fun onTaskMovingToBack(taskInfo: RunningTaskInfo) + + /** Notifies a task is closing. */ + fun onTaskClosing(taskInfo: RunningTaskInfo) +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PhonePipMenuController.java index 9cfe1620a2ff..8c1e5e6a3e84 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PhonePipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PhonePipMenuController.java @@ -18,10 +18,12 @@ package com.android.wm.shell.pip2.phone; import static android.view.WindowManager.SHELL_ROOT_LAYER_PIP; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.RemoteAction; import android.content.Context; import android.graphics.Rect; +import android.os.Bundle; import android.os.Debug; import android.os.Handler; import android.os.RemoteException; @@ -52,7 +54,8 @@ import java.util.List; * The current media session provides actions whenever there are no valid actions provided by the * current PiP activity. Otherwise, those actions always take precedence. */ -public class PhonePipMenuController implements PipMenuController { +public class PhonePipMenuController implements PipMenuController, + PipTransitionState.PipTransitionStateChangedListener { private static final String TAG = "PhonePipMenuController"; private static final boolean DEBUG = false; @@ -113,6 +116,11 @@ public class PhonePipMenuController implements PipMenuController { private PipMenuView mPipMenuView; + private final PipTaskListener mPipTaskListener; + + @NonNull + private final PipTransitionState mPipTransitionState; + private SurfaceControl mLeash; private ActionListener mMediaActionListener = new ActionListener() { @@ -125,15 +133,27 @@ public class PhonePipMenuController implements PipMenuController { public PhonePipMenuController(Context context, PipBoundsState pipBoundsState, PipMediaController mediaController, SystemWindows systemWindows, - PipUiEventLogger pipUiEventLogger, - ShellExecutor mainExecutor, Handler mainHandler) { + PipUiEventLogger pipUiEventLogger, PipTaskListener pipTaskListener, + @NonNull PipTransitionState pipTransitionState, ShellExecutor mainExecutor, + Handler mainHandler) { mContext = context; mPipBoundsState = pipBoundsState; mMediaController = mediaController; mSystemWindows = systemWindows; + mPipTaskListener = pipTaskListener; + mPipTransitionState = pipTransitionState; mMainExecutor = mainExecutor; mMainHandler = mainHandler; mPipUiEventLogger = pipUiEventLogger; + + mPipTransitionState.addPipTransitionStateChangedListener(this); + + mPipTaskListener.addParamsChangedListener(new PipTaskListener.PipParamsChangedCallback() { + @Override + public void onActionsChanged(List<RemoteAction> actions, RemoteAction closeAction) { + setAppActions(actions, closeAction); + } + }); } public boolean isMenuVisible() { @@ -438,8 +458,7 @@ public class PhonePipMenuController implements PipMenuController { * Sets the menu actions to the actions provided by the current PiP menu. */ @Override - public void setAppActions(List<RemoteAction> appActions, - RemoteAction closeAction) { + public void setAppActions(List<RemoteAction> appActions, RemoteAction closeAction) { mAppActions = appActions; mCloseAction = closeAction; updateMenuActions(); @@ -468,8 +487,8 @@ public class PhonePipMenuController implements PipMenuController { */ private void updateMenuActions() { if (mPipMenuView != null) { - mPipMenuView.setActions(mPipBoundsState.getBounds(), - resolveMenuActions(), mCloseAction); + mPipMenuView.setActions(mPipBoundsState.getBounds(), resolveMenuActions(), + mCloseAction); } } @@ -567,6 +586,29 @@ public class PhonePipMenuController implements PipMenuController { } } + @Override + public void onPipTransitionStateChanged(@PipTransitionState.TransitionState int oldState, + @PipTransitionState.TransitionState int newState, Bundle extra) { + switch (newState) { + case PipTransitionState.ENTERED_PIP: + attach(mPipTransitionState.mPinnedTaskLeash); + break; + case PipTransitionState.EXITED_PIP: + detach(); + break; + case PipTransitionState.CHANGED_PIP_BOUNDS: + updateMenuLayout(mPipBoundsState.getBounds()); + hideMenu(); + break; + case PipTransitionState.CHANGING_PIP_BOUNDS: + hideMenu(); + break; + case PipTransitionState.SCHEDULED_BOUNDS_CHANGE: + hideMenu(); + break; + } + } + void dump(PrintWriter pw, String prefix) { final String innerPrefix = prefix + " "; pw.println(prefix + TAG); 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 e9c4c14234e6..73be8db0ea8a 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 @@ -324,10 +324,16 @@ public class PipController implements ConfigurationChangeListener, int launcherRotation, Rect hotseatKeepClearArea) { ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "getSwipePipToHomeBounds: %s", componentName); - // preemptively add the keep clear area for Hotseat, so that it is taken into account - // when calculating the entry destination bounds of PiP window + // Preemptively add the keep clear area for Hotseat, so that it is taken into account + // when calculating the entry destination bounds of PiP window. mPipBoundsState.setNamedUnrestrictedKeepClearArea( PipBoundsState.NAMED_KCA_LAUNCHER_SHELF, hotseatKeepClearArea); + + // Set the display layout rotation early to calculate final orientation bounds that + // the animator expects, this will also be used to detect the fixed rotation when + // Shell resolves the type of the animation we are undergoing. + mPipDisplayLayoutState.rotateTo(launcherRotation); + mPipBoundsState.setBoundsStateForEntry(componentName, activityInfo, pictureInPictureParams, mPipBoundsAlgorithm); return mPipBoundsAlgorithm.getEntryDestinationBounds(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMenuView.java index a29104c4aafd..0910919b3064 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMenuView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMenuView.java @@ -447,7 +447,7 @@ public class PipMenuView extends FrameLayout { final LayoutInflater inflater = LayoutInflater.from(mContext); while (mActionsGroup.getChildCount() < mActions.size()) { final PipMenuActionView actionView = (PipMenuActionView) inflater.inflate( - R.layout.pip_menu_action, mActionsGroup, false); + R.layout.pip2_menu_action, mActionsGroup, false); mActionsGroup.addView(actionView); } 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 0324fdba0fbf..268c3a20a41a 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 @@ -336,7 +336,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, } cancelPhysicsAnimation(); mMenuController.hideMenu(ANIM_TYPE_NONE, false /* resize */); - // mPipTaskOrganizer.exitPip(skipAnimation ? 0 : LEAVE_PIP_DURATION, enterSplit); + mPipScheduler.scheduleExitPipViaExpand(); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java index f4defdc7963c..d4f190ebd2a2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java @@ -52,7 +52,6 @@ public class PipScheduler { private final Context mContext; private final PipBoundsState mPipBoundsState; - private final PhonePipMenuController mPipMenuController; private final ShellExecutor mMainExecutor; private final PipTransitionState mPipTransitionState; private PipSchedulerReceiver mSchedulerReceiver; @@ -97,12 +96,10 @@ public class PipScheduler { public PipScheduler(Context context, PipBoundsState pipBoundsState, - PhonePipMenuController pipMenuController, ShellExecutor mainExecutor, PipTransitionState pipTransitionState) { mContext = context; mPipBoundsState = pipBoundsState; - mPipMenuController = pipMenuController; mMainExecutor = mainExecutor; mPipTransitionState = pipTransitionState; @@ -263,7 +260,6 @@ public class PipScheduler { return; } mPipBoundsState.setBounds(newBounds); - mPipMenuController.updateMenuLayout(newBounds); maybeUpdateMovementBounds(); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java index 262c14d2bfe3..c58de2c3512a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java @@ -20,6 +20,7 @@ import static com.android.wm.shell.pip2.phone.PipTransition.ANIMATING_BOUNDS_CHA import android.app.ActivityManager; import android.app.PictureInPictureParams; +import android.app.RemoteAction; import android.content.Context; import android.graphics.Rect; import android.os.Bundle; @@ -37,6 +38,9 @@ import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.pip2.animation.PipResizeAnimator; import com.android.wm.shell.shared.annotations.ShellMainThread; +import java.util.ArrayList; +import java.util.List; + /** * A Task Listener implementation used only for CUJs and trigger paths that cannot be initiated via * Transitions framework directly. @@ -57,6 +61,7 @@ public class PipTaskListener implements ShellTaskOrganizer.TaskListener, new PictureInPictureParams.Builder().build(); private boolean mWaitingForAspectRatioChange = false; + private final List<PipParamsChangedCallback> mPipParamsChangedListeners = new ArrayList<>(); public PipTaskListener(Context context, ShellTaskOrganizer shellTaskOrganizer, @@ -85,10 +90,25 @@ public class PipTaskListener implements ShellTaskOrganizer.TaskListener, if (mPictureInPictureParams.equals(params)) { return; } + if (PipUtils.remoteActionsChanged(params.getActions(), mPictureInPictureParams.getActions()) + || !PipUtils.remoteActionsMatch(params.getCloseAction(), + mPictureInPictureParams.getCloseAction())) { + for (PipParamsChangedCallback listener : mPipParamsChangedListeners) { + listener.onActionsChanged(params.getActions(), params.getCloseAction()); + } + } mPictureInPictureParams.copyOnlySet(params != null ? params : new PictureInPictureParams.Builder().build()); } + /** Add a PipParamsChangedCallback listener. */ + public void addParamsChangedListener(PipParamsChangedCallback listener) { + if (mPipParamsChangedListeners.contains(listener)) { + return; + } + mPipParamsChangedListeners.add(listener); + } + @NonNull public PictureInPictureParams getPictureInPictureParams() { return mPictureInPictureParams; @@ -164,4 +184,12 @@ public class PipTaskListener implements ShellTaskOrganizer.TaskListener, break; } } + + public interface PipParamsChangedCallback { + /** + * Called if either the actions or the close action changed. + */ + default void onActionsChanged(List<RemoteAction> actions, RemoteAction closeAction) { + } + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java index dc0bc7816859..62a60fab6603 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java @@ -17,6 +17,7 @@ package com.android.wm.shell.pip2.phone; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.view.Surface.ROTATION_270; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_PIP; @@ -33,6 +34,7 @@ import android.annotation.NonNull; import android.app.ActivityManager; import android.app.PictureInPictureParams; import android.content.Context; +import android.graphics.Matrix; import android.graphics.Rect; import android.os.Bundle; import android.os.IBinder; @@ -49,6 +51,7 @@ import com.android.internal.util.Preconditions; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.pip.PipBoundsAlgorithm; import com.android.wm.shell.common.pip.PipBoundsState; +import com.android.wm.shell.common.pip.PipDisplayLayoutState; import com.android.wm.shell.common.pip.PipMenuController; import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.pip.PipTransitionController; @@ -82,7 +85,7 @@ public class PipTransition extends PipTransitionController implements * The fixed start delay in ms when fading out the content overlay from bounds animation. * The fadeout animation is guaranteed to start after the client has drawn under the new config. */ - private static final int CONTENT_OVERLAY_FADE_OUT_DELAY_MS = 400; + private static final int CONTENT_OVERLAY_FADE_OUT_DELAY_MS = 500; // // Dependencies @@ -92,6 +95,7 @@ public class PipTransition extends PipTransitionController implements private final PipTaskListener mPipTaskListener; private final PipScheduler mPipScheduler; private final PipTransitionState mPipTransitionState; + private final PipDisplayLayoutState mPipDisplayLayoutState; // // Transition caches @@ -124,6 +128,7 @@ public class PipTransition extends PipTransitionController implements PipTaskListener pipTaskListener, PipScheduler pipScheduler, PipTransitionState pipTransitionState, + PipDisplayLayoutState pipDisplayLayoutState, PipUiStateChangeController pipUiStateChangeController) { super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController, pipBoundsAlgorithm); @@ -134,6 +139,7 @@ public class PipTransition extends PipTransitionController implements mPipScheduler.setPipTransitionController(this); mPipTransitionState = pipTransitionState; mPipTransitionState.addPipTransitionStateChangedListener(this); + mPipDisplayLayoutState = pipDisplayLayoutState; } @Override @@ -321,11 +327,30 @@ public class PipTransition extends PipTransitionController implements (destinationBounds.width() - overlaySize) / 2f, (destinationBounds.height() - overlaySize) / 2f); } - startTransaction.merge(finishTransaction); + + final int startRotation = pipChange.getStartRotation(); + final int endRotation = mPipDisplayLayoutState.getRotation(); + if (endRotation != startRotation) { + boolean isClockwise = (endRotation - startRotation) == -ROTATION_270; + + // Display bounds were already updated to represent the final orientation, + // so we just need to readjust the origin, and perform rotation about (0, 0). + Rect displayBounds = mPipDisplayLayoutState.getDisplayBounds(); + int originTranslateX = isClockwise ? 0 : -displayBounds.width(); + int originTranslateY = isClockwise ? -displayBounds.height() : 0; + + Matrix transformTensor = new Matrix(); + final float[] matrixTmp = new float[9]; + transformTensor.setTranslate(originTranslateX + destinationBounds.left, + originTranslateY + destinationBounds.top); + final float degrees = (endRotation - startRotation) * 90f; + transformTensor.postRotate(degrees); + startTransaction.setMatrix(pipLeash, transformTensor, matrixTmp); + } startTransaction.apply(); finishCallback.onTransitionFinished(null /* finishWct */); - onClientDrawAtTransitionEnd(); + finishInner(); return true; } @@ -397,7 +422,7 @@ public class PipTransition extends PipTransitionController implements sourceRectHint, PipEnterExitAnimator.BOUNDS_ENTER, Surface.ROTATION_0); tx.addTransactionCommittedListener(mPipScheduler.getMainExecutor(), - this::onClientDrawAtTransitionEnd); + this::finishInner); finishWct.setBoundsChangeTransaction(pipTaskToken, tx); animator.setAnimationEndCallback(() -> @@ -430,7 +455,7 @@ public class PipTransition extends PipTransitionController implements animator.setAnimationEndCallback(() -> { finishCallback.onTransitionFinished(null); // This should update the pip transition state accordingly after we stop playing. - onClientDrawAtTransitionEnd(); + finishInner(); }); animator.start(); @@ -605,7 +630,7 @@ public class PipTransition extends PipTransitionController implements // Miscellaneous callbacks and listeners // - private void onClientDrawAtTransitionEnd() { + private void finishInner() { if (mPipTransitionState.getSwipePipToHomeOverlay() != null) { startOverlayFadeoutAnimation(); } else if (mPipTransitionState.getState() == PipTransitionState.ENTERING_PIP) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java index 03ff1aac794c..95cb3df50977 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java @@ -32,6 +32,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.graphics.Color; +import android.graphics.Point; import android.os.Bundle; import android.os.RemoteException; import android.util.Slog; @@ -46,13 +47,14 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.internal.protolog.ProtoLog; +import com.android.window.flags.Flags; import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SingleInstanceRemoteListener; import com.android.wm.shell.common.TaskStackListenerCallback; import com.android.wm.shell.common.TaskStackListenerImpl; -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.GroupedRecentTaskInfo; import com.android.wm.shell.shared.annotations.ExternalThread; @@ -79,14 +81,14 @@ import java.util.function.Consumer; * Manages the recent task list from the system, caching it as necessary. */ public class RecentTasksController implements TaskStackListenerCallback, - RemoteCallable<RecentTasksController>, DesktopModeTaskRepository.ActiveTasksListener, + RemoteCallable<RecentTasksController>, DesktopRepository.ActiveTasksListener, TaskStackTransitionObserver.TaskStackTransitionObserverListener { private static final String TAG = RecentTasksController.class.getSimpleName(); private final Context mContext; private final ShellController mShellController; private final ShellCommandHandler mShellCommandHandler; - private final Optional<DesktopModeTaskRepository> mDesktopModeTaskRepository; + private final Optional<DesktopRepository> mDesktopRepository; private final ShellExecutor mMainExecutor; private final TaskStackListenerImpl mTaskStackListener; private final RecentTasksImpl mImpl = new RecentTasksImpl(); @@ -119,7 +121,7 @@ public class RecentTasksController implements TaskStackListenerCallback, ShellCommandHandler shellCommandHandler, TaskStackListenerImpl taskStackListener, ActivityTaskManager activityTaskManager, - Optional<DesktopModeTaskRepository> desktopModeTaskRepository, + Optional<DesktopRepository> desktopRepository, TaskStackTransitionObserver taskStackTransitionObserver, @ShellMainThread ShellExecutor mainExecutor ) { @@ -127,7 +129,7 @@ public class RecentTasksController implements TaskStackListenerCallback, return null; } return new RecentTasksController(context, shellInit, shellController, shellCommandHandler, - taskStackListener, activityTaskManager, desktopModeTaskRepository, + taskStackListener, activityTaskManager, desktopRepository, taskStackTransitionObserver, mainExecutor); } @@ -137,7 +139,7 @@ public class RecentTasksController implements TaskStackListenerCallback, ShellCommandHandler shellCommandHandler, TaskStackListenerImpl taskStackListener, ActivityTaskManager activityTaskManager, - Optional<DesktopModeTaskRepository> desktopModeTaskRepository, + Optional<DesktopRepository> desktopRepository, TaskStackTransitionObserver taskStackTransitionObserver, ShellExecutor mainExecutor) { mContext = context; @@ -146,7 +148,7 @@ public class RecentTasksController implements TaskStackListenerCallback, mActivityTaskManager = activityTaskManager; mPcFeatureEnabled = mContext.getPackageManager().hasSystemFeature(FEATURE_PC); mTaskStackListener = taskStackListener; - mDesktopModeTaskRepository = desktopModeTaskRepository; + mDesktopRepository = desktopRepository; mTaskStackTransitionObserver = taskStackTransitionObserver; mMainExecutor = mainExecutor; shellInit.addInitCallback(this::onInit, this); @@ -166,7 +168,7 @@ public class RecentTasksController implements TaskStackListenerCallback, this::createExternalInterface, this); mShellCommandHandler.addDumpCallback(this::dump, this); mTaskStackListener.addListener(this); - mDesktopModeTaskRepository.ifPresent(it -> it.addActiveTaskListener(this)); + mDesktopRepository.ifPresent(it -> it.addActiveTaskListener(this)); if (Transitions.ENABLE_SHELL_TRANSITIONS) { mTaskStackTransitionObserver.addTaskStackTransitionObserverListener(this, mMainExecutor); @@ -415,14 +417,24 @@ public class RecentTasksController implements TaskStackListenerCallback, } if (DesktopModeStatus.canEnterDesktopMode(mContext) - && mDesktopModeTaskRepository.isPresent() - && mDesktopModeTaskRepository.get().isActiveTask(taskInfo.taskId)) { + && mDesktopRepository.isPresent() + && mDesktopRepository.get().isActiveTask(taskInfo.taskId)) { // Freeform tasks will be added as a separate entry if (mostRecentFreeformTaskIndex == Integer.MAX_VALUE) { mostRecentFreeformTaskIndex = recentTasks.size(); } + // If task has their app bounds set to null which happens after reboot, set the + // app bounds to persisted lastFullscreenBounds. Also set the position in parent + // to the top left of the bounds. + if (Flags.enableDesktopWindowingPersistence() + && taskInfo.configuration.windowConfiguration.getAppBounds() == null) { + taskInfo.configuration.windowConfiguration.setAppBounds( + taskInfo.lastNonFullscreenBounds); + taskInfo.positionInParent = new Point(taskInfo.lastNonFullscreenBounds.left, + taskInfo.lastNonFullscreenBounds.top); + } freeformTasks.add(taskInfo); - if (mDesktopModeTaskRepository.get().isMinimizedTask(taskInfo.taskId)) { + if (mDesktopRepository.get().isMinimizedTask(taskInfo.taskId)) { minimizedFreeformTasks.add(taskInfo.taskId); } continue; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/TaskStackTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/TaskStackTransitionObserver.kt index e5bfccf0682e..0cbbb715cde6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/TaskStackTransitionObserver.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/TaskStackTransitionObserver.kt @@ -17,14 +17,12 @@ package com.android.wm.shell.recents import android.app.ActivityManager.RunningTaskInfo -import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.os.IBinder import android.util.ArrayMap import android.view.SurfaceControl -import android.view.WindowManager import android.window.TransitionInfo -import com.android.wm.shell.shared.TransitionUtil import android.window.flags.DesktopModeFlags +import com.android.wm.shell.shared.TransitionUtil import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.Transitions import dagger.Lazy @@ -40,16 +38,11 @@ class TaskStackTransitionObserver( private val transitions: Lazy<Transitions>, shellInit: ShellInit ) : Transitions.TransitionObserver { - - private val transitionToTransitionChanges: MutableMap<IBinder, TransitionChanges> = - mutableMapOf() private val taskStackTransitionObserverListeners = ArrayMap<TaskStackTransitionObserverListener, Executor>() init { - if (Transitions.ENABLE_SHELL_TRANSITIONS) { - shellInit.addInitCallback(::onInit, this) - } + shellInit.addInitCallback(::onInit, this) } fun onInit() { @@ -63,9 +56,6 @@ class TaskStackTransitionObserver( finishTransaction: SurfaceControl.Transaction ) { if (DesktopModeFlags.ENABLE_TASK_STACK_OBSERVER_IN_SHELL.isTrue) { - val taskInfoList = mutableListOf<RunningTaskInfo>() - val transitionTypeList = mutableListOf<Int>() - for (change in info.changes) { if (change.flags and TransitionInfo.FLAG_IS_WALLPAPER != 0) { continue @@ -76,59 +66,21 @@ class TaskStackTransitionObserver( continue } - // Filter out changes that we care about - if (change.mode == WindowManager.TRANSIT_OPEN) { - change.taskInfo?.let { taskInfoList.add(it) } - transitionTypeList.add(change.mode) + // Find the first task that is opening, this should be the one at the front after + // the transition + if (TransitionUtil.isOpeningType(change.mode)) { + notifyTaskStackTransitionObserverListeners(taskInfo) + break } } - // Only add the transition to map if it has a change we care about - if (taskInfoList.isNotEmpty()) { - transitionToTransitionChanges.put( - transition, - TransitionChanges(taskInfoList, transitionTypeList) - ) - } } } override fun onTransitionStarting(transition: IBinder) {} - override fun onTransitionMerged(merged: IBinder, playing: IBinder) { - val mergedTransitionChanges = - transitionToTransitionChanges.get(merged) - ?: - // We are adding changes of the merged transition to changes of the playing - // transition so if there is no changes nothing to do. - return - - transitionToTransitionChanges.remove(merged) - val playingTransitionChanges = transitionToTransitionChanges.get(playing) - if (playingTransitionChanges != null) { - playingTransitionChanges.merge(mergedTransitionChanges) - } else { - transitionToTransitionChanges.put(playing, mergedTransitionChanges) - } - } + override fun onTransitionMerged(merged: IBinder, playing: IBinder) {} - override fun onTransitionFinished(transition: IBinder, aborted: Boolean) { - val taskInfoList = - transitionToTransitionChanges.getOrDefault(transition, TransitionChanges()).taskInfoList - val typeList = - transitionToTransitionChanges - .getOrDefault(transition, TransitionChanges()) - .transitionTypeList - transitionToTransitionChanges.remove(transition) - - for ((index, taskInfo) in taskInfoList.withIndex()) { - if ( - TransitionUtil.isOpeningType(typeList[index]) && - taskInfo.windowingMode == WINDOWING_MODE_FREEFORM - ) { - notifyTaskStackTransitionObserverListeners(taskInfo) - } - } - } + override fun onTransitionFinished(transition: IBinder, aborted: Boolean) {} fun addTaskStackTransitionObserverListener( taskStackTransitionObserverListener: TaskStackTransitionObserverListener, @@ -154,14 +106,4 @@ class TaskStackTransitionObserver( /** Called when a task is moved to front. */ fun onTaskMovedToFrontThroughTransition(taskInfo: RunningTaskInfo) {} } - - private data class TransitionChanges( - val taskInfoList: MutableList<RunningTaskInfo> = ArrayList(), - val transitionTypeList: MutableList<Int> = ArrayList(), - ) { - fun merge(transitionChanges: TransitionChanges) { - taskInfoList.addAll(transitionChanges.taskInfoList) - transitionTypeList.addAll(transitionChanges.transitionTypeList) - } - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index e8eb10c984af..e527c02e0dec 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -901,6 +901,23 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, setEnterInstanceId(instanceId); } + + @Override + public void setExcludeImeInsets(boolean exclude) { + if (android.view.inputmethod.Flags.refactorInsetsController()) { + final WindowContainerTransaction wct = new WindowContainerTransaction(); + if (mRootTaskInfo == null) { + ProtoLog.e(WM_SHELL_SPLIT_SCREEN, "setExcludeImeInsets: mRootTaskInfo is null"); + return; + } + ProtoLog.d(WM_SHELL_SPLIT_SCREEN, + "setExcludeImeInsets: root taskId=%s exclude=%s", + mRootTaskInfo.taskId, exclude); + wct.setExcludeImeInsets(mRootTaskInfo.token, exclude); + mTaskOrganizer.applyTransaction(wct); + } + } + /** * Checks if either of the apps in the desired split launch is currently in Pip. If so, it will * launch the non-pipped app as a fullscreen app, otherwise no-op. @@ -1717,6 +1734,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, final WindowContainerTransaction wct = new WindowContainerTransaction(); wct.reparent(mMainStage.mRootTaskInfo.token, mRootTaskInfo.token, true); wct.reparent(mSideStage.mRootTaskInfo.token, mRootTaskInfo.token, true); + // Make the stages adjacent to each other so they occlude what's behind them. wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token); setRootForceTranslucent(true, wct); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java index 30d7245436be..e61929fef312 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java @@ -141,10 +141,13 @@ public class MixedTransitionHelper { pipHandler.setEnterAnimationType(ANIM_TYPE_ALPHA); pipHandler.startEnterAnimation(pipChange, startTransaction, finishTransaction, finishCB); + // make a new finishTransaction because pip's startEnterAnimation "consumes" it so + // we need a separate one to send over to launcher. + SurfaceControl.Transaction otherFinishT = new SurfaceControl.Transaction(); // Dispatch the rest of the transition normally. This will most-likely be taken by // recents or default handler. mixed.mLeftoversHandler = player.dispatchTransition(mixed.mTransition, everythingElse, - otherStartT, finishTransaction, finishCB, mixedHandler); + otherStartT, otherFinishT, finishCB, mixedHandler); } else { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Not leaving split, so just " + "forward animation to Pip-Handler."); 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 f5b2340b87a7..c540edef32c4 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 @@ -361,7 +361,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId); if (!taskInfo.isFocused) { final WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.reorder(mTaskToken, true /* onTop */); + wct.reorder(mTaskToken, true /* onTop */, true /* includingParents */); mSyncQueue.queue(wct); } } 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 3330f968332c..bcf48d9ec2eb 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 @@ -103,7 +103,7 @@ import com.android.wm.shell.common.MultiInstanceHelper; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler; -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition; @@ -155,7 +155,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { private final ActivityTaskManager mActivityTaskManager; private final ShellCommandHandler mShellCommandHandler; private final ShellTaskOrganizer mTaskOrganizer; - private final DesktopModeTaskRepository mDesktopRepository; + private final DesktopRepository mDesktopRepository; private final ShellController mShellController; private final Context mContext; private final @ShellMainThread Handler mMainHandler; @@ -227,7 +227,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { ShellCommandHandler shellCommandHandler, IWindowManager windowManager, ShellTaskOrganizer taskOrganizer, - DesktopModeTaskRepository desktopRepository, + DesktopRepository desktopRepository, DisplayController displayController, ShellController shellController, DisplayInsetsController displayInsetsController, @@ -288,7 +288,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { ShellCommandHandler shellCommandHandler, IWindowManager windowManager, ShellTaskOrganizer taskOrganizer, - DesktopModeTaskRepository desktopRepository, + DesktopRepository desktopRepository, DisplayController displayController, ShellController shellController, DisplayInsetsController displayInsetsController, @@ -538,6 +538,14 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { decoration.closeMaximizeMenu(); } + private void onEnterOrExitImmersive(int taskId) { + final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId); + if (decoration == null) { + return; + } + mDesktopTasksController.toggleDesktopTaskFullImmersiveState(decoration.mTaskInfo); + } + private void onSnapResize(int taskId, boolean left) { final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId); if (decoration == null) { @@ -755,7 +763,16 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { // back to the decoration using // {@link DesktopModeWindowDecoration#setOnMaximizeOrRestoreClickListener}, which // should shared with the maximize menu's maximize/restore actions. - onMaximizeOrRestore(decoration.mTaskInfo.taskId, "caption_bar_button"); + if (Flags.enableFullyImmersiveInDesktop() + && TaskInfoKt.getRequestingImmersive(decoration.mTaskInfo)) { + // Task is requesting immersive, so it should either enter or exit immersive, + // depending on immersive state. + onEnterOrExitImmersive(decoration.mTaskInfo.taskId); + } else { + // Full immersive is disabled or task doesn't request/support it, so just + // toggle between maximize/restore states. + onMaximizeOrRestore(decoration.mTaskInfo.taskId, "caption_bar_button"); + } } else if (id == R.id.minimize_window) { final WindowContainerTransaction wct = new WindowContainerTransaction(); mDesktopTasksController.onDesktopWindowMinimize(wct, mTaskId); @@ -935,14 +952,18 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { } final boolean touchingButton = (id == R.id.close_window || id == R.id.maximize_window || id == R.id.open_menu_button || id == R.id.minimize_window); + final boolean dragAllowed = + !mDesktopRepository.isTaskInFullImmersiveState(taskInfo.taskId); switch (e.getActionMasked()) { case MotionEvent.ACTION_DOWN: { - mDragPointerId = e.getPointerId(0); - final Rect initialBounds = mDragPositioningCallback.onDragPositioningStart( - 0 /* ctrlType */, e.getRawX(0), - e.getRawY(0)); - updateDragStatus(e.getActionMasked()); - mOnDragStartInitialBounds.set(initialBounds); + if (dragAllowed) { + mDragPointerId = e.getPointerId(0); + final Rect initialBounds = mDragPositioningCallback.onDragPositioningStart( + 0 /* ctrlType */, e.getRawX(0), + e.getRawY(0)); + updateDragStatus(e.getActionMasked()); + mOnDragStartInitialBounds.set(initialBounds); + } mHasLongClicked = false; // Do not consume input event if a button is touched, otherwise it would // prevent the button's ripple effect from showing. @@ -951,6 +972,9 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { case ACTION_MOVE: { // If a decor's resize drag zone is active, don't also try to reposition it. if (decoration.isHandlingDragResize()) break; + // Dragging the header isn't allowed, so skip the positioning work. + if (!dragAllowed) break; + decoration.closeMaximizeMenu(); if (e.findPointerIndex(mDragPointerId) == -1) { mDragPointerId = e.getPointerId(0); @@ -1036,6 +1060,10 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { && action != MotionEvent.ACTION_CANCEL)) { return false; } + if (mDesktopRepository.isTaskInFullImmersiveState(mTaskId)) { + // Disallow double-tap to resize when in full immersive. + return false; + } onMaximizeOrRestore(mTaskId, "double_tap"); return true; } 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 5daa3eee340b..25d37fce7270 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 @@ -87,13 +87,14 @@ import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser; import com.android.wm.shell.apptoweb.AppToWebUtils; import com.android.wm.shell.apptoweb.AssistContentRequester; +import com.android.wm.shell.apptoweb.OpenByDefaultDialog; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.MultiInstanceHelper; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.desktopmode.CaptionState; -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository; import com.android.wm.shell.shared.annotations.ShellBackgroundThread; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; @@ -163,6 +164,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin private MaximizeMenu mMaximizeMenu; + private OpenByDefaultDialog mOpenByDefaultDialog; + private ResizeVeil mResizeVeil; private Bitmap mAppIconBitmap; private Bitmap mResizeVeilBitmap; @@ -193,14 +196,14 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin private final Runnable mCapturedLinkExpiredRunnable = this::onCapturedLinkExpired; private final MultiInstanceHelper mMultiInstanceHelper; private final WindowDecorCaptionHandleRepository mWindowDecorCaptionHandleRepository; - private final DesktopModeTaskRepository mDesktopRepository; + private final DesktopRepository mDesktopRepository; DesktopModeWindowDecoration( Context context, @NonNull Context userContext, DisplayController displayController, SplitScreenController splitScreenController, - DesktopModeTaskRepository desktopRepository, + DesktopRepository desktopRepository, ShellTaskOrganizer taskOrganizer, ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface, @@ -232,7 +235,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin @NonNull Context userContext, DisplayController displayController, SplitScreenController splitScreenController, - DesktopModeTaskRepository desktopRepository, + DesktopRepository desktopRepository, ShellTaskOrganizer taskOrganizer, ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface, @@ -448,6 +451,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mHandleMenu.relayout(startT, mResult.mCaptionX); } + if (isOpenByDefaultDialogActive()) { + mOpenByDefaultDialog.relayout(taskInfo); + } + final boolean inFullImmersive = mDesktopRepository .isTaskInFullImmersiveState(taskInfo.taskId); updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw, @@ -510,8 +517,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin closeManageWindowsMenu(); closeMaximizeMenu(); } - updateDragResizeListener(oldDecorationSurface); - updateMaximizeMenu(startT); + updateDragResizeListener(oldDecorationSurface, inFullImmersive); + updateMaximizeMenu(startT, inFullImmersive); Trace.endSection(); // DesktopModeWindowDecoration#updateRelayoutParamsAndSurfaces } @@ -564,11 +571,12 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin return mUserContext.getUser(); } - private void updateDragResizeListener(SurfaceControl oldDecorationSurface) { - if (!isDragResizable(mTaskInfo)) { + private void updateDragResizeListener(SurfaceControl oldDecorationSurface, + boolean inFullImmersive) { + if (!isDragResizable(mTaskInfo, inFullImmersive)) { if (!mTaskInfo.positionInParent.equals(mPositionInParent)) { // We still want to track caption bar's exclusion region on a non-resizeable task. - updateExclusionRegion(); + updateExclusionRegion(inFullImmersive); } closeDragResizeListener(); return; @@ -602,11 +610,16 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin getResizeEdgeHandleSize(res), getResizeHandleEdgeInset(res), getFineResizeCornerSize(res), getLargeResizeCornerSize(res)), touchSlop) || !mTaskInfo.positionInParent.equals(mPositionInParent)) { - updateExclusionRegion(); + updateExclusionRegion(inFullImmersive); } } - private static boolean isDragResizable(ActivityManager.RunningTaskInfo taskInfo) { + private static boolean isDragResizable(ActivityManager.RunningTaskInfo taskInfo, + boolean inFullImmersive) { + if (inFullImmersive) { + // Task cannot be resized in full immersive. + return false; + } if (DesktopModeFlags.ENABLE_WINDOWING_SCALED_RESIZING.isTrue()) { return taskInfo.isFreeform(); } @@ -670,8 +683,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mWindowDecorCaptionHandleRepository.notifyCaptionChanged(captionState); } - private void updateMaximizeMenu(SurfaceControl.Transaction startT) { - if (!isDragResizable(mTaskInfo) || !isMaximizeMenuActive()) { + private void updateMaximizeMenu(SurfaceControl.Transaction startT, boolean inFullImmersive) { + if (!isDragResizable(mTaskInfo, inFullImmersive) || !isMaximizeMenuActive()) { return; } if (!mTaskInfo.isVisible()) { @@ -824,6 +837,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin WindowInsets.Type.systemBars() & ~WindowInsets.Type.captionBar(), false /* ignoreVisibility */); relayoutParams.mCaptionTopPadding = systemBarInsets.top; + relayoutParams.mIsInsetSource = false; } // Report occluding elements as bounding rects to the insets system so that apps can // draw in the empty space in the center: @@ -939,6 +953,33 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin return mHandleMenu != null; } + boolean isOpenByDefaultDialogActive() { + return mOpenByDefaultDialog != null; + } + + void createOpenByDefaultDialog() { + mOpenByDefaultDialog = new OpenByDefaultDialog( + mContext, + mTaskInfo, + mTaskSurface, + mDisplayController, + mSurfaceControlTransactionSupplier, + new OpenByDefaultDialog.DialogLifecycleListener() { + @Override + public void onDialogCreated() { + closeHandleMenu(); + } + + @Override + public void onDialogDismissed() { + mOpenByDefaultDialog = null; + } + }, + mAppIconBitmap, + mAppName + ); + } + boolean shouldResizeListenerHandleEvent(@NonNull MotionEvent e, @NonNull Point offset) { return mDragResizeListener != null && mDragResizeListener.shouldHandleEvent(e, offset); } @@ -1235,6 +1276,12 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin onCapturedLinkExpired(); return Unit.INSTANCE; }, + /* onOpenByDefaultClickListener= */ () -> { + if (!isOpenByDefaultDialogActive()) { + createOpenByDefaultDialog(); + } + return Unit.INSTANCE; + }, /* onCloseMenuClickListener= */ () -> { closeHandleMenu(); return Unit.INSTANCE; @@ -1505,24 +1552,29 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mPositionInParent.set(mTaskInfo.positionInParent); } - private void updateExclusionRegion() { + private void updateExclusionRegion(boolean inFullImmersive) { // An outdated position in parent is one reason for this to be called; update it here. updatePositionInParent(); mExclusionRegionListener - .onExclusionRegionChanged(mTaskInfo.taskId, getGlobalExclusionRegion()); + .onExclusionRegionChanged(mTaskInfo.taskId, + getGlobalExclusionRegion(inFullImmersive)); } /** * Create a new exclusion region from the corner rects (if resizeable) and caption bounds * of this task. */ - private Region getGlobalExclusionRegion() { + private Region getGlobalExclusionRegion(boolean inFullImmersive) { Region exclusionRegion; - if (mDragResizeListener != null && isDragResizable(mTaskInfo)) { + if (mDragResizeListener != null && isDragResizable(mTaskInfo, inFullImmersive)) { exclusionRegion = mDragResizeListener.getCornersRegion(); } else { exclusionRegion = new Region(); } + if (inFullImmersive) { + // Task can't be moved in full immersive, so skip excluding the caption region. + return exclusionRegion; + } exclusionRegion.union(new Rect(0, 0, mResult.mWidth, getCaptionHeight(mTaskInfo.getWindowingMode()))); exclusionRegion.translate(mPositionInParent.x, mPositionInParent.y); @@ -1590,7 +1642,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin @NonNull Context userContext, DisplayController displayController, SplitScreenController splitScreenController, - DesktopModeTaskRepository desktopRepository, + DesktopRepository desktopRepository, ShellTaskOrganizer taskOrganizer, ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java index 3853f1f086c1..f4c7fe3eac0c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java @@ -95,7 +95,8 @@ class FluidResizeTaskPositioner implements TaskPositioner, Transitions.Transitio mDragStartListener.onDragStart(mWindowDecoration.mTaskInfo.taskId); if (mCtrlType != CTRL_TYPE_UNDEFINED && !mWindowDecoration.mTaskInfo.isFocused) { WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.reorder(mWindowDecoration.mTaskInfo.token, true); + wct.reorder(mWindowDecoration.mTaskInfo.token, true /* onTop */, + true /* includingParents */); mTaskOrganizer.applyTransaction(wct); } mRepositionTaskBounds.set(mTaskBoundsAtDragStart); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt index 98fef4722d1c..2e327035bddf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt @@ -120,6 +120,7 @@ class HandleMenu( onNewWindowClickListener: () -> Unit, onManageWindowsClickListener: () -> Unit, openInBrowserClickListener: (Intent) -> Unit, + onOpenByDefaultClickListener: () -> Unit, onCloseMenuClickListener: () -> Unit, onOutsideTouchListener: () -> Unit, ) { @@ -135,6 +136,7 @@ class HandleMenu( onNewWindowClickListener = onNewWindowClickListener, onManageWindowsClickListener = onManageWindowsClickListener, openInBrowserClickListener = openInBrowserClickListener, + onOpenByDefaultClickListener = onOpenByDefaultClickListener, onCloseMenuClickListener = onCloseMenuClickListener, onOutsideTouchListener = onOutsideTouchListener, ) @@ -153,6 +155,7 @@ class HandleMenu( onNewWindowClickListener: () -> Unit, onManageWindowsClickListener: () -> Unit, openInBrowserClickListener: (Intent) -> Unit, + onOpenByDefaultClickListener: () -> Unit, onCloseMenuClickListener: () -> Unit, onOutsideTouchListener: () -> Unit ) { @@ -174,6 +177,7 @@ class HandleMenu( this.onOpenInBrowserClickListener = { openInBrowserClickListener.invoke(openInBrowserIntent!!) } + this.onOpenByDefaultClickListener = onOpenByDefaultClickListener this.onCloseMenuClickListener = onCloseMenuClickListener this.onOutsideTouchListener = onOutsideTouchListener } @@ -448,7 +452,8 @@ class HandleMenu( private val openInBrowserPill = rootView.requireViewById<View>(R.id.open_in_browser_pill) private val browserBtn = openInBrowserPill.requireViewById<Button>( R.id.open_in_browser_button) - + private val openByDefaultBtn = openInBrowserPill.requireViewById<ImageButton>( + R.id.open_by_default_button) private val decorThemeUtil = DecorThemeUtil(context) private val animator = HandleMenuAnimator(rootView, menuWidth, captionHeight.toFloat()) @@ -461,6 +466,7 @@ class HandleMenu( var onNewWindowClickListener: (() -> Unit)? = null var onManageWindowsClickListener: (() -> Unit)? = null var onOpenInBrowserClickListener: (() -> Unit)? = null + var onOpenByDefaultClickListener: (() -> Unit)? = null var onCloseMenuClickListener: (() -> Unit)? = null var onOutsideTouchListener: (() -> Unit)? = null @@ -469,6 +475,9 @@ class HandleMenu( splitscreenBtn.setOnClickListener { onToSplitScreenClickListener?.invoke() } desktopBtn.setOnClickListener { onToDesktopClickListener?.invoke() } browserBtn.setOnClickListener { onOpenInBrowserClickListener?.invoke() } + openByDefaultBtn.setOnClickListener { + onOpenByDefaultClickListener?.invoke() + } collapseMenuButton.setOnClickListener { onCloseMenuClickListener?.invoke() } newWindowBtn.setOnClickListener { onNewWindowClickListener?.invoke() } manageWindowBtn.setOnClickListener { onManageWindowsClickListener?.invoke() } @@ -634,6 +643,8 @@ class HandleMenu( setTextColor(style.textColor) compoundDrawableTintList = ColorStateList.valueOf(style.textColor) } + + openByDefaultBtn.imageTintList = ColorStateList.valueOf(style.textColor) } private data class MenuStyle( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java index 6eb5cca9ad1a..a1f76d2d1597 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java @@ -108,7 +108,8 @@ public class VeiledResizeTaskPositioner implements TaskPositioner, Transitions.T mDesktopWindowDecoration.mContext, mHandler, CUJ_DESKTOP_MODE_RESIZE_WINDOW); if (!mDesktopWindowDecoration.mTaskInfo.isFocused) { WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.reorder(mDesktopWindowDecoration.mTaskInfo.token, true); + wct.reorder(mDesktopWindowDecoration.mTaskInfo.token, true /* onTop */, + true /* includingParents */); mTaskOrganizer.applyTransaction(wct); } } 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 000beba125b0..f8aed412e3fb 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 @@ -346,7 +346,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> private void updateCaptionInsets(RelayoutParams params, WindowContainerTransaction wct, RelayoutResult<T> outResult, Rect taskBounds) { - if (!mIsCaptionVisible) { + if (!mIsCaptionVisible || !params.mIsInsetSource) { if (mWindowDecorationInsets != null) { mWindowDecorationInsets.remove(wct); mWindowDecorationInsets = null; @@ -724,6 +724,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> int mCaptionWidthId; final List<OccludingCaptionElement> mOccludingCaptionElements = new ArrayList<>(); int mInputFeatures; + boolean mIsInsetSource = true; @InsetsSource.Flags int mInsetSourceFlags; int mShadowRadiusId; @@ -743,6 +744,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> mCaptionWidthId = Resources.ID_NULL; mOccludingCaptionElements.clear(); mInputFeatures = 0; + mIsInsetSource = true; mInsetSourceFlags = 0; mShadowRadiusId = Resources.ID_NULL; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipController.kt index 98413ee96133..c61b31e7ba01 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipController.kt @@ -16,6 +16,7 @@ package com.android.wm.shell.windowdecor.education +import android.annotation.ColorInt import android.annotation.DimenRes import android.annotation.LayoutRes import android.content.Context @@ -30,9 +31,14 @@ import android.view.WindowManager import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView +import android.window.DisplayAreaInfo +import android.window.WindowContainerTransaction +import androidx.core.graphics.drawable.DrawableCompat import androidx.dynamicanimation.animation.DynamicAnimation import androidx.dynamicanimation.animation.SpringForce import com.android.wm.shell.R +import com.android.wm.shell.common.DisplayChangeController.OnDisplayChangingListener +import com.android.wm.shell.common.DisplayController import com.android.wm.shell.shared.animation.PhysicsAnimator import com.android.wm.shell.windowdecor.WindowManagerWrapper import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer @@ -44,7 +50,8 @@ import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystem class DesktopWindowingEducationTooltipController( private val context: Context, private val additionalSystemViewContainerFactory: AdditionalSystemViewContainer.Factory, -) { + private val displayController: DisplayController, +) : OnDisplayChangingListener { // TODO: b/369384567 - Set tooltip color scheme to match LT/DT of app theme private var tooltipView: View? = null private var animator: PhysicsAnimator<View>? = null @@ -53,6 +60,20 @@ class DesktopWindowingEducationTooltipController( } private var popupWindow: AdditionalSystemViewContainer? = null + override fun onDisplayChange( + displayId: Int, + fromRotation: Int, + toRotation: Int, + newDisplayAreaInfo: DisplayAreaInfo?, + t: WindowContainerTransaction? + ) { + // Exit if the rotation hasn't changed or is changed by 180 degrees. [fromRotation] and + // [toRotation] can be one of the [@Surface.Rotation] values. + if ((fromRotation % 2 == toRotation % 2)) return + hideEducationTooltip() + // TODO: b/370820018 - Update tooltip position on orientation change instead of dismissing + } + /** * Shows education tooltip. * @@ -64,6 +85,7 @@ class DesktopWindowingEducationTooltipController( tooltipView = createEducationTooltipView(tooltipViewConfig, taskId) animator = createAnimator() animateShowTooltipTransition() + displayController.addDisplayChangingController(this) } /** Hide the current education view if visible */ @@ -100,6 +122,7 @@ class DesktopWindowingEducationTooltipController( hideEducationTooltip() tooltipViewConfig.onEducationClickAction() } + setTooltipColorScheme(tooltipViewConfig.tooltipColorScheme) } val tooltipDimens = tooltipDimens(tooltipView = tooltipView, tooltipViewConfig.arrowDirection) @@ -145,6 +168,7 @@ class DesktopWindowingEducationTooltipController( animator = null popupWindow?.releaseView() popupWindow = null + displayController.removeDisplayChangingController(this) } private fun createTooltipPopupWindow( @@ -168,6 +192,21 @@ class DesktopWindowingEducationTooltipController( view = tooltipView) } + private fun View.setTooltipColorScheme(tooltipColorScheme: TooltipColorScheme) { + requireViewById<LinearLayout>(R.id.tooltip_container).apply { + background.setTint(tooltipColorScheme.container) + } + requireViewById<ImageView>(R.id.arrow_icon).apply { + val wrappedDrawable = DrawableCompat.wrap(this.drawable) + DrawableCompat.setTint(wrappedDrawable, tooltipColorScheme.container) + } + requireViewById<TextView>(R.id.tooltip_text).apply { setTextColor(tooltipColorScheme.text) } + requireViewById<ImageView>(R.id.tooltip_icon).apply { + val wrappedDrawable = DrawableCompat.wrap(this.drawable) + DrawableCompat.setTint(wrappedDrawable, tooltipColorScheme.icon) + } + } + private fun tooltipViewGlobalCoordinates( tooltipViewGlobalCoordinates: Point, arrowDirection: TooltipArrowDirection, @@ -234,6 +273,7 @@ class DesktopWindowingEducationTooltipController( */ data class EducationViewConfig( @LayoutRes val tooltipViewLayout: Int, + val tooltipColorScheme: TooltipColorScheme, val tooltipViewGlobalCoordinates: Point, val tooltipText: String, val arrowDirection: TooltipArrowDirection, @@ -241,6 +281,19 @@ class DesktopWindowingEducationTooltipController( val onDismissAction: () -> Unit, ) + /** + * Color scheme of education view: + * + * @property container Color of the container of the tooltip. + * @property text Text color of the [TextView] of education tooltip. + * @property icon Color to be filled in tooltip's icon. + */ + data class TooltipColorScheme( + @ColorInt val container: Int, + @ColorInt val text: Int, + @ColorInt val icon: Int, + ) + /** Direction of arrow of the tooltip */ enum class TooltipArrowDirection { UP, diff --git a/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/Android.bp b/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/Android.bp index a231e381beda..176020ffc3b9 100644 --- a/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/Android.bp +++ b/libs/WindowManager/Shell/tests/e2e/splitscreen/flicker-legacy/Android.bp @@ -69,116 +69,6 @@ android_test { } //////////////////////////////////////////////////////////////////////////////// -// Begin cleanup after gcl merges - -filegroup { - name: "WMShellFlickerTestsSplitScreenGroup1-src", - srcs: [ - "src/**/A*.kt", - "src/**/B*.kt", - "src/**/C*.kt", - "src/**/D*.kt", - ], -} - -filegroup { - name: "WMShellFlickerTestsSplitScreenGroup2-src", - srcs: [ - "src/**/E*.kt", - ], -} - -filegroup { - name: "WMShellFlickerTestsSplitScreenGroup3-src", - srcs: [ - "src/**/S*.kt", - ], -} - -filegroup { - name: "WMShellFlickerTestsSplitScreenGroupOther-src", - srcs: [ - "src/**/*.kt", - ], -} - -android_test { - name: "WMShellFlickerTestsSplitScreenGroup1", - defaults: ["WMShellFlickerTestsDefault"], - manifest: "AndroidManifest.xml", - package_name: "com.android.wm.shell.flicker.splitscreen", - instrumentation_target_package: "com.android.wm.shell.flicker.splitscreen", - test_config_template: "AndroidTestTemplate.xml", - srcs: [ - ":WMShellFlickerTestsSplitScreenGroup1-src", - ], - static_libs: [ - "WMShellFlickerTestsBase", - "WMShellFlickerTestsSplitScreenBase", - ], - data: ["trace_config/*"], -} - -android_test { - name: "WMShellFlickerTestsSplitScreenGroup2", - defaults: ["WMShellFlickerTestsDefault"], - manifest: "AndroidManifest.xml", - package_name: "com.android.wm.shell.flicker.splitscreen", - instrumentation_target_package: "com.android.wm.shell.flicker.splitscreen", - test_config_template: "AndroidTestTemplate.xml", - srcs: [ - ":WMShellFlickerTestsSplitScreenGroup2-src", - ], - static_libs: [ - "WMShellFlickerTestsBase", - "WMShellFlickerTestsSplitScreenBase", - ], - data: ["trace_config/*"], -} - -android_test { - name: "WMShellFlickerTestsSplitScreenGroup3", - defaults: ["WMShellFlickerTestsDefault"], - manifest: "AndroidManifest.xml", - package_name: "com.android.wm.shell.flicker.splitscreen", - instrumentation_target_package: "com.android.wm.shell.flicker.splitscreen", - test_config_template: "AndroidTestTemplate.xml", - srcs: [ - ":WMShellFlickerTestsSplitScreenGroup3-src", - ], - static_libs: [ - "WMShellFlickerTestsBase", - "WMShellFlickerTestsSplitScreenBase", - ], - data: ["trace_config/*"], -} - -android_test { - name: "WMShellFlickerTestsSplitScreenGroupOther", - defaults: ["WMShellFlickerTestsDefault"], - manifest: "AndroidManifest.xml", - package_name: "com.android.wm.shell.flicker.splitscreen", - instrumentation_target_package: "com.android.wm.shell.flicker.splitscreen", - test_config_template: "AndroidTestTemplate.xml", - srcs: [ - ":WMShellFlickerTestsSplitScreenGroupOther-src", - ], - exclude_srcs: [ - ":WMShellFlickerTestsSplitScreenGroup1-src", - ":WMShellFlickerTestsSplitScreenGroup2-src", - ":WMShellFlickerTestsSplitScreenGroup3-src", - ], - static_libs: [ - "WMShellFlickerTestsBase", - "WMShellFlickerTestsSplitScreenBase", - ], - data: ["trace_config/*"], -} - -//////////////////////////////////////////////////////////////////////////////// -// End cleanup after gcl merges - -//////////////////////////////////////////////////////////////////////////////// // Begin breakdowns for FlickerTestsRotation module test_module_config { diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/Android.bp b/libs/WindowManager/Shell/tests/flicker/appcompat/Android.bp index 29a9f1050b25..b016c9f94133 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/Android.bp +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/Android.bp @@ -15,7 +15,7 @@ // package { - default_team: "trendy_team_app_compat", + default_team: "trendy_team_lse_app_compat", // 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" @@ -24,31 +24,6 @@ package { default_applicable_licenses: ["frameworks_base_license"], } -//////////////////////////////////////////////////////////////////////////////// -// Begin cleanup after gcl merge - -filegroup { - name: "WMShellFlickerTestsAppCompat-src", - srcs: [ - "src/**/*.kt", - ], -} - -android_test { - name: "WMShellFlickerTestsOther", - defaults: ["WMShellFlickerTestsDefault"], - manifest: "AndroidManifest.xml", - package_name: "com.android.wm.shell.flicker", - instrumentation_target_package: "com.android.wm.shell.flicker", - test_config_template: "AndroidTestTemplate.xml", - srcs: [":WMShellFlickerTestsAppCompat-src"], - static_libs: ["WMShellFlickerTestsBase"], - data: ["trace_config/*"], -} - -//////////////////////////////////////////////////////////////////////////////// -// End cleanup after gcl merge - android_test { name: "WMShellFlickerTestsAppCompat", defaults: ["WMShellFlickerTestsDefault"], diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt index 16c2d47f9db3..27303c1889c9 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt @@ -31,7 +31,7 @@ import org.junit.runners.Parameterized /** * Test launching app in size compat mode. * - * To run this test: `atest WMShellFlickerTestsOther:OpenAppInSizeCompatModeTest` + * To run this test: `atest WMShellFlickerTestsAppCompat:OpenAppInSizeCompatModeTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenTransparentActivityTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenTransparentActivityTest.kt index d85b7718aa56..2980d5113bba 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenTransparentActivityTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/OpenTransparentActivityTest.kt @@ -32,7 +32,7 @@ import org.junit.runners.Parameterized /** * Test launching app in size compat mode. * - * To run this test: `atest WMShellFlickerTestsOther:OpenTransparentActivityTest` + * To run this test: `atest WMShellFlickerTestsAppCompat:OpenTransparentActivityTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/QuickSwitchLauncherToLetterboxAppTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/QuickSwitchLauncherToLetterboxAppTest.kt index 164534c14d28..2484f675b236 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/QuickSwitchLauncherToLetterboxAppTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/QuickSwitchLauncherToLetterboxAppTest.kt @@ -36,7 +36,7 @@ import org.junit.runners.Parameterized /** * Test quick switching to letterboxed app from launcher * - * To run this test: `atest WMShellFlickerTestsOther:QuickSwitchLauncherToLetterboxAppTest` + * To run this test: `atest WMShellFlickerTestsAppCompat:QuickSwitchLauncherToLetterboxAppTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt index 034d54b185ed..77423af667f7 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RepositionFixedPortraitAppTest.kt @@ -32,7 +32,7 @@ import org.junit.runners.Parameterized /** * Test launching a fixed portrait letterboxed app in landscape and repositioning to the right. * - * To run this test: `atest WMShellFlickerTestsOther:RepositionFixedPortraitAppTest` + * To run this test: `atest WMShellFlickerTestsAppCompat:RepositionFixedPortraitAppTest` * * Actions: * diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt index 443fac19c7e7..5459ef03e360 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt @@ -31,7 +31,7 @@ import org.junit.runners.Parameterized /** * Test restarting app in size compat mode. * - * To run this test: `atest WMShellFlickerTestsOther:RestartAppInSizeCompatModeTest` + * To run this test: `atest WMShellFlickerTestsAppCompat:RestartAppInSizeCompatModeTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RotateImmersiveAppInFullscreenTest.kt b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RotateImmersiveAppInFullscreenTest.kt index 22543aa9f773..5bb96401bc86 100644 --- a/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RotateImmersiveAppInFullscreenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/appcompat/src/com/android/wm/shell/flicker/appcompat/RotateImmersiveAppInFullscreenTest.kt @@ -45,7 +45,7 @@ import org.junit.runners.Parameterized /** * Test rotating an immersive app in fullscreen. * - * To run this test: `atest WMShellFlickerTestsOther:RotateImmersiveAppInFullscreenTest` + * To run this test: `atest WMShellFlickerTestsAppCompat:RotateImmersiveAppInFullscreenTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp index 4165ed093929..ddbc681f7cac 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp +++ b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp @@ -29,92 +29,12 @@ filegroup { srcs: ["src/**/apps/*.kt"], } -//////////////////////////////////////////////////////////////////////////////// -// Begin cleanup after gcl merges - -filegroup { - name: "WMShellFlickerTestsPip1-src", - srcs: [ - "src/**/A*.kt", - "src/**/B*.kt", - "src/**/C*.kt", - "src/**/D*.kt", - "src/**/F*.kt", - "src/**/S*.kt", - ], -} - -filegroup { - name: "WMShellFlickerTestsPip2-src", - srcs: [ - "src/**/E*.kt", - ], -} - -filegroup { - name: "WMShellFlickerTestsPip3-src", - srcs: ["src/**/*.kt"], -} - filegroup { name: "WMShellFlickerTestsPipCommon-src", srcs: ["src/**/common/*.kt"], } android_test { - name: "WMShellFlickerTestsPip1", - defaults: ["WMShellFlickerTestsDefault"], - manifest: "AndroidManifest.xml", - package_name: "com.android.wm.shell.flicker.pip", - instrumentation_target_package: "com.android.wm.shell.flicker.pip", - test_config_template: "AndroidTestTemplate.xml", - srcs: [ - ":WMShellFlickerTestsPip1-src", - ":WMShellFlickerTestsPipCommon-src", - ], - static_libs: ["WMShellFlickerTestsBase"], - data: ["trace_config/*"], -} - -android_test { - name: "WMShellFlickerTestsPip2", - defaults: ["WMShellFlickerTestsDefault"], - manifest: "AndroidManifest.xml", - package_name: "com.android.wm.shell.flicker.pip", - instrumentation_target_package: "com.android.wm.shell.flicker.pip", - test_config_template: "AndroidTestTemplate.xml", - srcs: [ - ":WMShellFlickerTestsPip2-src", - ":WMShellFlickerTestsPipCommon-src", - ], - static_libs: ["WMShellFlickerTestsBase"], - data: ["trace_config/*"], -} - -android_test { - name: "WMShellFlickerTestsPip3", - defaults: ["WMShellFlickerTestsDefault"], - manifest: "AndroidManifest.xml", - package_name: "com.android.wm.shell.flicker.pip", - instrumentation_target_package: "com.android.wm.shell.flicker.pip", - test_config_template: "AndroidTestTemplate.xml", - srcs: [ - ":WMShellFlickerTestsPip3-src", - ":WMShellFlickerTestsPipCommon-src", - ], - exclude_srcs: [ - ":WMShellFlickerTestsPip1-src", - ":WMShellFlickerTestsPip2-src", - ":WMShellFlickerTestsPipApps-src", - ], - static_libs: ["WMShellFlickerTestsBase"], - data: ["trace_config/*"], -} - -//////////////////////////////////////////////////////////////////////////////// -// End cleanup after gcl merges - -android_test { name: "WMShellFlickerTestsPip", defaults: ["WMShellFlickerTestsDefault"], manifest: "AndroidManifest.xml", @@ -122,6 +42,7 @@ android_test { instrumentation_target_package: "com.android.wm.shell.flicker.pip", test_config_template: "AndroidTestTemplate.xml", srcs: ["src/**/*.kt"], + exclude_srcs: [":WMShellFlickerTestsPipApps-src"], static_libs: ["WMShellFlickerTestsBase"], data: ["trace_config/*"], } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt index a9ed13a099f3..a248303b1c33 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt @@ -38,7 +38,7 @@ import kotlin.math.abs /** * Test entering pip from an app via auto-enter property when navigating to home. * - * To run this test: `atest WMShellFlickerTestsPip1:AutoEnterPipOnGoToHomeTest` + * To run this test: `atest WMShellFlickerTestsPip:AutoEnterPipOnGoToHomeTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt index d059211088aa..df952c925720 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipWithSourceRectHintTest.kt @@ -30,7 +30,7 @@ import org.junit.runners.Parameterized /** * Test auto entering pip using a source rect hint. * - * To run this test: `atest WMShellFlickerTestsPip1:AutoEnterPipWithSourceRectHintTest` + * To run this test: `atest WMShellFlickerTestsPip:AutoEnterPipWithSourceRectHintTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt index 3ffc9d7b87f6..302b8c414979 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt @@ -32,7 +32,7 @@ import org.junit.runners.Parameterized /** * Test closing a pip window by swiping it to the bottom-center of the screen * - * To run this test: `atest WMShellFlickerTestsPip1:ClosePipBySwipingDownTest` + * To run this test: `atest WMShellFlickerTestsPip:ClosePipBySwipingDownTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt index d177624378c1..77a1edb7039a 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt @@ -30,7 +30,7 @@ import org.junit.runners.Parameterized /** * Test closing a pip window via the dismiss button * - * To run this test: `atest WMShellFlickerTestsPip1:ClosePipWithDismissButtonTest` + * To run this test: `atest WMShellFlickerTestsPip:ClosePipWithDismissButtonTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt index a86803d058f8..6e32d6412b50 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt @@ -31,7 +31,7 @@ import org.junit.runners.Parameterized /** * Test entering pip from an app via [onUserLeaveHint] and by navigating to home. * - * To run this test: `atest WMShellFlickerTestsPip2:EnterPipOnUserLeaveHintTest` + * To run this test: `atest WMShellFlickerTestsPip:EnterPipOnUserLeaveHintTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt index d0e8215e662e..9a6cb61cfc66 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt @@ -46,7 +46,7 @@ import org.junit.runners.Parameterized /** * Test entering pip while changing orientation (from app in landscape to pip window in portrait) * - * To run this test: `atest WMShellFlickerTestsPip2:EnterPipToOtherOrientation` + * To run this test: `atest WMShellFlickerTestsPip:EnterPipToOtherOrientation` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt index d92f55af578f..6b4751cee3bb 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt @@ -28,7 +28,7 @@ import org.junit.runners.Parameterized /** * Test entering pip from an app by interacting with the app UI * - * To run this test: `atest WMShellFlickerTestsPip2:EnterPipViaAppUiButtonTest` + * To run this test: `atest WMShellFlickerTestsPip:EnterPipViaAppUiButtonTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt index 8c0817d6e287..8d0bc0f5a155 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt @@ -28,7 +28,7 @@ import org.junit.runners.Parameterized /** * Test expanding a pip window back to full screen via the expand button * - * To run this test: `atest WMShellFlickerTestsPip2:ExitPipToAppViaExpandButtonTest` + * To run this test: `atest WMShellFlickerTestsPip:ExitPipToAppViaExpandButtonTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt index 90a9623056ce..939f3280d2e6 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt @@ -28,7 +28,7 @@ import org.junit.runners.Parameterized /** * Test expanding a pip window back to full screen via an intent * - * To run this test: `atest WMShellFlickerTestsPip2:ExitPipToAppViaIntentTest` + * To run this test: `atest WMShellFlickerTestsPip:ExitPipToAppViaIntentTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt index 9306c77a1c43..258663b5556d 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt @@ -33,7 +33,7 @@ import org.junit.runners.Parameterized /** * Test expanding a pip window by double-clicking it * - * To run this test: `atest WMShellFlickerTestsPip2:ExpandPipOnDoubleClickTest` + * To run this test: `atest WMShellFlickerTestsPip:ExpandPipOnDoubleClickTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt index cb8ee27f29e2..5f8ac2af241b 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenAutoEnterPipOnGoToHomeTest.kt @@ -39,7 +39,7 @@ import org.junit.runners.Parameterized /** * Test entering pip from an app via auto-enter property when navigating to home from split screen. * - * To run this test: `atest WMShellFlickerTestsPip1:FromSplitScreenAutoEnterPipOnGoToHomeTest` + * To run this test: `atest WMShellFlickerTestsPip:FromSplitScreenAutoEnterPipOnGoToHomeTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt index d03d7799d675..48c85a84e556 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt @@ -40,7 +40,7 @@ import org.junit.runners.Parameterized /** * Test entering pip from an app via auto-enter property when navigating to home from split screen. * - * To run this test: `atest WMShellFlickerTestsPip1:FromSplitScreenEnterPipOnUserLeaveHintTest` + * To run this test: `atest WMShellFlickerTestsPip:FromSplitScreenEnterPipOnUserLeaveHintTest` * * Actions: * ``` @@ -183,12 +183,6 @@ class FromSplitScreenEnterPipOnUserLeaveHintTest(flicker: LegacyFlickerTest) : } /** {@inheritDoc} */ - @FlakyTest(bugId = 312446524) - @Test - override fun visibleLayersShownMoreThanOneConsecutiveEntry() = - super.visibleLayersShownMoreThanOneConsecutiveEntry() - - /** {@inheritDoc} */ @Test @FlakyTest(bugId = 336510055) override fun entireScreenCovered() { diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt index 265eb4416a2b..ee62cf59b2f9 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt @@ -32,7 +32,7 @@ import org.junit.runners.Parameterized /** * Test Pip movement with Launcher shelf height change (increase). * - * To run this test: `atest WMShellFlickerTestsPip3:MovePipDownOnShelfHeightChange` + * To run this test: `atest WMShellFlickerTestsPip:MovePipDownOnShelfHeightChange` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt index 8d6be64da21d..4d643f7b4408 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt @@ -32,7 +32,7 @@ import org.junit.runners.Parameterized /** * Test Pip movement with Launcher shelf height change (decrease). * - * To run this test: `atest WMShellFlickerTestsPip3:MovePipUpOnShelfHeightChangeTest` + * To run this test: `atest WMShellFlickerTestsPip:MovePipUpOnShelfHeightChangeTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt index 9109eafacf63..c6cf3411835c 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt @@ -35,7 +35,7 @@ import org.junit.runners.Parameterized /** * Test Pip Stack in bounds after rotations. * - * To run this test: `atest WMShellFlickerTestsPip1:ShowPipAndRotateDisplay` + * To run this test: `atest WMShellFlickerTestsPip:ShowPipAndRotateDisplay` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt index 1fc9d9910a15..7b04b766a191 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt @@ -40,7 +40,7 @@ import org.junit.runners.Parameterized /** * Test entering pip from Maps app by interacting with the app UI * - * To run this test: `atest WMShellFlickerTests:MapsEnterPipTest` + * To run this test: `atest WMShellFlickerTestsPipAppsCSuite:MapsEnterPipTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt index 68fa7c7af740..691194609343 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/NetflixEnterPipTest.kt @@ -38,7 +38,7 @@ import org.junit.runners.Parameterized /** * Test entering pip from Netflix app by interacting with the app UI * - * To run this test: `atest WMShellFlickerTests:NetflixEnterPipTest` + * To run this test: `atest WMShellFlickerTestsPipAppsCSuite:NetflixEnterPipTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipTest.kt index 7873a85d515d..5e54f30dae8a 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipTest.kt @@ -34,7 +34,7 @@ import org.junit.runners.Parameterized /** * Test entering pip from YouTube app by interacting with the app UI * - * To run this test: `atest WMShellFlickerTests:YouTubeEnterPipTest` + * To run this test: `atest WMShellFlickerTestsPipAppsCSuite:YouTubeEnterPipTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipToOtherOrientationTest.kt index 72be3d85ec8b..159cba4a559e 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipToOtherOrientationTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/YouTubeEnterPipToOtherOrientationTest.kt @@ -38,7 +38,7 @@ import org.junit.runners.Parameterized /** * Test entering pip from YouTube app by interacting with the app UI * - * To run this test: `atest WMShellFlickerTests:YouTubeEnterPipTest` + * To run this test: `atest WMShellFlickerTestsPipAppsCSuite:YouTubeEnterPipTest` * * Actions: * ``` diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt index 8a073abf032c..6a84b2803d8c 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt @@ -25,7 +25,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized -/** Test Pip Menu on TV. To run this test: `atest WMShellFlickerTests:TvPipBasicTest` */ +/** Test Pip Menu on TV. To run this test: `atest WMShellFlickerTestsPip:TvPipBasicTest` */ @RequiresDevice @RunWith(Parameterized::class) class TvPipBasicTest(private val radioButtonId: String, private val pipWindowRatio: Rational?) : diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt index d4cd6da4acb1..09e8745a0224 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt @@ -27,7 +27,7 @@ import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test -/** Test Pip Menu on TV. To run this test: `atest WMShellFlickerTests:TvPipMenuTests` */ +/** Test Pip Menu on TV. To run this test: `atest WMShellFlickerTestsPip:TvPipMenuTests` */ @RequiresDevice class TvPipMenuTests : TvPipTestBase() { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java index 227060d15640..dee0b23a42f5 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java @@ -860,15 +860,9 @@ public class BackAnimationControllerTest extends ShellTestCase { } private void doMotionEvent(int actionDown, int coordinate) { - doMotionEvent(actionDown, coordinate, 0); - } - - private void doMotionEvent(int actionDown, int coordinate, float velocity) { mController.onMotionEvent( /* touchX */ coordinate, /* touchY */ coordinate, - /* velocityX = */ velocity, - /* velocityY = */ velocity, /* keyAction */ actionDown, /* swipeEdge */ BackEvent.EDGE_LEFT); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java index 9b019ddb8362..1da4ef6b5a8b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java @@ -54,8 +54,6 @@ public class BackProgressAnimatorTest { /* touchX = */ touchX, /* touchY = */ 0, /* progress = */ progress, - /* velocityX = */ 0, - /* velocityY = */ 0, /* triggerBack = */ false, /* swipeEdge = */ BackEvent.EDGE_LEFT, /* departingAnimationTarget = */ null); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomCrossActivityBackAnimationTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomCrossActivityBackAnimationTest.kt index 5b5ef6f48789..2235c20d7f21 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomCrossActivityBackAnimationTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomCrossActivityBackAnimationTest.kt @@ -222,8 +222,6 @@ class CustomCrossActivityBackAnimationTest : ShellTestCase() { /* touchX = */ touchX, /* touchY = */ 0f, /* progress = */ progress, - /* velocityX = */ 0f, - /* velocityY = */ 0f, /* triggerBack = */ false, /* swipeEdge = */ BackEvent.EDGE_LEFT, /* departingAnimationTarget = */ null 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 f8f0db930e6c..0373bbd43043 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 @@ -26,6 +26,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; @@ -34,6 +36,12 @@ import static org.mockito.Mockito.verifyZeroInteractions; import android.graphics.Insets; import android.graphics.Point; +import android.os.Looper; +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.view.IWindowManager; import android.view.InsetsSource; import android.view.InsetsSourceControl; import android.view.InsetsState; @@ -47,6 +55,7 @@ import com.android.wm.shell.shared.TransactionPool; import com.android.wm.shell.sysui.ShellInit; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -61,11 +70,16 @@ import java.util.concurrent.Executor; */ @SmallTest public class DisplayImeControllerTest extends ShellTestCase { + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Mock private SurfaceControl.Transaction mT; @Mock private ShellInit mShellInit; + @Mock + private IWindowManager mWm; + private DisplayImeController mDisplayImeController; private DisplayImeController.PerDisplay mPerDisplay; private Executor mExecutor; @@ -73,7 +87,8 @@ public class DisplayImeControllerTest extends ShellTestCase { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mExecutor = spy(Runnable::run); - mPerDisplay = new DisplayImeController(null, mShellInit, null, null, new TransactionPool() { + mDisplayImeController = new DisplayImeController(mWm, mShellInit, null, null, + new TransactionPool() { @Override public SurfaceControl.Transaction acquire() { return mT; @@ -84,8 +99,10 @@ public class DisplayImeControllerTest extends ShellTestCase { } }, mExecutor) { @Override - void removeImeSurface(int displayId) { } - }.new PerDisplay(DEFAULT_DISPLAY, ROTATION_0); + void removeImeSurface(int displayId) { + } + }; + mPerDisplay = mDisplayImeController.new PerDisplay(DEFAULT_DISPLAY, ROTATION_0); } @Test @@ -95,12 +112,14 @@ public class DisplayImeControllerTest extends ShellTestCase { @Test public void insetsControlChanged_schedulesNoWorkOnExecutor() { + Looper.prepare(); mPerDisplay.insetsControlChanged(insetsStateWithIme(false), insetsSourceControl()); verifyZeroInteractions(mExecutor); } @Test public void insetsChanged_schedulesNoWorkOnExecutor() { + Looper.prepare(); mPerDisplay.insetsChanged(insetsStateWithIme(false)); verifyZeroInteractions(mExecutor); } @@ -117,7 +136,10 @@ public class DisplayImeControllerTest extends ShellTestCase { verifyZeroInteractions(mExecutor); } + // With the refactor, the control's isInitiallyVisible is used to apply to the IME, therefore + // this test is obsolete @Test + @RequiresFlagsDisabled(android.view.inputmethod.Flags.FLAG_REFACTOR_INSETS_CONTROLLER) public void reappliesVisibilityToChangedLeash() { verifyZeroInteractions(mT); mPerDisplay.mImeShowing = false; @@ -136,6 +158,7 @@ public class DisplayImeControllerTest extends ShellTestCase { @Test public void insetsControlChanged_updateImeSourceControl() { + Looper.prepare(); mPerDisplay.insetsControlChanged(insetsStateWithIme(false), insetsSourceControl()); assertNotNull(mPerDisplay.mImeSourceControl); @@ -143,6 +166,19 @@ public class DisplayImeControllerTest extends ShellTestCase { assertNull(mPerDisplay.mImeSourceControl); } + @Test + @RequiresFlagsEnabled(android.view.inputmethod.Flags.FLAG_REFACTOR_INSETS_CONTROLLER) + public void setImeInputTargetRequestedVisibility_invokeOnImeRequested() { + var mockPp = mock(DisplayImeController.ImePositionProcessor.class); + mDisplayImeController.addPositionProcessor(mockPp); + + mPerDisplay.setImeInputTargetRequestedVisibility(true); + verify(mockPp).onImeRequested(anyInt(), eq(true)); + + mPerDisplay.setImeInputTargetRequestedVisibility(false); + verify(mockPp).onImeRequested(anyInt(), eq(false)); + } + private InsetsSourceControl[] insetsSourceControl() { return new InsetsSourceControl[]{ new InsetsSourceControl( diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt index 628c9cdd9339..3e9c732b9c3b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopActivityOrientationChangeHandlerTest.kt @@ -98,7 +98,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { private lateinit var mockitoSession: StaticMockitoSession private lateinit var handler: DesktopActivityOrientationChangeHandler private lateinit var shellInit: ShellInit - private lateinit var taskRepository: DesktopModeTaskRepository + private lateinit var taskRepository: DesktopRepository private lateinit var testScope: CoroutineScope // Mock running tasks are registered here so we can get the list from mock shell task organizer. private val runningTasks = mutableListOf<RunningTaskInfo>() @@ -116,7 +116,7 @@ class DesktopActivityOrientationChangeHandlerTest : ShellTestCase() { testScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob()) shellInit = spy(ShellInit(testExecutor)) taskRepository = - DesktopModeTaskRepository(context, shellInit, persistentRepository, testScope) + DesktopRepository(context, shellInit, persistentRepository, testScope) whenever(shellTaskOrganizer.getRunningTasks(anyInt())).thenAnswer { runningTasks } whenever(transitions.startTransition(anyInt(), any(), isNull())).thenAnswer { Binder() } whenever(runBlocking { persistentRepository.readDesktop(any(), any()) }).thenReturn( diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandlerTest.kt new file mode 100644 index 000000000000..cae609526c65 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandlerTest.kt @@ -0,0 +1,132 @@ +/* + * 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.os.IBinder +import android.testing.AndroidTestingRunner +import android.view.SurfaceControl +import android.view.WindowManager.TRANSIT_CHANGE +import android.window.WindowContainerTransaction +import androidx.test.filters.SmallTest +import com.android.wm.shell.ShellTestCase +import com.android.wm.shell.TestShellExecutor +import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask +import com.android.wm.shell.sysui.ShellInit +import com.android.wm.shell.transition.Transitions +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.mock +import org.mockito.kotlin.mock +import org.mockito.kotlin.times +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +/** + * Tests for [DesktopFullImmersiveTransitionHandler]. + * + * Usage: atest WMShellUnitTests:DesktopFullImmersiveTransitionHandler + */ +@SmallTest +@RunWith(AndroidTestingRunner::class) +class DesktopFullImmersiveTransitionHandlerTest : ShellTestCase() { + + @Mock private lateinit var mockTransitions: Transitions + private lateinit var desktopRepository: DesktopRepository + private val transactionSupplier = { SurfaceControl.Transaction() } + + private lateinit var immersiveHandler: DesktopFullImmersiveTransitionHandler + + @Before + fun setUp() { + desktopRepository = DesktopRepository( + context, ShellInit(TestShellExecutor()), mock(), mock() + ) + immersiveHandler = DesktopFullImmersiveTransitionHandler( + transitions = mockTransitions, + desktopRepository = desktopRepository, + transactionSupplier = transactionSupplier + ) + } + + @Test + fun enterImmersive_transitionReady_updatesRepository() { + val task = createFreeformTask() + val wct = WindowContainerTransaction() + val mockBinder = mock(IBinder::class.java) + whenever(mockTransitions.startTransition(TRANSIT_CHANGE, wct, immersiveHandler)) + .thenReturn(mockBinder) + desktopRepository.setTaskInFullImmersiveState( + displayId = task.displayId, + taskId = task.taskId, + immersive = false + ) + + immersiveHandler.enterImmersive(task, wct) + immersiveHandler.onTransitionReady(mockBinder) + + assertThat(desktopRepository.isTaskInFullImmersiveState(task.taskId)).isTrue() + } + + @Test + fun exitImmersive_transitionReady_updatesRepository() { + val task = createFreeformTask() + val wct = WindowContainerTransaction() + val mockBinder = mock(IBinder::class.java) + whenever(mockTransitions.startTransition(TRANSIT_CHANGE, wct, immersiveHandler)) + .thenReturn(mockBinder) + desktopRepository.setTaskInFullImmersiveState( + displayId = task.displayId, + taskId = task.taskId, + immersive = true + ) + + immersiveHandler.exitImmersive(task, wct) + immersiveHandler.onTransitionReady(mockBinder) + + assertThat(desktopRepository.isTaskInFullImmersiveState(task.taskId)).isFalse() + } + + @Test + fun enterImmersive_inProgress_ignores() { + val task = createFreeformTask() + val wct = WindowContainerTransaction() + val mockBinder = mock(IBinder::class.java) + whenever(mockTransitions.startTransition(TRANSIT_CHANGE, wct, immersiveHandler)) + .thenReturn(mockBinder) + + immersiveHandler.enterImmersive(task, wct) + immersiveHandler.enterImmersive(task, wct) + + verify(mockTransitions, times(1)).startTransition(TRANSIT_CHANGE, wct, immersiveHandler) + } + + @Test + fun exitImmersive_inProgress_ignores() { + val task = createFreeformTask() + val wct = WindowContainerTransaction() + val mockBinder = mock(IBinder::class.java) + whenever(mockTransitions.startTransition(TRANSIT_CHANGE, wct, immersiveHandler)) + .thenReturn(mockBinder) + + immersiveHandler.exitImmersive(task, wct) + immersiveHandler.exitImmersive(task, wct) + + verify(mockTransitions, times(1)).startTransition(TRANSIT_CHANGE, wct, immersiveHandler) + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt index 2b60200f06ad..07de0716200c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt @@ -60,7 +60,7 @@ import org.mockito.kotlin.whenever class DesktopMixedTransitionHandlerTest : ShellTestCase() { @Mock lateinit var transitions: Transitions - @Mock lateinit var desktopTaskRepository: DesktopModeTaskRepository + @Mock lateinit var desktopRepository: DesktopRepository @Mock lateinit var freeformTaskTransitionHandler: FreeformTaskTransitionHandler @Mock lateinit var closeDesktopTaskTransitionHandler: CloseDesktopTaskTransitionHandler @Mock lateinit var interactionJankMonitor: InteractionJankMonitor @@ -75,7 +75,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() { DesktopMixedTransitionHandler( context, transitions, - desktopTaskRepository, + desktopRepository, freeformTaskTransitionHandler, closeDesktopTaskTransitionHandler, interactionJankMonitor, @@ -144,7 +144,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() { fun startAnimation_withClosingDesktopTask_callsCloseTaskHandler() { val transition = mock<IBinder>() val transitionInfo = createTransitionInfo(task = createTask(WINDOWING_MODE_FREEFORM)) - whenever(desktopTaskRepository.getActiveNonMinimizedTaskCount(any())).thenReturn(2) + whenever(desktopRepository.getActiveNonMinimizedTaskCount(any())).thenReturn(2) whenever( closeDesktopTaskTransitionHandler.startAnimation(any(), any(), any(), any(), any()) ) @@ -167,7 +167,7 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() { fun startAnimation_withClosingLastDesktopTask_dispatchesTransition() { val transition = mock<IBinder>() val transitionInfo = createTransitionInfo(task = createTask(WINDOWING_MODE_FREEFORM)) - whenever(desktopTaskRepository.getActiveNonMinimizedTaskCount(any())).thenReturn(1) + whenever(desktopRepository.getActiveNonMinimizedTaskCount(any())).thenReturn(1) whenever(transitions.dispatchTransition(any(), any(), any(), any(), any(), any())) .thenReturn(mock()) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt index ca972296e8d4..d7a132dfa1be 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt @@ -16,13 +16,22 @@ package com.android.wm.shell.desktopmode +import android.platform.test.annotations.DisableFlags +import android.platform.test.annotations.EnableFlags +import android.platform.test.flag.junit.SetFlagsRule import com.android.dx.mockito.inline.extended.ExtendedMockito.verify import com.android.internal.util.FrameworkStatsLog import com.android.modules.utils.testing.ExtendedMockitoRule +import com.android.window.flags.Flags +import com.android.wm.shell.EventLogTags +import com.android.wm.shell.ShellTestCase import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterReason import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ExitReason import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.MinimizeReason +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.InputMethod import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.TaskUpdate +import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.TaskSizeUpdate import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UnminimizeReason import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_MINIMIZE_REASON import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_UNMINIMIZE_REASON @@ -34,14 +43,19 @@ import org.mockito.kotlin.eq /** * Tests for [DesktopModeEventLogger]. */ -class DesktopModeEventLoggerTest { +class DesktopModeEventLoggerTest : ShellTestCase() { private val desktopModeEventLogger = DesktopModeEventLogger() @JvmField - @Rule + @Rule(order = 0) val extendedMockitoRule = ExtendedMockitoRule.Builder(this) - .mockStatic(FrameworkStatsLog::class.java).build()!! + .mockStatic(FrameworkStatsLog::class.java) + .mockStatic(EventLogTags::class.java).build()!! + + @JvmField + @Rule(order = 1) + val setFlagsRule = SetFlagsRule() @Test fun logSessionEnter_enterReason() = runBlocking { @@ -60,6 +74,11 @@ class DesktopModeEventLoggerTest { eq(SESSION_ID) ) } + verify { + EventLogTags.writeWmShellEnterDesktopMode( + eq(EnterReason.UNKNOWN_ENTER.reason), + eq(SESSION_ID)) + } } @Test @@ -79,6 +98,11 @@ class DesktopModeEventLoggerTest { eq(SESSION_ID) ) } + verify { + EventLogTags.writeWmShellExitDesktopMode( + eq(ExitReason.UNKNOWN_EXIT.reason), + eq(SESSION_ID)) + } } @Test @@ -108,6 +132,22 @@ class DesktopModeEventLoggerTest { /* visible_task_count */ eq(TASK_COUNT)) } + + verify { + EventLogTags.writeWmShellDesktopModeTaskUpdate( + eq(FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_ADDED), + eq(TASK_UPDATE.instanceId), + eq(TASK_UPDATE.uid), + eq(TASK_UPDATE.taskHeight), + eq(TASK_UPDATE.taskWidth), + eq(TASK_UPDATE.taskX), + eq(TASK_UPDATE.taskY), + eq(SESSION_ID), + eq(UNSET_MINIMIZE_REASON), + eq(UNSET_UNMINIMIZE_REASON), + eq(TASK_COUNT)) + } } @Test @@ -137,6 +177,22 @@ class DesktopModeEventLoggerTest { /* visible_task_count */ eq(TASK_COUNT)) } + + verify { + EventLogTags.writeWmShellDesktopModeTaskUpdate( + eq(FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_REMOVED), + eq(TASK_UPDATE.instanceId), + eq(TASK_UPDATE.uid), + eq(TASK_UPDATE.taskHeight), + eq(TASK_UPDATE.taskWidth), + eq(TASK_UPDATE.taskX), + eq(TASK_UPDATE.taskY), + eq(SESSION_ID), + eq(UNSET_MINIMIZE_REASON), + eq(UNSET_UNMINIMIZE_REASON), + eq(TASK_COUNT)) + } } @Test @@ -167,6 +223,22 @@ class DesktopModeEventLoggerTest { /* visible_task_count */ eq(TASK_COUNT)) } + + verify { + EventLogTags.writeWmShellDesktopModeTaskUpdate( + eq(FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED), + eq(TASK_UPDATE.instanceId), + eq(TASK_UPDATE.uid), + eq(TASK_UPDATE.taskHeight), + eq(TASK_UPDATE.taskWidth), + eq(TASK_UPDATE.taskX), + eq(TASK_UPDATE.taskY), + eq(SESSION_ID), + eq(UNSET_MINIMIZE_REASON), + eq(UNSET_UNMINIMIZE_REASON), + eq(TASK_COUNT)) + } } @Test @@ -200,6 +272,22 @@ class DesktopModeEventLoggerTest { /* visible_task_count */ eq(TASK_COUNT)) } + + verify { + EventLogTags.writeWmShellDesktopModeTaskUpdate( + eq(FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED), + eq(TASK_UPDATE.instanceId), + eq(TASK_UPDATE.uid), + eq(TASK_UPDATE.taskHeight), + eq(TASK_UPDATE.taskWidth), + eq(TASK_UPDATE.taskX), + eq(TASK_UPDATE.taskY), + eq(SESSION_ID), + eq(MinimizeReason.TASK_LIMIT.reason), + eq(UNSET_UNMINIMIZE_REASON), + eq(TASK_COUNT)) + } } @Test @@ -233,9 +321,83 @@ class DesktopModeEventLoggerTest { /* visible_task_count */ eq(TASK_COUNT)) } + + verify { + EventLogTags.writeWmShellDesktopModeTaskUpdate( + eq(FrameworkStatsLog + .DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED), + eq(TASK_UPDATE.instanceId), + eq(TASK_UPDATE.uid), + eq(TASK_UPDATE.taskHeight), + eq(TASK_UPDATE.taskWidth), + eq(TASK_UPDATE.taskX), + eq(TASK_UPDATE.taskY), + eq(SESSION_ID), + eq(UNSET_MINIMIZE_REASON), + eq(UnminimizeReason.TASKBAR_TAP.reason), + eq(TASK_COUNT)) + } } - companion object { + @Test + @EnableFlags(Flags.FLAG_ENABLE_RESIZING_METRICS) + fun logTaskResizingStarted_logsTaskSizeUpdatedWithStartResizingStage() = runBlocking { + desktopModeEventLogger.logTaskResizingStarted(sessionId = SESSION_ID, createTaskSizeUpdate()) + + verify { + FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED), + /* resize_trigger */ + eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER), + /* resizing_stage */ + eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__START_RESIZING_STAGE), + /* input_method */ + eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__UNKNOWN_INPUT_METHOD), + /* desktop_mode_session_id */ + eq(SESSION_ID), + /* instance_id */ + eq(TASK_SIZE_UPDATE.instanceId), + /* uid */ + eq(TASK_SIZE_UPDATE.uid), + /* task_height */ + eq(TASK_SIZE_UPDATE.taskHeight), + /* task_width */ + eq(TASK_SIZE_UPDATE.taskWidth), + /* display_area */ + eq(TASK_SIZE_UPDATE.displayArea), + ) + } + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_RESIZING_METRICS) + fun logTaskResizingEnded_logsTaskSizeUpdatedWithEndResizingStage() = runBlocking { + desktopModeEventLogger.logTaskResizingEnded(sessionId = SESSION_ID, createTaskSizeUpdate()) + + verify { + FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED), + /* resize_trigger */ + eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER), + /* resizing_stage */ + eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__END_RESIZING_STAGE), + /* input_method */ + eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__INPUT_METHOD__UNKNOWN_INPUT_METHOD), + /* desktop_mode_session_id */ + eq(SESSION_ID), + /* instance_id */ + eq(TASK_SIZE_UPDATE.instanceId), + /* uid */ + eq(TASK_SIZE_UPDATE.uid), + /* task_height */ + eq(TASK_SIZE_UPDATE.taskHeight), + /* task_width */ + eq(TASK_SIZE_UPDATE.taskWidth), + /* display_area */ + eq(TASK_SIZE_UPDATE.displayArea), + ) + } + } + + private companion object { private const val SESSION_ID = 1 private const val TASK_ID = 1 private const val TASK_UID = 1 @@ -244,16 +406,40 @@ class DesktopModeEventLoggerTest { private const val TASK_HEIGHT = 100 private const val TASK_WIDTH = 100 private const val TASK_COUNT = 1 + private const val DISPLAY_AREA = 1000 private val TASK_UPDATE = TaskUpdate( TASK_ID, TASK_UID, TASK_HEIGHT, TASK_WIDTH, TASK_X, TASK_Y, visibleTaskCount = TASK_COUNT, ) + private val TASK_SIZE_UPDATE = TaskSizeUpdate( + resizeTrigger = ResizeTrigger.UNKNOWN_RESIZE_TRIGGER, + inputMethod = InputMethod.UNKNOWN_INPUT_METHOD, + TASK_ID, + TASK_UID, + TASK_HEIGHT, + TASK_WIDTH, + DISPLAY_AREA, + ) + + private fun createTaskSizeUpdate( + resizeTrigger: ResizeTrigger = ResizeTrigger.UNKNOWN_RESIZE_TRIGGER, + inputMethod: InputMethod = InputMethod.UNKNOWN_INPUT_METHOD, + ) = TaskSizeUpdate( + resizeTrigger, + inputMethod, + TASK_ID, + TASK_UID, + TASK_HEIGHT, + TASK_WIDTH, + DISPLAY_AREA, + ) + private fun createTaskUpdate( minimizeReason: MinimizeReason? = null, unminimizeReason: UnminimizeReason? = null, ) = TaskUpdate(TASK_ID, TASK_UID, TASK_HEIGHT, TASK_WIDTH, TASK_X, TASK_Y, minimizeReason, unminimizeReason, TASK_COUNT) } -}
\ No newline at end of file +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt index d399b20abb2a..daf7e7d5397b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt @@ -110,15 +110,20 @@ class DesktopModeLoggerTransitionObserverTest : ShellTestCase() { shellInit = spy(ShellInit(testExecutor)) desktopModeEventLogger = mock<DesktopModeEventLogger>() - transitionObserver = - DesktopModeLoggerTransitionObserver( - context, mockShellInit, transitions, desktopModeEventLogger) - if (Transitions.ENABLE_SHELL_TRANSITIONS) { - val initRunnableCaptor = ArgumentCaptor.forClass(Runnable::class.java) - verify(mockShellInit).addInitCallback(initRunnableCaptor.capture(), same(transitionObserver)) - initRunnableCaptor.value.run() - } else { - transitionObserver.onInit() + transitionObserver = DesktopModeLoggerTransitionObserver( + context, mockShellInit, transitions, desktopModeEventLogger) + val initRunnableCaptor = ArgumentCaptor.forClass(Runnable::class.java) + verify(mockShellInit).addInitCallback(initRunnableCaptor.capture(), same(transitionObserver)) + initRunnableCaptor.value.run() + } + + @Test + fun testInitialiseVisibleTasksSystemProperty() { + ExtendedMockito.verify { + SystemProperties.set( + eq(DesktopModeLoggerTransitionObserver.VISIBLE_TASKS_COUNTER_SYSTEM_PROPERTY), + eq(DesktopModeLoggerTransitionObserver + .VISIBLE_TASKS_COUNTER_SYSTEM_PROPERTY_DEFAULT_VALUE)) } } 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 2b7f86f36477..935e6d052f5e 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 @@ -17,8 +17,8 @@ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo +import android.graphics.PointF import android.graphics.Rect -import android.graphics.Region import android.testing.AndroidTestingRunner import android.view.SurfaceControl import androidx.test.filters.SmallTest @@ -33,6 +33,7 @@ import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.kotlin.whenever @@ -58,13 +59,15 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { whenever(displayLayout.width()).thenReturn(DISPLAY_BOUNDS.width()) whenever(displayLayout.height()).thenReturn(DISPLAY_BOUNDS.height()) whenever(displayLayout.stableInsets()).thenReturn(STABLE_INSETS) + whenever(displayController.getDisplayLayout(anyInt())).thenReturn(displayLayout) } @Test fun testFullscreenRegionCalculation() { createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN) var testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT) - assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, 2 * STABLE_INSETS.top)) + assertThat(testRegion.bounds).isEqualTo(Rect(0, Short.MIN_VALUE.toInt(), 2400, + 2 * STABLE_INSETS.top)) createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FREEFORM) testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT) @@ -75,17 +78,19 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { val toFullscreenWidth = displayLayout.width() * toFullscreenScale assertThat(testRegion.bounds).isEqualTo(Rect( (DISPLAY_BOUNDS.width() / 2f - toFullscreenWidth / 2f).toInt(), - -50, + Short.MIN_VALUE.toInt(), (DISPLAY_BOUNDS.width() / 2f + toFullscreenWidth / 2f).toInt(), transitionHeight)) createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_SPLIT) testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT) - assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, 2 * STABLE_INSETS.top)) + assertThat(testRegion.bounds).isEqualTo(Rect(0, Short.MIN_VALUE.toInt(), 2400, + 2 * STABLE_INSETS.top)) createVisualIndicator(DesktopModeVisualIndicator.DragStartState.DRAGGED_INTENT) testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT) - assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, transitionHeight)) + assertThat(testRegion.bounds).isEqualTo(Rect(0, Short.MIN_VALUE.toInt(), 2400, + transitionHeight)) } @Test @@ -133,22 +138,19 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { } @Test - fun testToDesktopRegionCalculation() { + fun testDefaultIndicators() { createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN) - val fullscreenRegion = visualIndicator.calculateFullscreenRegion(displayLayout, - CAPTION_HEIGHT) - val splitLeftRegion = visualIndicator.calculateSplitLeftRegion(displayLayout, - TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) - val splitRightRegion = visualIndicator.calculateSplitRightRegion(displayLayout, - TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) - val desktopRegion = visualIndicator.calculateToDesktopRegion(displayLayout, - splitLeftRegion, splitRightRegion, fullscreenRegion) - var testRegion = Region() - testRegion.union(DISPLAY_BOUNDS) - testRegion.op(splitLeftRegion, Region.Op.DIFFERENCE) - testRegion.op(splitRightRegion, Region.Op.DIFFERENCE) - testRegion.op(fullscreenRegion, Region.Op.DIFFERENCE) - assertThat(desktopRegion).isEqualTo(testRegion) + var result = visualIndicator.updateIndicatorType(PointF(-10000f, 500f)) + assertThat(result).isEqualTo(DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_SPLIT) + result = visualIndicator.updateIndicatorType(PointF(10000f, 500f)) + assertThat(result).isEqualTo(DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.DRAGGED_INTENT) + result = visualIndicator.updateIndicatorType(PointF(500f, 10000f)) + assertThat(result).isEqualTo(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FREEFORM) + result = visualIndicator.updateIndicatorType(PointF(500f, 10000f)) + assertThat(result).isEqualTo(DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR) } private fun createVisualIndicator(dragStartState: DesktopModeVisualIndicator.DragStartState) { 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/DesktopRepositoryTest.kt index 97ceecc3662d..55b9724795e1 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/DesktopRepositoryTest.kt @@ -56,9 +56,9 @@ import org.mockito.kotlin.whenever @SmallTest @RunWith(AndroidTestingRunner::class) @ExperimentalCoroutinesApi -class DesktopModeTaskRepositoryTest : ShellTestCase() { +class DesktopRepositoryTest : ShellTestCase() { - private lateinit var repo: DesktopModeTaskRepository + private lateinit var repo: DesktopRepository private lateinit var shellInit: ShellInit private lateinit var datastoreScope: CoroutineScope @@ -71,7 +71,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { datastoreScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob()) shellInit = spy(ShellInit(testExecutor)) - repo = DesktopModeTaskRepository(context, shellInit, persistentRepository, datastoreScope) + repo = DesktopRepository(context, shellInit, persistentRepository, datastoreScope) whenever(runBlocking { persistentRepository.readDesktop(any(), any()) }).thenReturn( Desktop.getDefaultInstance() ) @@ -940,7 +940,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { assertThat(repo.isTaskInFullImmersiveState(taskId = 2)).isTrue() } - class TestListener : DesktopModeTaskRepository.ActiveTasksListener { + class TestListener : DesktopRepository.ActiveTasksListener { var activeChangesOnDefaultDisplay = 0 var activeChangesOnSecondaryDisplay = 0 override fun onActiveTasksChanged(displayId: Int) { @@ -952,7 +952,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { } } - class TestVisibilityListener : DesktopModeTaskRepository.VisibleTasksListener { + class TestVisibilityListener : DesktopRepository.VisibleTasksListener { var visibleTasksCountOnDefaultDisplay = 0 var visibleTasksCountOnSecondaryDisplay = 0 @@ -980,4 +980,4 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { private const val DEFAULT_USER_ID = 1000 private const val DEFAULT_DESKTOP_ID = 0 } -} +}
\ No newline at end of file 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 2ddb1acf7300..ae4772eba5b0 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 @@ -50,6 +50,7 @@ import android.view.Display.DEFAULT_DISPLAY import android.view.DragEvent import android.view.Gravity import android.view.SurfaceControl +import android.view.WindowInsets import android.view.WindowManager import android.view.WindowManager.TRANSIT_CHANGE import android.view.WindowManager.TRANSIT_CLOSE @@ -75,6 +76,7 @@ import com.android.dx.mockito.inline.extended.StaticMockitoSession 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.window.flags.Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP import com.android.wm.shell.MockToken import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer @@ -142,11 +144,13 @@ import org.mockito.Mockito import org.mockito.Mockito.anyInt import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.mock +import org.mockito.Mockito.never import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.times import org.mockito.kotlin.any import org.mockito.kotlin.anyOrNull +import org.mockito.kotlin.argThat import org.mockito.kotlin.atLeastOnce import org.mockito.kotlin.capture import org.mockito.kotlin.eq @@ -183,6 +187,8 @@ class DesktopTasksControllerTest : ShellTestCase() { @Mock lateinit var toggleResizeDesktopTaskTransitionHandler: ToggleResizeDesktopTaskTransitionHandler @Mock lateinit var dragToDesktopTransitionHandler: DragToDesktopTransitionHandler + @Mock + lateinit var mockDesktopFullImmersiveTransitionHandler: DesktopFullImmersiveTransitionHandler @Mock lateinit var launchAdjacentController: LaunchAdjacentController @Mock lateinit var splitScreenController: SplitScreenController @Mock lateinit var recentsTransitionHandler: RecentsTransitionHandler @@ -201,7 +207,7 @@ class DesktopTasksControllerTest : ShellTestCase() { private lateinit var mockitoSession: StaticMockitoSession private lateinit var controller: DesktopTasksController private lateinit var shellInit: ShellInit - private lateinit var taskRepository: DesktopModeTaskRepository + private lateinit var taskRepository: DesktopRepository private lateinit var desktopTasksLimiter: DesktopTasksLimiter private lateinit var recentsTransitionStateListener: RecentsTransitionStateListener private lateinit var testScope: CoroutineScope @@ -232,7 +238,7 @@ class DesktopTasksControllerTest : ShellTestCase() { testScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob()) shellInit = spy(ShellInit(testExecutor)) - taskRepository = DesktopModeTaskRepository(context, shellInit, persistentRepository, testScope) + taskRepository = DesktopRepository(context, shellInit, persistentRepository, testScope) desktopTasksLimiter = DesktopTasksLimiter( transitions, @@ -289,6 +295,7 @@ class DesktopTasksControllerTest : ShellTestCase() { dragAndDropTransitionHandler, toggleResizeDesktopTaskTransitionHandler, dragToDesktopTransitionHandler, + mockDesktopFullImmersiveTransitionHandler, taskRepository, desktopModeLoggerTransitionObserver, launchAdjacentController, @@ -2643,13 +2650,17 @@ class DesktopTasksControllerTest : ShellTestCase() { @Test fun onDesktopDragMove_endsOutsideValidDragArea_snapsToValidBounds() { val task = setUpFreeformTask() + val spyController = spy(controller) val mockSurface = mock(SurfaceControl::class.java) val mockDisplayLayout = mock(DisplayLayout::class.java) whenever(displayController.getDisplayLayout(task.displayId)).thenReturn(mockDisplayLayout) whenever(mockDisplayLayout.stableInsets()).thenReturn(Rect(0, 100, 2000, 2000)) - controller.onDragPositioningMove(task, mockSurface, 200f, Rect(100, -100, 500, 1000)) + spyController.onDragPositioningMove(task, mockSurface, 200f, Rect(100, -100, 500, 1000)) - controller.onDragPositioningEnd( + whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) + .thenReturn(DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR) + spyController.onDragPositioningEnd( task, mockSurface, Point(100, -100), /* position */ @@ -3119,6 +3130,54 @@ class DesktopTasksControllerTest : ShellTestCase() { verify(shellController, times(1)).addUserChangeListener(any()) } + @Test + fun toggleImmersive_enter_resizesToDisplayBounds() { + val task = setUpFreeformTask(DEFAULT_DISPLAY) + taskRepository.setTaskInFullImmersiveState(DEFAULT_DISPLAY, task.taskId, false /* immersive */) + + controller.toggleDesktopTaskFullImmersiveState(task) + + verify(mockDesktopFullImmersiveTransitionHandler).enterImmersive(eq(task), argThat { wct -> + wct.hasBoundsChange(task.token, Rect()) + }) + } + + @Test + fun toggleImmersive_exit_resizesToStableBounds() { + val task = setUpFreeformTask(DEFAULT_DISPLAY) + taskRepository.setTaskInFullImmersiveState(DEFAULT_DISPLAY, task.taskId, true /* immersive */) + + controller.toggleDesktopTaskFullImmersiveState(task) + + verify(mockDesktopFullImmersiveTransitionHandler).exitImmersive(eq(task), argThat { wct -> + wct.hasBoundsChange(task.token, STABLE_BOUNDS) + }) + } + + @Test + @EnableFlags(FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) + fun onTaskInfoChanged_inImmersiveUnrequestsImmersive_exits() { + val task = setUpFreeformTask(DEFAULT_DISPLAY) + taskRepository.setTaskInFullImmersiveState(DEFAULT_DISPLAY, task.taskId, immersive = true) + + task.requestedVisibleTypes = WindowInsets.Type.statusBars() + controller.onTaskInfoChanged(task) + + verify(mockDesktopFullImmersiveTransitionHandler).exitImmersive(eq(task), any()) + } + + @Test + @EnableFlags(FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) + fun onTaskInfoChanged_notInImmersiveUnrequestsImmersive_noReExit() { + val task = setUpFreeformTask(DEFAULT_DISPLAY) + taskRepository.setTaskInFullImmersiveState(DEFAULT_DISPLAY, task.taskId, immersive = false) + + task.requestedVisibleTypes = WindowInsets.Type.statusBars() + controller.onTaskInfoChanged(task) + + verify(mockDesktopFullImmersiveTransitionHandler, never()).exitImmersive(eq(task), any()) + } + /** * Assert that an unhandled drag event launches a PendingIntent with the * windowing mode and bounds we are expecting. @@ -3484,6 +3543,13 @@ private fun WindowContainerTransaction.assertLaunchTaskAt( .isEqualTo(windowingMode) } +private fun WindowContainerTransaction.hasBoundsChange( + token: WindowContainerToken, + bounds: Rect +): Boolean = this.changes.any { change -> + change.key == token.asBinder() && change.value.configuration.windowConfiguration.bounds == bounds +} + private fun WindowContainerTransaction?.anyDensityConfigChange( token: WindowContainerToken ): Boolean { 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 bc5ae97a55ea..596b76dbdb2e 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 @@ -19,6 +19,8 @@ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo import android.os.Binder import android.os.Handler +import android.platform.test.annotations.DisableFlags +import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.SetFlagsRule import android.testing.AndroidTestingRunner import android.view.Display.DEFAULT_DISPLAY @@ -33,6 +35,7 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn import com.android.dx.mockito.inline.extended.StaticMockitoSession import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_MINIMIZE_WINDOW import com.android.internal.jank.InteractionJankMonitor +import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase import com.android.wm.shell.common.ShellExecutor @@ -89,7 +92,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { private lateinit var mockitoSession: StaticMockitoSession private lateinit var desktopTasksLimiter: DesktopTasksLimiter - private lateinit var desktopTaskRepo: DesktopModeTaskRepository + private lateinit var desktopTaskRepo: DesktopRepository private lateinit var shellInit: ShellInit private lateinit var testScope: CoroutineScope @@ -103,7 +106,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { testScope = CoroutineScope(Dispatchers.Unconfined + SupervisorJob()) desktopTaskRepo = - DesktopModeTaskRepository(context, shellInit, persistentRepository, testScope) + DesktopRepository(context, shellInit, persistentRepository, testScope) desktopTasksLimiter = DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT, interactionJankMonitor, mContext, handler) @@ -243,6 +246,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { } @Test + @DisableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun removeLeftoverMinimizedTasks_activeNonMinimizedTasksStillAround_doesNothing() { desktopTaskRepo.addActiveTask(displayId = DEFAULT_DISPLAY, taskId = 1) desktopTaskRepo.addActiveTask(displayId = DEFAULT_DISPLAY, taskId = 2) @@ -256,6 +260,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { } @Test + @DisableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun removeLeftoverMinimizedTasks_noMinimizedTasks_doesNothing() { val wct = WindowContainerTransaction() desktopTasksLimiter.leftoverMinimizedTasksRemover.removeLeftoverMinimizedTasks( @@ -265,6 +270,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { } @Test + @DisableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun removeLeftoverMinimizedTasks_onlyMinimizedTasksLeft_removesAllMinimizedTasks() { val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) @@ -283,6 +289,20 @@ class DesktopTasksLimiterTest : ShellTestCase() { } @Test + @EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) + fun removeLeftoverMinimizedTasks_onlyMinimizedTasksLeft_backNavEnabled_doesNothing() { + val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) + val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) + desktopTaskRepo.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task1.taskId) + desktopTaskRepo.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) + + val wct = WindowContainerTransaction() + desktopTasksLimiter.leftoverMinimizedTasksRemover.onActiveTasksChanged(DEFAULT_DISPLAY) + + assertThat(wct.hierarchyOps).isEmpty() + } + + @Test fun addAndGetMinimizeTaskChangesIfNeeded_tasksWithinLimit_noTaskMinimized() { (1..<MAX_TASK_LIMIT).forEach { _ -> setUpFreeformTask() } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt index c989d1640f80..598df34a310d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt @@ -18,11 +18,13 @@ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM +import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN import android.content.ComponentName import android.content.Context import android.content.Intent import android.platform.test.annotations.EnableFlags import android.view.Display.DEFAULT_DISPLAY +import android.view.WindowManager.TRANSIT_OPEN import android.view.WindowManager.TRANSIT_TO_BACK import android.window.IWindowContainerToken import android.window.TransitionInfo @@ -60,7 +62,7 @@ class DesktopTasksTransitionObserverTest { private val transitions = mock<Transitions>() private val context = mock<Context>() private val shellTaskOrganizer = mock<ShellTaskOrganizer>() - private val taskRepository = mock<DesktopModeTaskRepository>() + private val taskRepository = mock<DesktopRepository>() private lateinit var transitionObserver: DesktopTasksTransitionObserver private lateinit var shellInit: ShellInit @@ -110,6 +112,24 @@ class DesktopTasksTransitionObserverTest { verify(taskRepository, never()).minimizeTask(task.displayId, task.taskId) } + @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) + fun removeTasks_onTaskFullscreenLaunch_taskRemovedFromRepo() { + val task = createTaskInfo(1, WINDOWING_MODE_FULLSCREEN) + whenever(taskRepository.getVisibleTaskCount(any())).thenReturn(1) + whenever(taskRepository.isActiveTask(task.taskId)).thenReturn(true) + + transitionObserver.onTransitionReady( + transition = mock(), + info = createOpenTransition(task), + startTransaction = mock(), + finishTransaction = mock(), + ) + + verify(taskRepository, never()).minimizeTask(task.displayId, task.taskId) + verify(taskRepository).removeFreeformTask(task.displayId, task.taskId) + } + private fun createBackNavigationTransition( task: RunningTaskInfo? ): TransitionInfo { @@ -125,11 +145,26 @@ class DesktopTasksTransitionObserverTest { } } - private fun createTaskInfo(id: Int) = + private fun createOpenTransition( + task: RunningTaskInfo? + ): TransitionInfo { + return TransitionInfo(TRANSIT_OPEN, 0 /* flags */).apply { + addChange( + Change(mock(), mock()).apply { + mode = TRANSIT_OPEN + parent = null + taskInfo = task + flags = flags + } + ) + } + } + + private fun createTaskInfo(id: Int, windowingMode: Int = WINDOWING_MODE_FREEFORM) = RunningTaskInfo().apply { taskId = id displayId = DEFAULT_DISPLAY - configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM + configuration.windowConfiguration.windowingMode = windowingMode token = WindowContainerToken(Mockito.mock(IWindowContainerToken::class.java)) baseIntent = Intent().apply { component = ComponentName("package", "component.name") diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt index d9387d2f08dd..230f7e6912ee 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt @@ -581,7 +581,7 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() { ) ) .thenReturn(token) - handler.startDragToDesktopTransition(task.taskId, dragAnimator) + handler.startDragToDesktopTransition(task, dragAnimator) return token } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt index 5596ad7726f1..1e105d9588ab 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/education/AppHandleEducationControllerTest.kt @@ -46,6 +46,7 @@ import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.setMain import org.junit.Before +import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -61,10 +62,7 @@ import org.mockito.kotlin.times import org.mockito.kotlin.verify import org.mockito.kotlin.whenever -/** - * Tests of [AppHandleEducationController] - * Usage: atest AppHandleEducationControllerTest - */ +/** Tests of [AppHandleEducationController] Usage: atest AppHandleEducationControllerTest */ @SmallTest @RunWith(AndroidTestingRunner::class) @OptIn(ExperimentalCoroutinesApi::class) @@ -220,6 +218,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) + @Ignore("b/371527084: revisit testcase after refactoring original logic") fun showWindowingImageButtonTooltip_appHandleExpanded_shouldCallShowEducationTooltipTwice() = testScope.runTest { // After first tooltip is dismissed, app handle is expanded. Should show second education @@ -237,6 +236,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) + @Ignore("b/371527084: revisit testcase after refactoring original logic") fun showWindowingImageButtonTooltip_appHandleExpandedAfterTimeout_shouldCallShowEducationTooltipOnce() = testScope.runTest { // After first tooltip is dismissed, app handle is expanded after timeout. Should not show @@ -258,6 +258,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) + @Ignore("b/371527084: revisit testcase after refactoring original logic") fun showWindowingImageButtonTooltip_appHandleExpandedTwice_shouldCallShowEducationTooltipTwice() = testScope.runTest { // After first tooltip is dismissed, app handle is expanded twice. Should show second @@ -279,6 +280,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) + @Ignore("b/371527084: revisit testcase after refactoring original logic") fun showWindowingImageButtonTooltip_appHandleNotExpanded_shouldCallShowEducationTooltipOnce() = testScope.runTest { // After first tooltip is dismissed, app handle is not expanded. Should not show second @@ -296,6 +298,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) + @Ignore("b/371527084: revisit testcase after refactoring original logic") fun showExitWindowingButtonTooltip_appHeaderVisible_shouldCallShowEducationTooltipThrice() = testScope.runTest { // After first two tooltips are dismissed, app header is visible. Should show third @@ -313,6 +316,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) + @Ignore("b/371527084: revisit testcase after refactoring original logic") fun showExitWindowingButtonTooltip_appHeaderVisibleAfterTimeout_shouldCallShowEducationTooltipTwice() = testScope.runTest { // After first two tooltips are dismissed, app header is visible after timeout. Should not @@ -334,6 +338,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) + @Ignore("b/371527084: revisit testcase after refactoring original logic") fun showExitWindowingButtonTooltip_appHeaderVisibleTwice_shouldCallShowEducationTooltipThrice() = testScope.runTest { // After first two tooltips are dismissed, app header is visible twice. Should show third @@ -354,6 +359,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) + @Ignore("b/371527084: revisit testcase after refactoring original logic") fun showExitWindowingButtonTooltip_appHeaderExpanded_shouldCallShowEducationTooltipTwice() = testScope.runTest { // After first two tooltips are dismissed, app header is visible but expanded. Should not @@ -393,6 +399,7 @@ class AppHandleEducationControllerTest : ShellTestCase() { @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_HANDLE_EDUCATION) + @Ignore("b/371527084: revisit testcase after refactoring original logic") fun setAppHandleEducationTooltipCallbacks_onWindowingImageButtonTooltipClicked_callbackInvoked() = testScope.runTest { // After first tooltip is dismissed, app handle is expanded. Should show second education diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java index 3b2c7e6eaf99..36e0427a7e22 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java @@ -41,7 +41,8 @@ import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestRunningTaskInfoBuilder; import com.android.wm.shell.common.LaunchAdjacentController; -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.desktopmode.DesktopRepository; +import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.windowdecor.WindowDecorViewModel; @@ -73,7 +74,9 @@ public final class FreeformTaskListenerTests extends ShellTestCase { @Mock private SurfaceControl mMockSurfaceControl; @Mock - private DesktopModeTaskRepository mDesktopModeTaskRepository; + private DesktopRepository mDesktopRepository; + @Mock + private DesktopTasksController mDesktopTasksController; @Mock private LaunchAdjacentController mLaunchAdjacentController; private FreeformTaskListener mFreeformTaskListener; @@ -89,7 +92,8 @@ public final class FreeformTaskListenerTests extends ShellTestCase { mContext, mShellInit, mTaskOrganizer, - Optional.of(mDesktopModeTaskRepository), + Optional.of(mDesktopRepository), + Optional.of(mDesktopTasksController), mLaunchAdjacentController, mWindowDecorViewModel); } @@ -102,7 +106,7 @@ public final class FreeformTaskListenerTests extends ShellTestCase { mFreeformTaskListener.onFocusTaskChanged(task); - verify(mDesktopModeTaskRepository) + verify(mDesktopRepository) .addOrMoveFreeformTaskToTop(task.displayId, task.taskId); } @@ -114,7 +118,7 @@ public final class FreeformTaskListenerTests extends ShellTestCase { mFreeformTaskListener.onFocusTaskChanged(fullscreenTask); - verify(mDesktopModeTaskRepository, never()) + verify(mDesktopRepository, never()) .addOrMoveFreeformTaskToTop(fullscreenTask.displayId, fullscreenTask.taskId); } @@ -156,7 +160,7 @@ public final class FreeformTaskListenerTests extends ShellTestCase { task.displayId = INVALID_DISPLAY; mFreeformTaskListener.onTaskVanished(task); - verify(mDesktopModeTaskRepository).minimizeTask(task.displayId, task.taskId); + verify(mDesktopRepository).minimizeTask(task.displayId, task.taskId); } @Test @@ -168,13 +172,25 @@ public final class FreeformTaskListenerTests extends ShellTestCase { mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl); - when(mDesktopModeTaskRepository.isClosingTask(task.taskId)).thenReturn(true); + when(mDesktopRepository.isClosingTask(task.taskId)).thenReturn(true); task.isVisible = false; task.displayId = INVALID_DISPLAY; mFreeformTaskListener.onTaskVanished(task); - verify(mDesktopModeTaskRepository, never()).minimizeTask(task.displayId, task.taskId); - verify(mDesktopModeTaskRepository).removeFreeformTask(task.displayId, task.taskId); + verify(mDesktopRepository, never()).minimizeTask(task.displayId, task.taskId); + verify(mDesktopRepository).removeFreeformTask(task.displayId, task.taskId); + } + + @Test + public void onTaskInfoChanged_withDesktopController_forwards() { + ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder() + .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); + task.isVisible = true; + mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl); + + mFreeformTaskListener.onTaskInfoChanged(task); + + verify(mDesktopTasksController).onTaskInfoChanged(task); } @After diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java index 499e339bc682..d4a319ef7195 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java @@ -17,8 +17,12 @@ package com.android.wm.shell.freeform; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; +import static android.view.WindowManager.TRANSIT_TO_BACK; +import static android.view.WindowManager.TRANSIT_TO_FRONT; +import static android.view.WindowManager.TRANSIT_CHANGE; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -30,6 +34,8 @@ import android.app.ActivityManager; import android.content.Context; import android.content.pm.PackageManager; import android.os.IBinder; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import android.view.SurfaceControl; import android.window.IWindowContainerToken; import android.window.TransitionInfo; @@ -37,30 +43,43 @@ import android.window.WindowContainerToken; import androidx.test.filters.SmallTest; +import com.android.window.flags.Flags; + +import com.android.wm.shell.desktopmode.DesktopTaskChangeListener; +import com.android.wm.shell.desktopmode.DesktopFullImmersiveTransitionHandler; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.TransitionInfoBuilder; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.windowdecor.WindowDecorViewModel; +import java.util.Optional; + import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Optional; + /** - * Tests of {@link FreeformTaskTransitionObserver} + * Tests for {@link FreeformTaskTransitionObserver}. */ @SmallTest public class FreeformTaskTransitionObserverTest { + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private ShellInit mShellInit; @Mock private Transitions mTransitions; @Mock + private DesktopFullImmersiveTransitionHandler mDesktopFullImmersiveTransitionHandler; + @Mock private WindowDecorViewModel mWindowDecorViewModel; - + @Mock + private TaskChangeListener mTaskChangeListener; private FreeformTaskTransitionObserver mTransitionObserver; @Before @@ -69,30 +88,29 @@ public class FreeformTaskTransitionObserverTest { PackageManager pm = mock(PackageManager.class); doReturn(true).when(pm).hasSystemFeature( - PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT); + PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT); final Context context = mock(Context.class); doReturn(pm).when(context).getPackageManager(); mTransitionObserver = new FreeformTaskTransitionObserver( - context, mShellInit, mTransitions, mWindowDecorViewModel); - if (Transitions.ENABLE_SHELL_TRANSITIONS) { - final ArgumentCaptor<Runnable> initRunnableCaptor = ArgumentCaptor.forClass( - Runnable.class); - verify(mShellInit).addInitCallback(initRunnableCaptor.capture(), - same(mTransitionObserver)); - initRunnableCaptor.getValue().run(); - } else { - mTransitionObserver.onInit(); - } + context, mShellInit, mTransitions, + Optional.of(mDesktopFullImmersiveTransitionHandler), + mWindowDecorViewModel, Optional.of(mTaskChangeListener)); + + final ArgumentCaptor<Runnable> initRunnableCaptor = ArgumentCaptor.forClass( + Runnable.class); + verify(mShellInit).addInitCallback(initRunnableCaptor.capture(), + same(mTransitionObserver)); + initRunnableCaptor.getValue().run(); } @Test - public void testRegistersObserverAtInit() { + public void init_registersObserver() { verify(mTransitions).registerObserver(same(mTransitionObserver)); } @Test - public void testCreatesWindowDecorOnOpenTransition_freeform() { + public void openTransition_createsWindowDecor() { final TransitionInfo.Change change = createChange(TRANSIT_OPEN, 1, WINDOWING_MODE_FREEFORM); final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0) @@ -109,7 +127,71 @@ public class FreeformTaskTransitionObserverTest { } @Test - public void testPreparesWindowDecorOnCloseTransition_freeform() { + public void openTransition_notifiesOnTaskOpening() { + final TransitionInfo.Change change = + createChange(TRANSIT_OPEN, 1, WINDOWING_MODE_FREEFORM); + final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0) + .addChange(change).build(); + + final IBinder transition = mock(IBinder.class); + final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); + mTransitionObserver.onTransitionReady(transition, info, startT, finishT); + mTransitionObserver.onTransitionStarting(transition); + + verify(mTaskChangeListener).onTaskOpening(change.getTaskInfo()); + } + + @Test + public void toFrontTransition_notifiesOnTaskMovingToFront() { + final TransitionInfo.Change change = + createChange(TRANSIT_TO_FRONT, /* taskId= */ 1, WINDOWING_MODE_FREEFORM); + final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TO_FRONT, /* flags= */ 0) + .addChange(change).build(); + + final IBinder transition = mock(IBinder.class); + final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); + mTransitionObserver.onTransitionReady(transition, info, startT, finishT); + mTransitionObserver.onTransitionStarting(transition); + + verify(mTaskChangeListener).onTaskMovingToFront(change.getTaskInfo()); + } + + @Test + public void toBackTransition_notifiesOnTaskMovingToBack() { + final TransitionInfo.Change change = + createChange(TRANSIT_TO_BACK, /* taskId= */ 1, WINDOWING_MODE_FREEFORM); + final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TO_BACK, /* flags= */ 0) + .addChange(change).build(); + + final IBinder transition = mock(IBinder.class); + final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); + mTransitionObserver.onTransitionReady(transition, info, startT, finishT); + mTransitionObserver.onTransitionStarting(transition); + + verify(mTaskChangeListener).onTaskMovingToBack(change.getTaskInfo()); + } + + @Test + public void changeTransition_notifiesOnTaskChanging() { + final TransitionInfo.Change change = + createChange(TRANSIT_CHANGE, /* taskId= */ 1, WINDOWING_MODE_FREEFORM); + final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_CHANGE, /* flags= */ 0) + .addChange(change).build(); + + final IBinder transition = mock(IBinder.class); + final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); + mTransitionObserver.onTransitionReady(transition, info, startT, finishT); + mTransitionObserver.onTransitionStarting(transition); + + verify(mTaskChangeListener).onTaskChanging(change.getTaskInfo()); + } + + @Test + public void closeTransition_preparesWindowDecor() { final TransitionInfo.Change change = createChange(TRANSIT_CLOSE, 1, WINDOWING_MODE_FREEFORM); final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_CLOSE, 0) @@ -126,7 +208,23 @@ public class FreeformTaskTransitionObserverTest { } @Test - public void testDoesntCloseWindowDecorDuringCloseTransition() throws Exception { + public void closeTransition_notifiesOnTaskClosing() { + final TransitionInfo.Change change = + createChange(TRANSIT_CLOSE, 1, WINDOWING_MODE_FREEFORM); + final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_CLOSE, 0) + .addChange(change).build(); + + final IBinder transition = mock(IBinder.class); + final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); + mTransitionObserver.onTransitionReady(transition, info, startT, finishT); + mTransitionObserver.onTransitionStarting(transition); + + verify(mTaskChangeListener).onTaskClosing(change.getTaskInfo()); + } + + @Test + public void closeTransition_doesntCloseWindowDecorDuringTransition() throws Exception { final TransitionInfo.Change change = createChange(TRANSIT_CLOSE, 1, WINDOWING_MODE_FREEFORM); final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_CLOSE, 0) @@ -142,7 +240,7 @@ public class FreeformTaskTransitionObserverTest { } @Test - public void testClosesWindowDecorAfterCloseTransition() throws Exception { + public void closeTransition_closesWindowDecorAfterTransition() throws Exception { final TransitionInfo.Change change = createChange(TRANSIT_CLOSE, 1, WINDOWING_MODE_FREEFORM); final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_CLOSE, 0) @@ -161,7 +259,7 @@ public class FreeformTaskTransitionObserverTest { } @Test - public void testClosesMergedWindowDecorationAfterTransitionFinishes() throws Exception { + public void transitionFinished_closesMergedWindowDecoration() throws Exception { // The playing transition final TransitionInfo.Change change1 = createChange(TRANSIT_OPEN, 1, WINDOWING_MODE_FREEFORM); @@ -192,7 +290,7 @@ public class FreeformTaskTransitionObserverTest { } @Test - public void testClosesAllWindowDecorsOnTransitionMergeAfterCloseTransitions() throws Exception { + public void closeTransition_closesWindowDecorsOnTransitionMerge() throws Exception { // The playing transition final TransitionInfo.Change change1 = createChange(TRANSIT_CLOSE, 1, WINDOWING_MODE_FREEFORM); @@ -223,6 +321,19 @@ public class FreeformTaskTransitionObserverTest { verify(mWindowDecorViewModel).destroyWindowDecoration(change2.getTaskInfo()); } + @Test + @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) + public void onTransitionReady_forwardsToDesktopImmersiveHandler() { + final IBinder transition = mock(IBinder.class); + final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_CHANGE, 0).build(); + final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class); + final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class); + + mTransitionObserver.onTransitionReady(transition, info, startT, finishT); + + verify(mDesktopFullImmersiveTransitionHandler).onTransitionReady(transition); + } + private static TransitionInfo.Change createChange(int mode, int taskId, int windowingMode) { final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = taskId; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java index 753d4cd153ee..9b73d53e0639 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java @@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; +import static com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_PERSISTENCE; import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50; import static org.junit.Assert.assertEquals; @@ -50,6 +51,7 @@ import android.app.KeyguardManager; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; +import android.graphics.Point; import android.graphics.Rect; import android.os.Bundle; import android.platform.test.annotations.DisableFlags; @@ -68,7 +70,7 @@ import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestShellExecutor; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.TaskStackListenerImpl; -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.shared.GroupedRecentTaskInfo; import com.android.wm.shell.shared.ShellSharedConstants; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; @@ -107,7 +109,7 @@ public class RecentTasksControllerTest extends ShellTestCase { @Mock private ShellCommandHandler mShellCommandHandler; @Mock - private DesktopModeTaskRepository mDesktopModeTaskRepository; + private DesktopRepository mDesktopRepository; @Mock private ActivityTaskManager mActivityTaskManager; @Mock @@ -144,7 +146,7 @@ public class RecentTasksControllerTest extends ShellTestCase { mDisplayInsetsController, mMainExecutor)); mRecentTasksControllerReal = new RecentTasksController(mContext, mShellInit, mShellController, mShellCommandHandler, mTaskStackListener, mActivityTaskManager, - Optional.of(mDesktopModeTaskRepository), mTaskStackTransitionObserver, + Optional.of(mDesktopRepository), mTaskStackTransitionObserver, mMainExecutor); mRecentTasksController = spy(mRecentTasksControllerReal); mShellTaskOrganizer = new ShellTaskOrganizer(mShellInit, mShellCommandHandler, @@ -303,8 +305,8 @@ public class RecentTasksControllerTest extends ShellTestCase { ActivityManager.RecentTaskInfo t4 = makeTaskInfo(4); setRawList(t1, t2, t3, t4); - when(mDesktopModeTaskRepository.isActiveTask(1)).thenReturn(true); - when(mDesktopModeTaskRepository.isActiveTask(3)).thenReturn(true); + when(mDesktopRepository.isActiveTask(1)).thenReturn(true); + when(mDesktopRepository.isActiveTask(3)).thenReturn(true); ArrayList<GroupedRecentTaskInfo> recentTasks = mRecentTasksController.getRecentTasks( MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0); @@ -342,8 +344,8 @@ public class RecentTasksControllerTest extends ShellTestCase { new SplitBounds(new Rect(), new Rect(), 1, 2, SNAP_TO_2_50_50); mRecentTasksController.addSplitPair(t1.taskId, t2.taskId, pair1Bounds); - when(mDesktopModeTaskRepository.isActiveTask(3)).thenReturn(true); - when(mDesktopModeTaskRepository.isActiveTask(5)).thenReturn(true); + when(mDesktopRepository.isActiveTask(3)).thenReturn(true); + when(mDesktopRepository.isActiveTask(5)).thenReturn(true); ArrayList<GroupedRecentTaskInfo> recentTasks = mRecentTasksController.getRecentTasks( MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0); @@ -382,8 +384,8 @@ public class RecentTasksControllerTest extends ShellTestCase { ActivityManager.RecentTaskInfo t4 = makeTaskInfo(4); setRawList(t1, t2, t3, t4); - when(mDesktopModeTaskRepository.isActiveTask(1)).thenReturn(true); - when(mDesktopModeTaskRepository.isActiveTask(3)).thenReturn(true); + when(mDesktopRepository.isActiveTask(1)).thenReturn(true); + when(mDesktopRepository.isActiveTask(3)).thenReturn(true); ArrayList<GroupedRecentTaskInfo> recentTasks = mRecentTasksController.getRecentTasks( MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0); @@ -410,10 +412,10 @@ public class RecentTasksControllerTest extends ShellTestCase { ActivityManager.RecentTaskInfo t5 = makeTaskInfo(5); setRawList(t1, t2, t3, t4, t5); - when(mDesktopModeTaskRepository.isActiveTask(1)).thenReturn(true); - when(mDesktopModeTaskRepository.isActiveTask(3)).thenReturn(true); - when(mDesktopModeTaskRepository.isActiveTask(5)).thenReturn(true); - when(mDesktopModeTaskRepository.isMinimizedTask(3)).thenReturn(true); + when(mDesktopRepository.isActiveTask(1)).thenReturn(true); + when(mDesktopRepository.isActiveTask(3)).thenReturn(true); + when(mDesktopRepository.isActiveTask(5)).thenReturn(true); + when(mDesktopRepository.isMinimizedTask(3)).thenReturn(true); ArrayList<GroupedRecentTaskInfo> recentTasks = mRecentTasksController.getRecentTasks( MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0); @@ -441,6 +443,40 @@ public class RecentTasksControllerTest extends ShellTestCase { } @Test + @EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_PERSISTENCE) + public void testGetRecentTasks_hasDesktopTasks_persistenceEnabled_freeformTaskHaveBoundsSet() { + ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1); + ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2); + + t1.lastNonFullscreenBounds = new Rect(100, 200, 300, 400); + t2.lastNonFullscreenBounds = new Rect(150, 250, 350, 450); + setRawList(t1, t2); + + when(mDesktopRepository.isActiveTask(1)).thenReturn(true); + when(mDesktopRepository.isActiveTask(2)).thenReturn(true); + + ArrayList<GroupedRecentTaskInfo> recentTasks = mRecentTasksController.getRecentTasks( + MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0); + + assertEquals(1, recentTasks.size()); + GroupedRecentTaskInfo freeformGroup = recentTasks.get(0); + + // Check bounds + assertEquals(t1.lastNonFullscreenBounds, freeformGroup.getTaskInfoList().get( + 0).configuration.windowConfiguration.getAppBounds()); + assertEquals(t2.lastNonFullscreenBounds, freeformGroup.getTaskInfoList().get( + 1).configuration.windowConfiguration.getAppBounds()); + + // Check position in parent + assertEquals(new Point(t1.lastNonFullscreenBounds.left, + t1.lastNonFullscreenBounds.top), + freeformGroup.getTaskInfoList().get(0).positionInParent); + assertEquals(new Point(t2.lastNonFullscreenBounds.left, + t2.lastNonFullscreenBounds.top), + freeformGroup.getTaskInfoList().get(1).positionInParent); + } + + @Test public void testRemovedTaskRemovesSplit() { ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1); ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2); @@ -623,6 +659,7 @@ public class RecentTasksControllerTest extends ShellTestCase { private ActivityManager.RecentTaskInfo makeTaskInfo(int taskId) { ActivityManager.RecentTaskInfo info = new ActivityManager.RecentTaskInfo(); info.taskId = taskId; + info.lastNonFullscreenBounds = new Rect(); return info; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java index 769acf7fdfde..0effc3e3d6b8 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java @@ -48,7 +48,7 @@ import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestShellExecutor; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.TaskStackListenerImpl; -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; @@ -82,7 +82,7 @@ public class RecentsTransitionHandlerTest extends ShellTestCase { @Mock private ShellCommandHandler mShellCommandHandler; @Mock - private DesktopModeTaskRepository mDesktopModeTaskRepository; + private DesktopRepository mDesktopRepository; @Mock private ActivityTaskManager mActivityTaskManager; @Mock @@ -120,7 +120,7 @@ public class RecentsTransitionHandlerTest extends ShellTestCase { mDisplayInsetsController, mMainExecutor)); mRecentTasksControllerReal = new RecentTasksController(mContext, mShellInit, mShellController, mShellCommandHandler, mTaskStackListener, mActivityTaskManager, - Optional.of(mDesktopModeTaskRepository), mTaskStackTransitionObserver, + Optional.of(mDesktopRepository), mTaskStackTransitionObserver, mMainExecutor); mRecentTasksController = spy(mRecentTasksControllerReal); mShellTaskOrganizer = new ShellTaskOrganizer(mShellInit, mShellCommandHandler, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/TaskStackTransitionObserverTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/TaskStackTransitionObserverTest.kt index 0e5efa650cc4..afdb68776d04 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/TaskStackTransitionObserverTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/TaskStackTransitionObserverTest.kt @@ -114,7 +114,7 @@ class TaskStackTransitionObserverTest { @Test @EnableFlags(Flags.FLAG_ENABLE_TASK_STACK_OBSERVER_IN_SHELL) - fun taskCreated_fullscreenWindow_listenerNotNotified() { + fun taskCreated_fullscreenWindow_listenerNotified() { val listener = TestListener() val executor = TestShellExecutor() transitionObserver.addTaskStackTransitionObserverListener(listener, executor) @@ -130,9 +130,9 @@ class TaskStackTransitionObserverTest { callOnTransitionFinished() executor.flushAll() - assertThat(listener.taskInfoToBeNotified.taskId).isEqualTo(0) + assertThat(listener.taskInfoToBeNotified.taskId).isEqualTo(1) assertThat(listener.taskInfoToBeNotified.windowingMode) - .isEqualTo(WindowConfiguration.WINDOWING_MODE_UNDEFINED) + .isEqualTo(WindowConfiguration.WINDOWING_MODE_FULLSCREEN) } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/bubbles/BubbleInfoTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/bubbles/BubbleInfoTest.kt index 641063c27076..205defef5dd5 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/bubbles/BubbleInfoTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/shared/bubbles/BubbleInfoTest.kt @@ -16,6 +16,8 @@ package com.android.wm.shell.shared.bubbles +import android.graphics.drawable.Icon +import android.net.Uri import android.os.Parcel import android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE import android.testing.AndroidTestingRunner @@ -42,7 +44,12 @@ class BubbleInfoTest : ShellTestCase() { "title", "Some app", true, - true + true, + ParcelableFlyoutMessage( + Icon.createWithContentUri(Uri.parse("content://image/123")), + "sender", + "message" + ) ) val parcel = Parcel.obtain() bubbleInfo.writeToParcel(parcel, PARCELABLE_WRITE_RETURN_VALUE) @@ -60,5 +67,10 @@ class BubbleInfoTest : ShellTestCase() { assertThat(bubbleInfo.appName).isEqualTo(bubbleInfoFromParcel.appName) assertThat(bubbleInfo.isImportantConversation) .isEqualTo(bubbleInfoFromParcel.isImportantConversation) + with(bubbleInfo.parcelableFlyoutMessage!!) { + assertThat(icon!!.uri.toString()).isEqualTo("content://image/123") + assertThat(title).isEqualTo("sender") + assertThat(message).isEqualTo("message") + } } } 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 5ae4ca839d61..4aa7e18b4b84 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 @@ -87,7 +87,7 @@ import com.android.wm.shell.common.MultiInstanceHelper import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository +import com.android.wm.shell.desktopmode.DesktopRepository import com.android.wm.shell.desktopmode.DesktopTasksController import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition import com.android.wm.shell.desktopmode.DesktopTasksLimiter @@ -161,7 +161,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { @Mock private lateinit var mockTaskOrganizer: ShellTaskOrganizer @Mock private lateinit var mockDisplayController: DisplayController @Mock private lateinit var mockSplitScreenController: SplitScreenController - @Mock private lateinit var mockDesktopRepository: DesktopModeTaskRepository + @Mock private lateinit var mockDesktopRepository: DesktopRepository @Mock private lateinit var mockDisplayLayout: DisplayLayout @Mock private lateinit var displayInsetsController: DisplayInsetsController @Mock private lateinit var mockSyncQueue: SyncTransactionQueue @@ -1221,9 +1221,48 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { assertEquals(decor.mTaskInfo.token.asBinder(), wct.getHierarchyOps().get(0).getContainer()) } + @Test + @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) + fun testMaximizeButtonClick_requestingImmersive_togglesDesktopImmersiveState() { + val onClickListenerCaptor = forClass(View.OnClickListener::class.java) + as ArgumentCaptor<View.OnClickListener> + val decor = createOpenTaskDecoration( + windowingMode = WINDOWING_MODE_FREEFORM, + onCaptionButtonClickListener = onClickListenerCaptor, + requestingImmersive = true, + ) + val view = mock(View::class.java) + whenever(view.id).thenReturn(R.id.maximize_window) + + onClickListenerCaptor.value.onClick(view) + + verify(mockDesktopTasksController) + .toggleDesktopTaskFullImmersiveState(decor.mTaskInfo) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) + fun testMaximizeButtonClick_notRequestingImmersive_togglesDesktopTaskSize() { + val onClickListenerCaptor = forClass(View.OnClickListener::class.java) + as ArgumentCaptor<View.OnClickListener> + val decor = createOpenTaskDecoration( + windowingMode = WINDOWING_MODE_FREEFORM, + onCaptionButtonClickListener = onClickListenerCaptor, + requestingImmersive = false, + ) + val view = mock(View::class.java) + whenever(view.id).thenReturn(R.id.maximize_window) + + onClickListenerCaptor.value.onClick(view) + + verify(mockDesktopTasksController) + .toggleDesktopTaskSize(decor.mTaskInfo) + } + private fun createOpenTaskDecoration( @WindowingMode windowingMode: Int, taskSurface: SurfaceControl = SurfaceControl(), + requestingImmersive: Boolean = false, onMaxOrRestoreListenerCaptor: ArgumentCaptor<Function0<Unit>> = forClass(Function0::class.java) as ArgumentCaptor<Function0<Unit>>, onLeftSnapClickListenerCaptor: ArgumentCaptor<Function0<Unit>> = @@ -1243,7 +1282,10 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { onCaptionButtonTouchListener: ArgumentCaptor<View.OnTouchListener> = forClass(View.OnTouchListener::class.java) as ArgumentCaptor<View.OnTouchListener> ): DesktopModeWindowDecoration { - val decor = setUpMockDecorationForTask(createTask(windowingMode = windowingMode)) + val decor = setUpMockDecorationForTask(createTask( + windowingMode = windowingMode, + requestingImmersive = requestingImmersive + )) onTaskOpening(decor.mTaskInfo, taskSurface) verify(decor).setOnMaximizeOrRestoreClickListener(onMaxOrRestoreListenerCaptor.capture()) verify(decor).setOnLeftSnapClickListener(onLeftSnapClickListenerCaptor.capture()) @@ -1282,6 +1324,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { activityType: Int = ACTIVITY_TYPE_STANDARD, focused: Boolean = true, activityInfo: ActivityInfo = ActivityInfo(), + requestingImmersive: Boolean = false ): RunningTaskInfo { return TestRunningTaskInfoBuilder() .setDisplayId(displayId) @@ -1292,6 +1335,11 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { topActivityInfo = activityInfo isFocused = focused isResizeable = true + requestedVisibleTypes = if (requestingImmersive) { + statusBars().inv() + } else { + statusBars() + } } } 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 3e7f3bdd72a2..35be80e87ecd 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 @@ -106,7 +106,7 @@ import com.android.wm.shell.common.MultiInstanceHelper; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.desktopmode.CaptionState; -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.splitscreen.SplitScreenController; @@ -163,7 +163,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { @Mock private ShellTaskOrganizer mMockShellTaskOrganizer; @Mock - private DesktopModeTaskRepository mMockDesktopRepository; + private DesktopRepository mMockDesktopRepository; @Mock private Choreographer mMockChoreographer; @Mock @@ -619,6 +619,27 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { } @Test + @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) + public void updateRelayoutParams_header_notAnInsetsSourceInFullyImmersive() { + final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); + taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM); + final RelayoutParams relayoutParams = new RelayoutParams(); + + DesktopModeWindowDecoration.updateRelayoutParams( + relayoutParams, + mTestableContext, + taskInfo, + /* applyStartTransactionOnDraw= */ true, + /* shouldSetTaskPositionAndCrop */ false, + /* isStatusBarVisible */ true, + /* isKeyguardVisibleAndOccluded */ false, + /* inFullImmersiveMode */ true, + new InsetsState()); + + assertThat(relayoutParams.mIsInsetSource).isFalse(); + } + + @Test @DisableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) public void updateRelayoutParams_header_statusBarInvisible_captionVisible() { final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); @@ -1025,6 +1046,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { any(), openInBrowserCaptor.capture(), any(), + any(), any() ); openInBrowserCaptor.getValue().invoke(new Intent(Intent.ACTION_MAIN, TEST_URI1)); @@ -1053,6 +1075,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { any(), openInBrowserCaptor.capture(), any(), + any(), any() ); @@ -1103,6 +1126,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { any(), any(), any(), + any(), closeClickListener.capture(), any() ); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt index cabd472ec263..1820133a4795 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt @@ -240,7 +240,7 @@ class HandleMenuTest : ShellTestCase() { null /* openInBrowserLink */, captionWidth = HANDLE_WIDTH, captionHeight = 50, captionX = captionX ) - handleMenu.show(mock(), mock(), mock(), mock(), mock(), mock(), mock(), mock()) + handleMenu.show(mock(), mock(), mock(), mock(), mock(), mock(), mock(), mock(), mock()) return handleMenu } 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 94cabc492277..54dd15baa4c0 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 @@ -650,6 +650,57 @@ public class WindowDecorationTests extends ShellTestCase { } @Test + public void testRelayout_notAnInsetsSource_doesNotAddInsets() { + final Display defaultDisplay = mock(Display.class); + doReturn(defaultDisplay).when(mMockDisplayController) + .getDisplay(Display.DEFAULT_DISPLAY); + + final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder() + .setDisplayId(Display.DEFAULT_DISPLAY) + .setVisible(true) + .setBounds(new Rect(0, 0, 1000, 1000)) + .build(); + final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo); + + mRelayoutParams.mIsInsetSource = false; + windowDecor.relayout(taskInfo); + + // Never added. + verify(mMockWindowContainerTransaction, never()).addInsetsSource(eq(taskInfo.token), any(), + eq(0) /* index */, eq(captionBar()), any(), any(), anyInt()); + verify(mMockWindowContainerTransaction, never()).addInsetsSource(eq(taskInfo.token), any(), + eq(0) /* index */, eq(mandatorySystemGestures()), any(), any(), anyInt()); + } + + @Test + public void testRelayout_notAnInsetsSource_hadInsetsBefore_removesInsets() { + final Display defaultDisplay = mock(Display.class); + doReturn(defaultDisplay).when(mMockDisplayController) + .getDisplay(Display.DEFAULT_DISPLAY); + + final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder() + .setDisplayId(Display.DEFAULT_DISPLAY) + .setVisible(true) + .setBounds(new Rect(0, 0, 1000, 1000)) + .build(); + final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo); + + mRelayoutParams.mIsCaptionVisible = true; + mRelayoutParams.mIsInsetSource = true; + windowDecor.relayout(taskInfo); + + mRelayoutParams.mIsCaptionVisible = true; + mRelayoutParams.mIsInsetSource = false; + windowDecor.relayout(taskInfo); + + // Insets should be removed. + verify(mMockWindowContainerTransaction).removeInsetsSource(eq(taskInfo.token), any(), + eq(0) /* index */, eq(captionBar())); + verify(mMockWindowContainerTransaction).removeInsetsSource(eq(taskInfo.token), any(), + eq(0) /* index */, eq(mandatorySystemGestures())); + } + + @Test public void testClose_withExistingInsets_insetsRemoved() { final Display defaultDisplay = mock(Display.class); doReturn(defaultDisplay).when(mMockDisplayController) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipControllerTest.kt index 5594981135b1..741dfb8dd885 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/education/DesktopWindowingEducationTooltipControllerTest.kt @@ -24,14 +24,21 @@ import android.testing.TestableContext import android.testing.TestableLooper import android.testing.TestableResources import android.view.MotionEvent +import android.view.Surface.ROTATION_180 +import android.view.Surface.ROTATION_90 import android.view.View import android.view.WindowManager import android.widget.TextView +import android.window.WindowContainerTransaction +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb import androidx.test.filters.SmallTest import com.android.wm.shell.R import com.android.wm.shell.ShellTestCase +import com.android.wm.shell.common.DisplayController import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController.TooltipArrowDirection +import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController.TooltipColorScheme import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -42,9 +49,11 @@ import org.mockito.MockitoAnnotations import org.mockito.kotlin.any import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.argumentCaptor +import org.mockito.kotlin.atLeastOnce import org.mockito.kotlin.mock import org.mockito.kotlin.times import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever @SmallTest @TestableLooper.RunWithLooper(setAsMainLooper = true) @@ -52,6 +61,8 @@ import org.mockito.kotlin.verify class DesktopWindowingEducationTooltipControllerTest : ShellTestCase() { @Mock private lateinit var mockWindowManager: WindowManager @Mock private lateinit var mockViewContainerFactory: AdditionalSystemViewContainer.Factory + @Mock private lateinit var mockDisplayController: DisplayController + @Mock private lateinit var mockPopupWindow: AdditionalSystemViewContainer private lateinit var testableResources: TestableResources private lateinit var testableContext: TestableContext private lateinit var tooltipController: DesktopWindowingEducationTooltipController @@ -69,7 +80,8 @@ class DesktopWindowingEducationTooltipControllerTest : ShellTestCase() { Context.LAYOUT_INFLATER_SERVICE, context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)) testableContext.addMockSystemService(WindowManager::class.java, mockWindowManager) tooltipController = - DesktopWindowingEducationTooltipController(testableContext, mockViewContainerFactory) + DesktopWindowingEducationTooltipController( + testableContext, mockViewContainerFactory, mockDisplayController) } @Test @@ -218,8 +230,55 @@ class DesktopWindowingEducationTooltipControllerTest : ShellTestCase() { verify(mockLambda).invoke() } + @Test + fun showEducationTooltip_displayRotationChanged_hidesTooltip() { + whenever( + mockViewContainerFactory.create(any(), any(), any(), any(), any(), any(), any(), any())) + .thenReturn(mockPopupWindow) + val tooltipViewConfig = createTooltipConfig() + + tooltipController.showEducationTooltip(tooltipViewConfig = tooltipViewConfig, taskId = 123) + tooltipController.onDisplayChange( + /* displayId= */ 123, + /* fromRotation= */ ROTATION_90, + /* toRotation= */ ROTATION_180, + /* newDisplayAreaInfo= */ null, + WindowContainerTransaction(), + ) + + verify(mockPopupWindow, times(1)).releaseView() + verify(mockDisplayController, atLeastOnce()).removeDisplayChangingController(any()) + } + + @Test + fun showEducationTooltip_setTooltipColorScheme_correctColorsAreSet() { + val tooltipColorScheme = + TooltipColorScheme( + container = Color.Red.toArgb(), text = Color.Blue.toArgb(), icon = Color.Green.toArgb()) + val tooltipViewConfig = createTooltipConfig(tooltipColorScheme = tooltipColorScheme) + + tooltipController.showEducationTooltip(tooltipViewConfig = tooltipViewConfig, taskId = 123) + + verify(mockViewContainerFactory, times(1)) + .create( + windowManagerWrapper = any(), + taskId = anyInt(), + x = anyInt(), + y = anyInt(), + width = anyInt(), + height = anyInt(), + flags = anyInt(), + view = tooltipViewArgumentCaptor.capture()) + val tooltipTextView = + tooltipViewArgumentCaptor.lastValue.findViewById<TextView>(R.id.tooltip_text) + assertThat(tooltipTextView.textColors.defaultColor).isEqualTo(Color.Blue.toArgb()) + } + private fun createTooltipConfig( @LayoutRes tooltipViewLayout: Int = R.layout.desktop_windowing_education_top_arrow_tooltip, + tooltipColorScheme: TooltipColorScheme = + TooltipColorScheme( + container = Color.Red.toArgb(), text = Color.Red.toArgb(), icon = Color.Red.toArgb()), tooltipViewGlobalCoordinates: Point = Point(0, 0), tooltipText: String = "This is a tooltip", arrowDirection: TooltipArrowDirection = TooltipArrowDirection.UP, @@ -228,6 +287,7 @@ class DesktopWindowingEducationTooltipControllerTest : ShellTestCase() { ) = DesktopWindowingEducationTooltipController.EducationViewConfig( tooltipViewLayout = tooltipViewLayout, + tooltipColorScheme = tooltipColorScheme, tooltipViewGlobalCoordinates = tooltipViewGlobalCoordinates, tooltipText = tooltipText, arrowDirection = arrowDirection, diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp index a39f30bbad1f..385fbfe1a86a 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -75,6 +75,7 @@ cc_library { "BigBufferStream.cpp", "ChunkIterator.cpp", "ConfigDescription.cpp", + "CursorWindow.cpp", "FileStream.cpp", "Idmap.cpp", "LoadedArsc.cpp", @@ -113,7 +114,6 @@ cc_library { srcs: [ "BackupData.cpp", "BackupHelpers.cpp", - "CursorWindow.cpp", ], shared_libs: [ "libbase", @@ -147,11 +147,6 @@ cc_library { "libz", ], }, - host_linux: { - srcs: [ - "CursorWindow.cpp", - ], - }, windows: { enabled: true, }, diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp index cbb1e8f82838..abf2b0a91642 100644 --- a/libs/androidfw/CursorWindow.cpp +++ b/libs/androidfw/CursorWindow.cpp @@ -139,6 +139,7 @@ fail_silent: return UNKNOWN_ERROR; } +#ifdef __linux__ status_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outWindow) { *outWindow = nullptr; @@ -240,6 +241,7 @@ fail: fail_silent: return UNKNOWN_ERROR; } +#endif status_t CursorWindow::clear() { if (mReadOnly) { diff --git a/libs/androidfw/include/androidfw/CursorWindow.h b/libs/androidfw/include/androidfw/CursorWindow.h index c2eac12eb77d..0996355cd2c4 100644 --- a/libs/androidfw/include/androidfw/CursorWindow.h +++ b/libs/androidfw/include/androidfw/CursorWindow.h @@ -23,7 +23,9 @@ #include <string> #include "android-base/stringprintf.h" +#ifdef __linux__ #include "binder/Parcel.h" +#endif #include "utils/String8.h" #include "android-base/mapped_file.h" @@ -82,9 +84,11 @@ public: ~CursorWindow(); static status_t create(const String8& name, size_t size, CursorWindow** outCursorWindow); +#ifdef __linux__ static status_t createFromParcel(Parcel* parcel, CursorWindow** outCursorWindow); status_t writeToParcel(Parcel* parcel); +#endif inline String8 name() { return mName; } inline size_t size() { return mSize; } diff --git a/libs/appfunctions/api/current.txt b/libs/appfunctions/api/current.txt index bb0fc41acd30..bc269fedddfe 100644 --- a/libs/appfunctions/api/current.txt +++ b/libs/appfunctions/api/current.txt @@ -16,7 +16,7 @@ package com.google.android.appfunctions.sidecar { ctor public AppFunctionService(); method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent); method @MainThread public void onExecuteFunction(@NonNull com.google.android.appfunctions.sidecar.ExecuteAppFunctionRequest, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<com.google.android.appfunctions.sidecar.ExecuteAppFunctionResponse>); - method @Deprecated @MainThread public abstract void onExecuteFunction(@NonNull com.google.android.appfunctions.sidecar.ExecuteAppFunctionRequest, @NonNull java.util.function.Consumer<com.google.android.appfunctions.sidecar.ExecuteAppFunctionResponse>); + method @Deprecated @MainThread public void onExecuteFunction(@NonNull com.google.android.appfunctions.sidecar.ExecuteAppFunctionRequest, @NonNull java.util.function.Consumer<com.google.android.appfunctions.sidecar.ExecuteAppFunctionResponse>); field @NonNull public static final String BIND_APP_FUNCTION_SERVICE = "android.permission.BIND_APP_FUNCTION_SERVICE"; field @NonNull public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService"; } @@ -45,12 +45,12 @@ package com.google.android.appfunctions.sidecar { method @NonNull public static com.google.android.appfunctions.sidecar.ExecuteAppFunctionResponse newSuccess(@NonNull android.app.appsearch.GenericDocument, @Nullable android.os.Bundle); field public static final String PROPERTY_RETURN_VALUE = "returnValue"; field public static final int RESULT_APP_UNKNOWN_ERROR = 2; // 0x2 + field public static final int RESULT_CANCELLED = 6; // 0x6 field public static final int RESULT_DENIED = 1; // 0x1 - field public static final int RESULT_DISABLED = 6; // 0x6 + field public static final int RESULT_DISABLED = 5; // 0x5 field public static final int RESULT_INTERNAL_ERROR = 3; // 0x3 field public static final int RESULT_INVALID_ARGUMENT = 4; // 0x4 field public static final int RESULT_OK = 0; // 0x0 - field public static final int RESULT_TIMED_OUT = 5; // 0x5 } } diff --git a/libs/appfunctions/java/com/google/android/appfunctions/sidecar/AppFunctionService.java b/libs/appfunctions/java/com/google/android/appfunctions/sidecar/AppFunctionService.java index 6023c977bd76..6e91de6bbcf2 100644 --- a/libs/appfunctions/java/com/google/android/appfunctions/sidecar/AppFunctionService.java +++ b/libs/appfunctions/java/com/google/android/appfunctions/sidecar/AppFunctionService.java @@ -26,6 +26,7 @@ import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.CancellationSignal; +import android.util.Log; import java.util.function.Consumer; @@ -143,7 +144,11 @@ public abstract class AppFunctionService extends Service { */ @MainThread @Deprecated - public abstract void onExecuteFunction( + public void onExecuteFunction( @NonNull ExecuteAppFunctionRequest request, - @NonNull Consumer<ExecuteAppFunctionResponse> callback); + @NonNull Consumer<ExecuteAppFunctionResponse> callback) { + Log.w( + "AppFunctionService", + "Calling deprecated default implementation of onExecuteFunction"); + } } diff --git a/libs/appfunctions/java/com/google/android/appfunctions/sidecar/ExecuteAppFunctionResponse.java b/libs/appfunctions/java/com/google/android/appfunctions/sidecar/ExecuteAppFunctionResponse.java index c7ce95bab7a5..d87fec7985e9 100644 --- a/libs/appfunctions/java/com/google/android/appfunctions/sidecar/ExecuteAppFunctionResponse.java +++ b/libs/appfunctions/java/com/google/android/appfunctions/sidecar/ExecuteAppFunctionResponse.java @@ -73,11 +73,14 @@ public final class ExecuteAppFunctionResponse { */ public static final int RESULT_INVALID_ARGUMENT = 4; - /** The operation was timed out. */ - public static final int RESULT_TIMED_OUT = 5; - /** The caller tried to execute a disabled app function. */ - public static final int RESULT_DISABLED = 6; + public static final int RESULT_DISABLED = 5; + + /** + * The operation was cancelled. Use this error code to report that a cancellation is done after + * receiving a cancellation signal. + */ + public static final int RESULT_CANCELLED = 6; /** The result code of the app function execution. */ @ResultCode private final int mResultCode; @@ -236,7 +239,6 @@ public final class ExecuteAppFunctionResponse { RESULT_APP_UNKNOWN_ERROR, RESULT_INTERNAL_ERROR, RESULT_INVALID_ARGUMENT, - RESULT_TIMED_OUT, RESULT_DISABLED }) @Retention(RetentionPolicy.SOURCE) diff --git a/libs/hwui/AutoBackendTextureRelease.cpp b/libs/hwui/AutoBackendTextureRelease.cpp index 27add3542c01..430519606d9b 100644 --- a/libs/hwui/AutoBackendTextureRelease.cpp +++ b/libs/hwui/AutoBackendTextureRelease.cpp @@ -141,6 +141,13 @@ void AutoBackendTextureRelease::releaseQueueOwnership(GrDirectContext* context) return; } + if (!RenderThread::isCurrent()) { + // releaseQueueOwnership needs to run on RenderThread to prevent multithread calling + // setBackendTextureState will operate skia resource cache which need single owner + RenderThread::getInstance().queue().post([this, context]() { releaseQueueOwnership(context); }); + return; + } + LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan); if (mBackendTexture.isValid()) { // Passing in VK_IMAGE_LAYOUT_UNDEFINED means we keep the old layout. diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index b763a96e8e8a..c0160705fd47 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -19,6 +19,7 @@ #include <GLES2/gl2ext.h> // TODO: Use public SurfaceTexture APIs once available and include public NDK header file instead. +#include <statslog_hwui.h> #include <surfacetexture/surface_texture_platform.h> #include "AutoBackendTextureRelease.h" @@ -50,6 +51,14 @@ DeferredLayerUpdater::~DeferredLayerUpdater() { setTransform(nullptr); mRenderState.removeContextCallback(this); destroyLayer(); + if (mFirstTimeForDataspace > std::chrono::steady_clock::time_point::min()) { + auto currentTime = std::chrono::steady_clock::now(); + stats_write(stats::TEXTURE_VIEW_EVENT, static_cast<int32_t>(getuid()), + static_cast<int64_t>(std::chrono::duration_cast<std::chrono::milliseconds>( + currentTime - mFirstTimeForDataspace) + .count()), + mDataspace); + } } void DeferredLayerUpdater::setSurfaceTexture(AutoTextureRelease&& consumer) { @@ -195,6 +204,21 @@ void DeferredLayerUpdater::apply() { updateLayer(forceFilter, layerImage, outTransform, currentCropRect, maxLuminanceNits); } + + if (dataspace != mDataspace || + mFirstTimeForDataspace == std::chrono::steady_clock::time_point::min()) { + auto currentTime = std::chrono::steady_clock::now(); + if (mFirstTimeForDataspace > std::chrono::steady_clock::time_point::min()) { + stats_write(stats::TEXTURE_VIEW_EVENT, static_cast<int32_t>(getuid()), + static_cast<int64_t>( + std::chrono::duration_cast<std::chrono::milliseconds>( + currentTime - mFirstTimeForDataspace) + .count()), + mDataspace); + } + mFirstTimeForDataspace = currentTime; + mDataspace = dataspace; + } } } diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h index a7f8f6189a8e..3abb47ca92d1 100644 --- a/libs/hwui/DeferredLayerUpdater.h +++ b/libs/hwui/DeferredLayerUpdater.h @@ -16,6 +16,8 @@ #pragma once +#include <EGL/egl.h> +#include <EGL/eglext.h> #include <SkBlendMode.h> #include <SkColorFilter.h> #include <SkImage.h> @@ -24,9 +26,9 @@ #include <android/surface_texture.h> #include <cutils/compiler.h> #include <utils/Errors.h> +#include <utils/Timers.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> +#include <chrono> #include <map> #include <memory> @@ -154,6 +156,9 @@ private: bool mGLContextAttached; bool mUpdateTexImage; int mCurrentSlot = -1; + android_dataspace mDataspace = HAL_DATASPACE_UNKNOWN; + std::chrono::steady_clock::time_point mFirstTimeForDataspace = + std::chrono::steady_clock::time_point::min(); Layer* mLayer; }; diff --git a/libs/hwui/Gainmap.cpp b/libs/hwui/Gainmap.cpp index 30f401ef5f01..ea955e25dc2f 100644 --- a/libs/hwui/Gainmap.cpp +++ b/libs/hwui/Gainmap.cpp @@ -15,12 +15,37 @@ */ #include "Gainmap.h" +#include <SkBitmap.h> +#include <SkCanvas.h> +#include <SkColorFilter.h> +#include <SkImagePriv.h> +#include <SkPaint.h> + +#include "HardwareBitmapUploader.h" + namespace android::uirenderer { sp<Gainmap> Gainmap::allocateHardwareGainmap(const sp<Gainmap>& srcGainmap) { auto gainmap = sp<Gainmap>::make(); gainmap->info = srcGainmap->info; - const SkBitmap skSrcBitmap = srcGainmap->bitmap->getSkBitmap(); + SkBitmap skSrcBitmap = srcGainmap->bitmap->getSkBitmap(); + if (skSrcBitmap.info().colorType() == kAlpha_8_SkColorType && + !HardwareBitmapUploader::hasAlpha8Support()) { + // The regular Bitmap::allocateHardwareBitmap will do a conversion that preserves channels, + // so alpha8 maps to the alpha channel of rgba. However, for gainmaps we will interpret + // the data of an rgba buffer differently as we'll only look at the rgb channels + // So we need to map alpha8 to rgbx_8888 essentially + SkBitmap bitmap; + bitmap.allocPixels(skSrcBitmap.info().makeColorType(kN32_SkColorType)); + SkCanvas canvas(bitmap); + SkPaint paint; + const float alphaToOpaque[] = {0, 0, 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 255}; + paint.setColorFilter(SkColorFilters::Matrix(alphaToOpaque, SkColorFilters::Clamp::kNo)); + canvas.drawImage(SkMakeImageFromRasterBitmap(skSrcBitmap, kNever_SkCopyPixelsMode), 0, 0, + SkSamplingOptions{}, &paint); + skSrcBitmap = bitmap; + } sk_sp<Bitmap> skBitmap(Bitmap::allocateHardwareBitmap(skSrcBitmap)); if (!skBitmap.get()) { return nullptr; diff --git a/libs/hwui/hwui/ImageDecoder.cpp b/libs/hwui/hwui/ImageDecoder.cpp index 588463c49497..e074a27db38f 100644 --- a/libs/hwui/hwui/ImageDecoder.cpp +++ b/libs/hwui/hwui/ImageDecoder.cpp @@ -501,18 +501,13 @@ SkCodec::Result ImageDecoder::decode(void* pixels, size_t rowBytes) { SkCodec::Result ImageDecoder::extractGainmap(Bitmap* destination, bool isShared) { ATRACE_CALL(); SkGainmapInfo gainmapInfo; - std::unique_ptr<SkStream> gainmapStream; + std::unique_ptr<SkAndroidCodec> gainmapCodec; { - ATRACE_NAME("getAndroidGainmap"); - if (!mCodec->getAndroidGainmap(&gainmapInfo, &gainmapStream)) { + ATRACE_NAME("getGainmapAndroidCodec"); + if (!mCodec->getGainmapAndroidCodec(&gainmapInfo, &gainmapCodec)) { return SkCodec::kSuccess; } } - auto gainmapCodec = SkAndroidCodec::MakeFromStream(std::move(gainmapStream)); - if (!gainmapCodec) { - ALOGW("Failed to create codec for gainmap stream"); - return SkCodec::kInvalidInput; - } ImageDecoder decoder{std::move(gainmapCodec)}; // Gainmap inherits the origin of the containing image decoder.mOverrideOrigin.emplace(getOrigin()); diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp index ede385adc779..9cd6e253140e 100644 --- a/libs/hwui/hwui/MinikinUtils.cpp +++ b/libs/hwui/hwui/MinikinUtils.cpp @@ -48,6 +48,7 @@ minikin::MinikinPaint MinikinUtils::prepareMinikinPaint(const Paint* paint, minikinPaint.localeListId = paint->getMinikinLocaleListId(); minikinPaint.fontStyle = resolvedFace->fStyle; minikinPaint.fontFeatureSettings = paint->getFontFeatureSettings(); + minikinPaint.fontVariationSettings = paint->getFontVariationOverride(); const std::optional<minikin::FamilyVariant>& familyVariant = paint->getFamilyVariant(); if (familyVariant.has_value()) { diff --git a/libs/hwui/jni/BitmapFactory.cpp b/libs/hwui/jni/BitmapFactory.cpp index 785aef312072..49a7f73fb3a3 100644 --- a/libs/hwui/jni/BitmapFactory.cpp +++ b/libs/hwui/jni/BitmapFactory.cpp @@ -183,14 +183,8 @@ static bool needsFineScale(const SkISize fullSize, const SkISize decodedSize, needsFineScale(fullSize.height(), decodedSize.height(), sampleSize); } -static bool decodeGainmap(std::unique_ptr<SkStream> gainmapStream, const SkGainmapInfo& gainmapInfo, +static bool decodeGainmap(std::unique_ptr<SkAndroidCodec> codec, const SkGainmapInfo& gainmapInfo, sp<uirenderer::Gainmap>* outGainmap, const int sampleSize, float scale) { - std::unique_ptr<SkAndroidCodec> codec; - codec = SkAndroidCodec::MakeFromStream(std::move(gainmapStream), nullptr); - if (!codec) { - ALOGE("Can not create a codec for Gainmap."); - return false; - } SkColorType decodeColorType = kN32_SkColorType; if (codec->getInfo().colorType() == kGray_8_SkColorType) { decodeColorType = kGray_8_SkColorType; @@ -613,15 +607,15 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream, bool hasGainmap = false; SkGainmapInfo gainmapInfo; - std::unique_ptr<SkStream> gainmapStream = nullptr; + std::unique_ptr<SkAndroidCodec> gainmapCodec; sp<uirenderer::Gainmap> gainmap = nullptr; if (result == SkCodec::kSuccess) { - hasGainmap = codec->getAndroidGainmap(&gainmapInfo, &gainmapStream); + hasGainmap = codec->getGainmapAndroidCodec(&gainmapInfo, &gainmapCodec); } if (hasGainmap) { hasGainmap = - decodeGainmap(std::move(gainmapStream), gainmapInfo, &gainmap, sampleSize, scale); + decodeGainmap(std::move(gainmapCodec), gainmapInfo, &gainmap, sampleSize, scale); } if (!isMutable && javaBitmap == NULL) { diff --git a/libs/hwui/jni/BitmapRegionDecoder.cpp b/libs/hwui/jni/BitmapRegionDecoder.cpp index 6a65b8273194..f7e8e073a272 100644 --- a/libs/hwui/jni/BitmapRegionDecoder.cpp +++ b/libs/hwui/jni/BitmapRegionDecoder.cpp @@ -48,25 +48,14 @@ public: } SkGainmapInfo gainmapInfo; - std::unique_ptr<SkStream> gainmapStream; + std::unique_ptr<SkAndroidCodec> gainmapCodec; std::unique_ptr<skia::BitmapRegionDecoder> gainmapBRD = nullptr; - if (mainImageBRD->getAndroidGainmap(&gainmapInfo, &gainmapStream)) { - sk_sp<SkData> data = nullptr; - if (gainmapStream->getMemoryBase()) { - // It is safe to make without copy because we'll hold onto the stream. - data = SkData::MakeWithoutCopy(gainmapStream->getMemoryBase(), - gainmapStream->getLength()); - } else { - data = SkCopyStreamToData(gainmapStream.get()); - // We don't need to hold the stream anymore - gainmapStream = nullptr; - } - gainmapBRD = skia::BitmapRegionDecoder::Make(std::move(data)); + if (!mainImageBRD->getGainmapBitmapRegionDecoder(&gainmapInfo, &gainmapBRD)) { + gainmapBRD = nullptr; } - return std::unique_ptr<BitmapRegionDecoderWrapper>( - new BitmapRegionDecoderWrapper(std::move(mainImageBRD), std::move(gainmapBRD), - gainmapInfo, std::move(gainmapStream))); + return std::unique_ptr<BitmapRegionDecoderWrapper>(new BitmapRegionDecoderWrapper( + std::move(mainImageBRD), std::move(gainmapBRD), gainmapInfo)); } SkEncodedImageFormat getEncodedFormat() { return mMainImageBRD->getEncodedFormat(); } @@ -191,16 +180,14 @@ public: private: BitmapRegionDecoderWrapper(std::unique_ptr<skia::BitmapRegionDecoder> mainImageBRD, std::unique_ptr<skia::BitmapRegionDecoder> gainmapBRD, - SkGainmapInfo info, std::unique_ptr<SkStream> stream) + SkGainmapInfo info) : mMainImageBRD(std::move(mainImageBRD)) , mGainmapBRD(std::move(gainmapBRD)) - , mGainmapInfo(info) - , mGainmapStream(std::move(stream)) {} + , mGainmapInfo(info) {} std::unique_ptr<skia::BitmapRegionDecoder> mMainImageBRD; std::unique_ptr<skia::BitmapRegionDecoder> mGainmapBRD; SkGainmapInfo mGainmapInfo; - std::unique_ptr<SkStream> mGainmapStream; }; } // namespace android diff --git a/libs/hwui/jni/graphics_jni_helpers.h b/libs/hwui/jni/graphics_jni_helpers.h index 78db54acc9e5..91db134af18f 100644 --- a/libs/hwui/jni/graphics_jni_helpers.h +++ b/libs/hwui/jni/graphics_jni_helpers.h @@ -80,9 +80,52 @@ static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) { return static_cast<T>(res); } +// Inline variable that specifies the method binding format. +// The expected format is 'XX${method}XX', where ${method} represents the original method name. +// This variable is shared across all translation units. This is treated as a global variable as +// per C++ 17. +inline std::string jniMethodFormat; + +inline static void setJniMethodFormat(std::string value) { + jniMethodFormat = value; +} + +// Register the native methods, potenially applying the jniMethodFormat if it has been set. +static inline int jniRegisterMaybeRenamedNativeMethods(JNIEnv* env, const char* className, + const JNINativeMethod* gMethods, + int numMethods) { + if (jniMethodFormat.empty()) { + return jniRegisterNativeMethods(env, className, gMethods, numMethods); + } + + // Make a copy of gMethods with reformatted method names. + JNINativeMethod* modifiedMethods = new JNINativeMethod[numMethods]; + LOG_ALWAYS_FATAL_IF(!modifiedMethods, "Failed to allocate a copy of the JNI methods"); + + size_t methodNamePos = jniMethodFormat.find("${method}"); + LOG_ALWAYS_FATAL_IF(methodNamePos == std::string::npos, + "Invalid jniMethodFormat: could not find '${method}' in pattern"); + + for (int i = 0; i < numMethods; i++) { + modifiedMethods[i] = gMethods[i]; + std::string modifiedName = jniMethodFormat; + modifiedName.replace(methodNamePos, 9, gMethods[i].name); + char* modifiedNameChars = new char[modifiedName.length() + 1]; + LOG_ALWAYS_FATAL_IF(!modifiedNameChars, "Failed to allocate the new method name"); + std::strcpy(modifiedNameChars, modifiedName.c_str()); + modifiedMethods[i].name = modifiedNameChars; + } + int res = jniRegisterNativeMethods(env, className, modifiedMethods, numMethods); + for (int i = 0; i < numMethods; i++) { + delete[] modifiedMethods[i].name; + } + delete[] modifiedMethods; + return res; +} + static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { - int res = jniRegisterNativeMethods(env, className, gMethods, numMethods); + int res = jniRegisterMaybeRenamedNativeMethods(env, className, gMethods, numMethods); LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods."); return res; } diff --git a/libs/hwui/jni/text/TextShaper.cpp b/libs/hwui/jni/text/TextShaper.cpp index 6c05346d26da..456338631ae4 100644 --- a/libs/hwui/jni/text/TextShaper.cpp +++ b/libs/hwui/jni/text/TextShaper.cpp @@ -156,16 +156,47 @@ static jboolean TextShaper_Result_getFakeItalic(CRITICAL_JNI_PARAMS_COMMA jlong return layout->layout.getFakery(i).isFakeItalic(); } +float findValueFromVariationSettings(const minikin::FontFakery& fakery, minikin::AxisTag tag) { + for (const minikin::FontVariation& fv : fakery.variationSettings()) { + if (fv.axisTag == tag) { + return fv.value; + } + } + return std::numeric_limits<float>::quiet_NaN(); +} + // CriticalNative static jfloat TextShaper_Result_getWeightOverride(CRITICAL_JNI_PARAMS_COMMA jlong ptr, jint i) { const LayoutWrapper* layout = reinterpret_cast<LayoutWrapper*>(ptr); - return layout->layout.getFakery(i).wghtAdjustment(); + if (text_feature::typeface_redesign()) { + float value = + findValueFromVariationSettings(layout->layout.getFakery(i), minikin::TAG_wght); + if (!std::isnan(value)) { + return value; + } else { + const std::shared_ptr<minikin::Font>& font = layout->layout.getFontRef(i); + return font->style().weight(); + } + } else { + return layout->layout.getFakery(i).wghtAdjustment(); + } } // CriticalNative static jfloat TextShaper_Result_getItalicOverride(CRITICAL_JNI_PARAMS_COMMA jlong ptr, jint i) { const LayoutWrapper* layout = reinterpret_cast<LayoutWrapper*>(ptr); - return layout->layout.getFakery(i).italAdjustment(); + if (text_feature::typeface_redesign()) { + float value = + findValueFromVariationSettings(layout->layout.getFakery(i), minikin::TAG_ital); + if (!std::isnan(value)) { + return value; + } else { + const std::shared_ptr<minikin::Font>& font = layout->layout.getFontRef(i); + return font->style().isItalic(); + } + } else { + return layout->layout.getFakery(i).italAdjustment(); + } } // CriticalNative diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index c90c44152440..0da8371bc824 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -16,6 +16,9 @@ package android.media; +import static android.media.audio.Flags.FLAG_DOLBY_AC4_LEVEL4_ENCODING_API; + +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; @@ -309,7 +312,7 @@ public final class AudioFormat implements Parcelable { public static final int ENCODING_AAC_ELD = 15; /** Audio data format: AAC xHE compressed */ public static final int ENCODING_AAC_XHE = 16; - /** Audio data format: AC-4 sync frame transport format */ + /** Audio data format: AC-4 (levels 0-3) sync frame transport format */ public static final int ENCODING_AC4 = 17; /** Audio data format: E-AC-3-JOC compressed * E-AC-3-JOC streams can be decoded by downstream devices supporting {@link #ENCODING_E_AC3}. @@ -375,6 +378,9 @@ public final class AudioFormat implements Parcelable { public static final int ENCODING_DTS_UHD_P2 = 30; /** Audio data format: Direct Stream Digital */ public static final int ENCODING_DSD = 31; + /** Audio data format: AC-4 level 4 sync frame transport format */ + @FlaggedApi(FLAG_DOLBY_AC4_LEVEL4_ENCODING_API) + public static final int ENCODING_AC4_L4 = 32; /** @hide */ public static String toLogFriendlyEncoding(int enc) { @@ -413,6 +419,8 @@ public final class AudioFormat implements Parcelable { return "ENCODING_AAC_XHE"; case ENCODING_AC4: return "ENCODING_AC4"; + case ENCODING_AC4_L4: + return "ENCODING_AC4_L4"; case ENCODING_E_AC3_JOC: return "ENCODING_E_AC3_JOC"; case ENCODING_DOLBY_MAT: @@ -823,6 +831,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AC4_L4: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -863,6 +872,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AC4_L4: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -908,6 +918,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AC4_L4: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -950,6 +961,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AC4_L4: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -1238,6 +1250,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AC4_L4: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -1468,6 +1481,7 @@ public final class AudioFormat implements Parcelable { ENCODING_AAC_ELD, ENCODING_AAC_XHE, ENCODING_AC4, + ENCODING_AC4_L4, ENCODING_E_AC3_JOC, ENCODING_DOLBY_MAT, ENCODING_OPUS, @@ -1506,6 +1520,7 @@ public final class AudioFormat implements Parcelable { ENCODING_AAC_ELD, ENCODING_AAC_XHE, ENCODING_AC4, + ENCODING_AC4_L4, ENCODING_E_AC3_JOC, ENCODING_DOLBY_MAT, ENCODING_OPUS, @@ -1533,6 +1548,7 @@ public final class AudioFormat implements Parcelable { ENCODING_AAC_LC, ENCODING_DOLBY_TRUEHD, ENCODING_AC4, + ENCODING_AC4_L4, ENCODING_E_AC3_JOC, ENCODING_DOLBY_MAT, ENCODING_MPEGH_BL_L3, @@ -1554,6 +1570,7 @@ public final class AudioFormat implements Parcelable { ENCODING_AAC_LC, ENCODING_DOLBY_TRUEHD, ENCODING_AC4, + ENCODING_AC4_L4, ENCODING_E_AC3_JOC, ENCODING_DOLBY_MAT, ENCODING_MPEGH_BL_L3, @@ -1592,7 +1609,9 @@ public final class AudioFormat implements Parcelable { case ENCODING_DOLBY_TRUEHD: return "Dolby TrueHD"; case ENCODING_AC4: - return "Dolby AC-4"; + return "Dolby AC-4 levels 0-3"; + case ENCODING_AC4_L4: + return "Dolby AC-4 level 4"; case ENCODING_E_AC3_JOC: return "Dolby Atmos in Dolby Digital Plus"; case ENCODING_DOLBY_MAT: diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index ebdfd3e41aa1..a8b863bc67f9 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -542,6 +542,8 @@ public class AudioSystem return "AUDIO_FORMAT_AAC_LATM_HE_V2"; // (AAC_LATM | AAC_SUB_HE_V2) case /* AUDIO_FORMAT_E_AC3_JOC */ 0xA000001: return "AUDIO_FORMAT_E_AC3_JOC"; // (E_AC3 | E_AC3_SUB_JOC) + case /* AUDIO_FORMAT_AC4_L4 */ 0x22000001: + return "AUDIO_FORMAT_AC4_L4"; // (AC4 | AC4_SUB_L4) case /* AUDIO_FORMAT_MAT_1_0 */ 0x24000001: return "AUDIO_FORMAT_MAT_1_0"; // (MAT | MAT_SUB_1_0) case /* AUDIO_FORMAT_MAT_2_0 */ 0x24000002: diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java index 47637b82111a..290d49b31eb7 100644 --- a/media/java/android/media/session/PlaybackState.java +++ b/media/java/android/media/session/PlaybackState.java @@ -15,10 +15,8 @@ */ package android.media.session; -import static com.android.media.flags.Flags.FLAG_ENABLE_NOTIFYING_ACTIVITY_MANAGER_WITH_MEDIA_SESSION_STATUS_CHANGE; import android.annotation.DrawableRes; -import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.LongDef; import android.annotation.Nullable; @@ -187,13 +185,21 @@ public final class PlaybackState implements Parcelable { */ public static final long ACTION_SET_PLAYBACK_SPEED = 1 << 22; - /** - * @hide - */ - @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING, - STATE_REWINDING, STATE_BUFFERING, STATE_ERROR, STATE_CONNECTING, - STATE_SKIPPING_TO_PREVIOUS, STATE_SKIPPING_TO_NEXT, STATE_SKIPPING_TO_QUEUE_ITEM, - STATE_PLAYBACK_SUPPRESSED}) + /** @hide */ + @IntDef({ + STATE_NONE, + STATE_STOPPED, + STATE_PAUSED, + STATE_PLAYING, + STATE_FAST_FORWARDING, + STATE_REWINDING, + STATE_BUFFERING, + STATE_ERROR, + STATE_CONNECTING, + STATE_SKIPPING_TO_PREVIOUS, + STATE_SKIPPING_TO_NEXT, + STATE_SKIPPING_TO_QUEUE_ITEM + }) @Retention(RetentionPolicy.SOURCE) public @interface State {} @@ -290,19 +296,6 @@ public final class PlaybackState implements Parcelable { public static final int STATE_SKIPPING_TO_QUEUE_ITEM = 11; /** - * State indicating that playback is paused due to an external transient interruption, like a - * phone call. - * - * <p>This state is different from {@link #STATE_PAUSED} in that it is deemed transitory, - * possibly allowing the service associated to the session in this state to run in the - * foreground. - * - * @see Builder#setState - */ - @FlaggedApi(FLAG_ENABLE_NOTIFYING_ACTIVITY_MANAGER_WITH_MEDIA_SESSION_STATUS_CHANGE) - public static final int STATE_PLAYBACK_SUPPRESSED = 12; - - /** * Use this value for the position to indicate the position is not known. */ public static final long PLAYBACK_POSITION_UNKNOWN = -1; @@ -401,7 +394,6 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li> * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li> * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li> - * <li> {@link PlaybackState#STATE_PLAYBACK_SUPPRESSED}</li> * </ul> */ @State @@ -525,7 +517,6 @@ public final class PlaybackState implements Parcelable { * <li>{@link #STATE_SKIPPING_TO_NEXT}</li> * <li>{@link #STATE_SKIPPING_TO_PREVIOUS}</li> * <li>{@link #STATE_SKIPPING_TO_QUEUE_ITEM}</li> - * <li>{@link #STATE_PLAYBACK_SUPPRESSED}</li> * </ul> */ public boolean isActive() { @@ -538,7 +529,6 @@ public final class PlaybackState implements Parcelable { case PlaybackState.STATE_BUFFERING: case PlaybackState.STATE_CONNECTING: case PlaybackState.STATE_PLAYING: - case PlaybackState.STATE_PLAYBACK_SUPPRESSED: return true; } return false; @@ -584,8 +574,6 @@ public final class PlaybackState implements Parcelable { return "SKIPPING_TO_NEXT"; case STATE_SKIPPING_TO_QUEUE_ITEM: return "SKIPPING_TO_QUEUE_ITEM"; - case STATE_PLAYBACK_SUPPRESSED: - return "STATE_PLAYBACK_SUPPRESSED"; default: return "UNKNOWN"; } @@ -823,7 +811,6 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li> * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li> * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li> - * <li> {@link PlaybackState#STATE_PLAYBACK_SUPPRESSED}</li> * </ul> * * @param state The current state of playback. @@ -868,7 +855,6 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li> * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li> * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li> - * <li> {@link PlaybackState#STATE_PLAYBACK_SUPPRESSED}</li> * </ul> * * @param state The current state of playback. diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java index 4676dffb727f..84a13ab9aba1 100644 --- a/media/java/android/media/tv/tuner/filter/MediaEvent.java +++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java @@ -17,12 +17,14 @@ package android.media.tv.tuner.filter; import android.annotation.BytesLong; +import android.annotation.FlaggedApi; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.media.AudioPresentation; import android.media.MediaCodec.LinearBlock; +import android.media.tv.flags.Flags; import java.util.Collections; import java.util.List; @@ -57,12 +59,16 @@ public class MediaEvent extends FilterEvent { private final int mScIndexMask; private final AudioDescriptor mExtraMetaData; private final List<AudioPresentation> mAudioPresentations; + private final int mNumDataPieces; + private final int mIndexInDataGroup; + private final int mDataGroupId; // This constructor is used by JNI code only private MediaEvent(int streamId, boolean isPtsPresent, long pts, boolean isDtsPresent, long dts, long dataLength, long offset, LinearBlock buffer, boolean isSecureMemory, long dataId, int mpuSequenceNumber, boolean isPrivateData, int scIndexMask, - AudioDescriptor extraMetaData, List<AudioPresentation> audioPresentations) { + AudioDescriptor extraMetaData, List<AudioPresentation> audioPresentations, + int numDataPieces, int indexInDataGroup, int dataGroupId) { mStreamId = streamId; mIsPtsPresent = isPtsPresent; mPts = pts; @@ -78,6 +84,9 @@ public class MediaEvent extends FilterEvent { mScIndexMask = scIndexMask; mExtraMetaData = extraMetaData; mAudioPresentations = audioPresentations; + mNumDataPieces = numDataPieces; + mIndexInDataGroup = indexInDataGroup; + mDataGroupId = dataGroupId; } /** @@ -235,6 +244,67 @@ public class MediaEvent extends FilterEvent { } /** + * Gets the number of data pieces into which the original data was split. + * + * <p>The {@link #getNumDataPieces()}, {@link #getIndexInDataGroup()} and + * {@link #getDataGroupId()} methods should be used together to reassemble the original data if + * it was split into pieces. Use {@link #getLinearBlock()} to get the memory where the data + * pieces are stored. + * + * @return 0 or 1 if this MediaEvent object contains the complete data; otherwise the number of + * pieces into which the original data was split. + * @see #getIndexInDataGroup() + * @see #getDataGroupId() + * @see #getLinearBlock() + */ + @FlaggedApi(Flags.FLAG_TUNER_W_APIS) + @IntRange(from = 0) + public int getNumDataPieces() { + return mNumDataPieces; + } + + /** + * Gets the index of the data piece. The index in the data group indicates the order in which + * this {@link MediaEvent}'s data piece should be reassembled. The result should be within the + * range [0, {@link #getNumDataPieces()}). + * + * <p>The {@link #getNumDataPieces()}, {@link #getIndexInDataGroup()} and + * {@link #getDataGroupId()} methods should be used together to reassemble the original data if + * it was split into pieces. Use {@link #getLinearBlock()} to get the memory where the data + * pieces are stored. + * + * @return The index in the data group. + * @see #getNumDataPieces() + * @see #getDataGroupId() + * @see #getLinearBlock() + */ + @FlaggedApi(Flags.FLAG_TUNER_W_APIS) + @IntRange(from = 0) + public int getIndexInDataGroup() { + return mIndexInDataGroup; + } + + /** + * Gets the group ID for reassembling the complete data. {@link MediaEvent}s that have the same + * data group ID contain different pieces of the same data. This value should be ignored if + * {@link #getNumDataPieces()} returns 0 or 1. + * + * <p>The {@link #getNumDataPieces()}, {@link #getIndexInDataGroup()} and + * {@link #getDataGroupId()} methods should be used together to reassemble the original data if + * it was split into pieces. Use {@link #getLinearBlock()} to get the memory where the data + * pieces are stored. + * + * @return The data group ID. + * @see #getNumDataPieces() + * @see #getIndexInDataGroup() + * @see #getLinearBlock() + */ + @FlaggedApi(Flags.FLAG_TUNER_W_APIS) + public int getDataGroupId() { + return mDataGroupId; + } + + /** * Finalize the MediaEvent object. * @hide */ diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index 00b0e57c09ea..49e794116011 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -686,12 +686,16 @@ void FilterClientCallbackImpl::getMediaEvent(const jobjectArray& arr, const int } else if (mediaEvent.scIndexMask.getTag() == DemuxFilterScIndexMask::Tag::scVvc) { sc = mediaEvent.scIndexMask.get<DemuxFilterScIndexMask::Tag::scVvc>(); } + jint numDataPieces = mediaEvent.numDataPieces; + jint indexInDataGroup = mediaEvent.indexInDataGroup; + jint dataGroupId = mediaEvent.dataGroupId; ScopedLocalRef obj(env, env->NewObject(mMediaEventClass, mMediaEventInitID, streamId, isPtsPresent, pts, isDtsPresent, dts, dataLength, offset, nullptr, isSecureMemory, avDataId, mpuSequenceNumber, isPesPrivateData, sc, - audioDescriptor.get(), presentationsJObj.get())); + audioDescriptor.get(), presentationsJObj.get(), + numDataPieces, indexInDataGroup, dataGroupId)); // Protect mFilterClient from being set to null. android::Mutex::Autolock autoLock(mLock); @@ -1048,7 +1052,7 @@ FilterClientCallbackImpl::FilterClientCallbackImpl() { "<init>", "(IZJZJJJLandroid/media/MediaCodec$LinearBlock;" "ZJIZILandroid/media/tv/tuner/filter/AudioDescriptor;" - "Ljava/util/List;)V"); + "Ljava/util/List;III)V"); mAudioDescriptorInitID = env->GetMethodID(mAudioDescriptorClass, "<init>", "(BBCBBB)V"); mPesEventInitID = env->GetMethodID(mPesEventClass, "<init>", "(III)V"); mTsRecordEventInitID = env->GetMethodID(mTsRecordEventClass, "<init>", "(IIIJJI)V"); diff --git a/nfc/Android.bp b/nfc/Android.bp index db3dcb0631dd..7ad8c4c8de41 100644 --- a/nfc/Android.bp +++ b/nfc/Android.bp @@ -41,6 +41,10 @@ java_sdk_library { "framework-permission-s.stubs.module_lib", "framework-permission.stubs.module_lib", ], + stub_only_libs: [ + // Needed for javadoc references. + "framework-permission-s.stubs.module_lib", + ], static_libs: [ "android.nfc.flags-aconfig-java", "android.permission.flags-aconfig-java", diff --git a/nfc/api/current.txt b/nfc/api/current.txt index e7cb76c370fd..96b7c1339190 100644 --- a/nfc/api/current.txt +++ b/nfc/api/current.txt @@ -223,6 +223,7 @@ package android.nfc.cardemulation { field public static final String CATEGORY_PAYMENT = "payment"; field public static final String EXTRA_CATEGORY = "category"; field public static final String EXTRA_SERVICE_COMPONENT = "component"; + field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT = 3; // 0x3 field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DH = 0; // 0x0 field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE = 1; // 0x1 field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC = 2; // 0x2 diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt index 94231b0facdb..4428adee818d 100644 --- a/nfc/api/system-current.txt +++ b/nfc/api/system-current.txt @@ -58,12 +58,16 @@ package android.nfc { @FlaggedApi("android.nfc.nfc_oem_extension") public final class NfcOemExtension { method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearPreference(); method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public java.util.List<java.lang.String> getActiveNfceeList(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.nfc.RoutingStatus getRoutingStatus(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean hasUserEnabledNfc(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isAutoChangeEnabled(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isTagPresent(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void maybeTriggerFirmwareUpdate(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void overwriteRoutingTable(int, int, int); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void pausePolling(int); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcOemExtension.Callback); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void resumePolling(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAutoChangeEnabled(boolean); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void setControllerAlwaysOnMode(int); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void synchronizeScreenState(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void triggerInitialization(); @@ -90,7 +94,11 @@ package android.nfc { method public void onEnable(@NonNull java.util.function.Consumer<java.lang.Boolean>); method public void onEnableFinished(int); method public void onEnableStarted(); + method public void onGetOemAppSearchIntent(@NonNull java.util.List<java.lang.String>, @NonNull java.util.function.Consumer<android.content.Intent>); method public void onHceEventReceived(int); + method public void onLaunchHceAppChooserActivity(@NonNull String, @NonNull java.util.List<android.nfc.cardemulation.ApduServiceInfo>, @NonNull android.content.ComponentName, @NonNull String); + method public void onLaunchHceTapAgainDialog(@NonNull android.nfc.cardemulation.ApduServiceInfo, @NonNull String); + method public void onNdefMessage(@NonNull android.nfc.Tag, @NonNull android.nfc.NdefMessage, @NonNull java.util.function.Consumer<java.lang.Boolean>); method public void onNdefRead(@NonNull java.util.function.Consumer<java.lang.Boolean>); method public void onReaderOptionChanged(boolean); method public void onRfDiscoveryStarted(boolean); @@ -101,6 +109,12 @@ package android.nfc { method public void onTagDispatch(@NonNull java.util.function.Consumer<java.lang.Boolean>); } + @FlaggedApi("android.nfc.nfc_oem_extension") public class RoutingStatus { + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int getDefaultIsoDepRoute(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int getDefaultOffHostRoute(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int getDefaultRoute(); + } + } package android.nfc.cardemulation { diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl index 19b9e0f0b515..1eae3c6f30f1 100644 --- a/nfc/java/android/nfc/INfcCardEmulation.aidl +++ b/nfc/java/android/nfc/INfcCardEmulation.aidl @@ -51,4 +51,8 @@ interface INfcCardEmulation void overrideRoutingTable(int userHandle, String protocol, String technology, in String pkg); void recoverRoutingTable(int userHandle); boolean isEuiccSupported(); + void setAutoChangeStatus(boolean state); + boolean isAutoChangeEnabled(); + List<String> getRoutingStatus(); + void overwriteRoutingTable(int userHandle, String emptyAid, String protocol, String tech); } diff --git a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl index e49ef7e80705..48c7ee659266 100644 --- a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl +++ b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl @@ -15,9 +15,14 @@ */ package android.nfc; +import android.content.ComponentName; +import android.nfc.cardemulation.ApduServiceInfo; +import android.nfc.NdefMessage; import android.nfc.Tag; import android.os.ResultReceiver; +import java.util.List; + /** * @hide */ @@ -41,4 +46,8 @@ interface INfcOemExtensionCallback { void onCardEmulationActivated(boolean isActivated); void onRfFieldActivated(boolean isActivated); void onRfDiscoveryStarted(boolean isDiscoveryStarted); + void onGetOemAppSearchIntent(in List<String> firstPackage, in ResultReceiver intentConsumer); + void onNdefMessage(in Tag tag, in NdefMessage message, in ResultReceiver hasOemExecutableContent); + void onLaunchHceAppChooserActivity(in String selectedAid, in List<ApduServiceInfo> services, in ComponentName failedComponent, in String category); + void onLaunchHceTapAgainActivity(in ApduServiceInfo service, in String category); } diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java index 6d5c069bca3a..fb63b5c03d00 100644 --- a/nfc/java/android/nfc/NfcOemExtension.java +++ b/nfc/java/android/nfc/NfcOemExtension.java @@ -16,6 +16,12 @@ package android.nfc; +import static android.nfc.cardemulation.CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_DH; +import static android.nfc.cardemulation.CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE; +import static android.nfc.cardemulation.CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC; +import static android.nfc.cardemulation.CardEmulation.routeIntToString; + +import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; @@ -23,8 +29,14 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.nfc.cardemulation.ApduServiceInfo; +import android.nfc.cardemulation.CardEmulation; +import android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute; import android.os.Binder; +import android.os.Bundle; import android.os.RemoteException; import android.os.ResultReceiver; import android.util.Log; @@ -306,6 +318,60 @@ public final class NfcOemExtension { * @param isDiscoveryStarted true, if RF discovery started, else RF state is Idle. */ void onRfDiscoveryStarted(boolean isDiscoveryStarted); + + /** + * Gets the intent to find the OEM package in the OEM App market. If the consumer returns + * {@code null} or a timeout occurs, the intent from the first available package will be + * used instead. + * + * @param packages the OEM packages name stored in the tag + * @param intentConsumer The {@link Consumer} to be completed. + * The {@link Consumer#accept(Object)} should be called with + * the Intent required. + * + */ + void onGetOemAppSearchIntent(@NonNull List<String> packages, + @NonNull Consumer<Intent> intentConsumer); + + /** + * Checks if the NDEF message contains any specific OEM package executable content + * + * @param tag the {@link android.nfc.Tag Tag} + * @param message NDEF Message to read from tag + * @param hasOemExecutableContent The {@link Consumer} to be completed. If there is + * OEM package executable content, the + * {@link Consumer#accept(Object)} should be called with + * {@link Boolean#TRUE}, otherwise call with + * {@link Boolean#FALSE}. + */ + void onNdefMessage(@NonNull Tag tag, @NonNull NdefMessage message, + @NonNull Consumer<Boolean> hasOemExecutableContent); + + /** + * Callback to indicate the app chooser activity should be launched for handling CE + * transaction. This is invoked for example when there are more than 1 app installed that + * can handle the HCE transaction. OEMs can launch the Activity based + * on their requirement. + * + * @param selectedAid the selected AID from APDU + * @param services {@link ApduServiceInfo} of the service triggering the activity + * @param failedComponent the component failed to be resolved + * @param category the category of the service + */ + void onLaunchHceAppChooserActivity(@NonNull String selectedAid, + @NonNull List<ApduServiceInfo> services, + @NonNull ComponentName failedComponent, + @NonNull String category); + + /** + * Callback to indicate tap again dialog should be launched for handling HCE transaction. + * This is invoked for example when a CE service needs the device to unlocked before + * handling the transaction. OEMs can launch the Activity based on their requirement. + * + * @param service {@link ApduServiceInfo} of the service triggering the dialog + * @param category the category of the service + */ + void onLaunchHceTapAgainDialog(@NonNull ApduServiceInfo service, @NonNull String category); } @@ -523,6 +589,85 @@ public final class NfcOemExtension { NfcAdapter.callService(() -> NfcAdapter.sService.resumePolling()); } + /** + * Set whether to enable auto routing change or not (enabled by default). + * If disabled, routing targets are limited to a single off-host destination. + * + * @param state status of auto routing change, true if enable, otherwise false + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + public void setAutoChangeEnabled(boolean state) { + NfcAdapter.callService(() -> + NfcAdapter.sCardEmulationService.setAutoChangeStatus(state)); + } + + /** + * Check if auto routing change is enabled or not. + * + * @return true if enabled, otherwise false + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + public boolean isAutoChangeEnabled() { + return NfcAdapter.callServiceReturn(() -> + NfcAdapter.sCardEmulationService.isAutoChangeEnabled(), false); + } + + /** + * Get current routing status + * + * @return {@link RoutingStatus} indicating the default route, default ISO-DEP + * route and default off-host route. + */ + @NonNull + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + public RoutingStatus getRoutingStatus() { + List<String> status = NfcAdapter.callServiceReturn(() -> + NfcAdapter.sCardEmulationService.getRoutingStatus(), new ArrayList<>()); + return new RoutingStatus(routeStringToInt(status.get(0)), + routeStringToInt(status.get(1)), + routeStringToInt(status.get(2))); + } + + /** + * Overwrites NFC controller routing table, which includes Protocol Route, Technology Route, + * and Empty AID Route. + * + * The parameter set to + * {@link ProtocolAndTechnologyRoute#PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET} + * can be used to keep current values for that entry. At least one route should be overridden + * when calling this API, otherwise throw {@link IllegalArgumentException}. + * + * @param protocol ISO-DEP route destination, where the possible inputs are defined in + * {@link ProtocolAndTechnologyRoute}. + * @param technology Tech-A, Tech-B and Tech-F route destination, where the possible inputs + * are defined in + * {@link ProtocolAndTechnologyRoute} + * @param emptyAid Zero-length AID route destination, where the possible inputs are defined in + * {@link ProtocolAndTechnologyRoute} + */ + @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + public void overwriteRoutingTable( + @CardEmulation.ProtocolAndTechnologyRoute int protocol, + @CardEmulation.ProtocolAndTechnologyRoute int technology, + @CardEmulation.ProtocolAndTechnologyRoute int emptyAid) { + + String protocolRoute = routeIntToString(protocol); + String technologyRoute = routeIntToString(technology); + String emptyAidRoute = routeIntToString(emptyAid); + + NfcAdapter.callService(() -> + NfcAdapter.sCardEmulationService.overwriteRoutingTable( + mContext.getUser().getIdentifier(), + emptyAidRoute, + protocolRoute, + technologyRoute + )); + } + private final class NfcOemExtensionCallback extends INfcOemExtensionCallback.Stub { @Override @@ -562,25 +707,25 @@ public final class NfcOemExtension { public void onApplyRouting(ResultReceiver isSkipped) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( - new ReceiverWrapper(isSkipped), cb::onApplyRouting, ex)); + new ReceiverWrapper<>(isSkipped), cb::onApplyRouting, ex)); } @Override public void onNdefRead(ResultReceiver isSkipped) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( - new ReceiverWrapper(isSkipped), cb::onNdefRead, ex)); + new ReceiverWrapper<>(isSkipped), cb::onNdefRead, ex)); } @Override public void onEnable(ResultReceiver isAllowed) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( - new ReceiverWrapper(isAllowed), cb::onEnable, ex)); + new ReceiverWrapper<>(isAllowed), cb::onEnable, ex)); } @Override public void onDisable(ResultReceiver isAllowed) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( - new ReceiverWrapper(isAllowed), cb::onDisable, ex)); + new ReceiverWrapper<>(isAllowed), cb::onDisable, ex)); } @Override public void onBootStarted() throws RemoteException { @@ -616,7 +761,7 @@ public final class NfcOemExtension { public void onTagDispatch(ResultReceiver isSkipped) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( - new ReceiverWrapper(isSkipped), cb::onTagDispatch, ex)); + new ReceiverWrapper<>(isSkipped), cb::onTagDispatch, ex)); } @Override public void onRoutingChanged() throws RemoteException { @@ -635,6 +780,59 @@ public final class NfcOemExtension { handleVoidCallback(enabled, cb::onReaderOptionChanged, ex)); } + @Override + public void onGetOemAppSearchIntent(List<String> packages, ResultReceiver intentConsumer) + throws RemoteException { + mCallbackMap.forEach((cb, ex) -> + handleVoid2ArgCallback(packages, new ReceiverWrapper<>(intentConsumer), + cb::onGetOemAppSearchIntent, ex)); + } + + @Override + public void onNdefMessage(Tag tag, NdefMessage message, + ResultReceiver hasOemExecutableContent) throws RemoteException { + mCallbackMap.forEach((cb, ex) -> { + synchronized (mLock) { + final long identity = Binder.clearCallingIdentity(); + try { + ex.execute(() -> cb.onNdefMessage( + tag, message, new ReceiverWrapper<>(hasOemExecutableContent))); + } catch (RuntimeException exception) { + throw exception; + } finally { + Binder.restoreCallingIdentity(identity); + } + } + }); + } + + @Override + public void onLaunchHceAppChooserActivity(String selectedAid, + List<ApduServiceInfo> services, + ComponentName failedComponent, String category) + throws RemoteException { + mCallbackMap.forEach((cb, ex) -> { + synchronized (mLock) { + final long identity = Binder.clearCallingIdentity(); + try { + ex.execute(() -> cb.onLaunchHceAppChooserActivity( + selectedAid, services, failedComponent, category)); + } catch (RuntimeException exception) { + throw exception; + } finally { + Binder.restoreCallingIdentity(identity); + } + } + }); + } + + @Override + public void onLaunchHceTapAgainActivity(ApduServiceInfo service, String category) + throws RemoteException { + mCallbackMap.forEach((cb, ex) -> + handleVoid2ArgCallback(service, category, cb::onLaunchHceTapAgainDialog, ex)); + } + private <T> void handleVoidCallback( T input, Consumer<T> callbackMethod, Executor executor) { synchronized (mLock) { @@ -718,7 +916,16 @@ public final class NfcOemExtension { } } - private class ReceiverWrapper implements Consumer<Boolean> { + private @CardEmulation.ProtocolAndTechnologyRoute int routeStringToInt(String route) { + return switch (route) { + case "DH" -> PROTOCOL_AND_TECHNOLOGY_ROUTE_DH; + case "eSE" -> PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE; + case "SIM" -> PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC; + default -> throw new IllegalStateException("Unexpected value: " + route); + }; + } + + private class ReceiverWrapper<T> implements Consumer<T> { private final ResultReceiver mResultReceiver; ReceiverWrapper(ResultReceiver resultReceiver) { @@ -726,12 +933,19 @@ public final class NfcOemExtension { } @Override - public void accept(Boolean result) { - mResultReceiver.send(result ? 1 : 0, null); + public void accept(T result) { + if (result instanceof Boolean) { + mResultReceiver.send((Boolean) result ? 1 : 0, null); + } else if (result instanceof Intent) { + Bundle bundle = new Bundle(); + bundle.putParcelable("intent", (Intent) result); + mResultReceiver.send(0, bundle); + } + } @Override - public Consumer<Boolean> andThen(Consumer<? super Boolean> after) { + public Consumer<T> andThen(Consumer<? super T> after) { return Consumer.super.andThen(after); } } diff --git a/nfc/java/android/nfc/RoutingStatus.java b/nfc/java/android/nfc/RoutingStatus.java new file mode 100644 index 000000000000..4a1b1f3cecbc --- /dev/null +++ b/nfc/java/android/nfc/RoutingStatus.java @@ -0,0 +1,79 @@ +/* + * 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.nfc; + +import android.annotation.FlaggedApi; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.nfc.cardemulation.CardEmulation; + +/** + * A class indicating default route, ISO-DEP route and off-host route. + * + * @hide + */ +@SystemApi +@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) +public class RoutingStatus { + private final @CardEmulation.ProtocolAndTechnologyRoute int mDefaultRoute; + private final @CardEmulation.ProtocolAndTechnologyRoute int mDefaultIsoDepRoute; + private final @CardEmulation.ProtocolAndTechnologyRoute int mDefaultOffHostRoute; + + RoutingStatus(@CardEmulation.ProtocolAndTechnologyRoute int mDefaultRoute, + @CardEmulation.ProtocolAndTechnologyRoute int mDefaultIsoDepRoute, + @CardEmulation.ProtocolAndTechnologyRoute int mDefaultOffHostRoute) { + this.mDefaultRoute = mDefaultRoute; + this.mDefaultIsoDepRoute = mDefaultIsoDepRoute; + this.mDefaultOffHostRoute = mDefaultOffHostRoute; + } + + /** + * Getter of the default route. + * @return an integer defined in + * {@link android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute} + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + @CardEmulation.ProtocolAndTechnologyRoute + public int getDefaultRoute() { + return mDefaultRoute; + } + + /** + * Getter of the default ISO-DEP route. + * @return an integer defined in + * {@link android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute} + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + @CardEmulation.ProtocolAndTechnologyRoute + public int getDefaultIsoDepRoute() { + return mDefaultIsoDepRoute; + } + + /** + * Getter of the default off-host route. + * @return an integer defined in + * {@link android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute} + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + @CardEmulation.ProtocolAndTechnologyRoute + public int getDefaultOffHostRoute() { + return mDefaultOffHostRoute; + } + +} diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java index 4be082ccc02f..d8f04c50b695 100644 --- a/nfc/java/android/nfc/cardemulation/CardEmulation.java +++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java @@ -168,6 +168,12 @@ public final class CardEmulation { public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC = 2; /** + * Route to the default value in config file. + */ + @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE) + public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT = 3; + + /** * Route unset. */ @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE) @@ -895,45 +901,47 @@ public final class CardEmulation { PROTOCOL_AND_TECHNOLOGY_ROUTE_DH, PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE, PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC, - PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET + PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET, + PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT }) @Retention(RetentionPolicy.SOURCE) public @interface ProtocolAndTechnologyRoute {} - /** - * Setting NFC controller routing table, which includes Protocol Route and Technology Route, - * while this Activity is in the foreground. - * - * The parameter set to {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET} - * can be used to keep current values for that entry. Either - * Protocol Route or Technology Route should be override when calling this API, otherwise - * throw {@link IllegalArgumentException}. - * <p> - * Example usage in an Activity that requires to set proto route to "ESE" and keep tech route: - * <pre> - * protected void onResume() { - * mNfcAdapter.overrideRoutingTable( - * this, {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE}, null); - * }</pre> - * </p> - * Also activities must call {@link #recoverRoutingTable(Activity)} - * when it goes to the background. 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 RoleManager#ROLE_WALLET}), - * otherwise a call to this method will fail and throw {@link SecurityException}. - * @param activity The Activity that requests NFC controller routing table to be changed. - * @param protocol ISO-DEP route destination, where the possible inputs are defined - * in {@link ProtocolAndTechnologyRoute}. - * @param technology Tech-A, Tech-B and Tech-F route destination, where the possible inputs - * are defined in {@link ProtocolAndTechnologyRoute} - * @throws SecurityException if the caller is not the preferred NFC service - * @throws IllegalArgumentException if the activity is not resumed or the caller is not in the - * foreground. - * <p> - * This is a high risk API and only included to support mainline effort - * @hide - */ + /** + * Setting NFC controller routing table, which includes Protocol Route and Technology Route, + * while this Activity is in the foreground. + * + * The parameter set to {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET} + * can be used to keep current values for that entry. Either + * Protocol Route or Technology Route should be override when calling this API, otherwise + * throw {@link IllegalArgumentException}. + * <p> + * Example usage in an Activity that requires to set proto route to "ESE" and keep tech route: + * <pre> + * protected void onResume() { + * mNfcAdapter.overrideRoutingTable( + * this, {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE}, + * {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET}); + * }</pre> + * </p> + * Also activities must call {@link #recoverRoutingTable(Activity)} + * when it goes to the background. 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 RoleManager#ROLE_WALLET}), + * otherwise a call to this method will fail and throw {@link SecurityException}. + * @param activity The Activity that requests NFC controller routing table to be changed. + * @param protocol ISO-DEP route destination, where the possible inputs are defined + * in {@link ProtocolAndTechnologyRoute}. + * @param technology Tech-A, Tech-B and Tech-F route destination, where the possible inputs + * are defined in {@link ProtocolAndTechnologyRoute} + * @throws SecurityException if the caller is not the preferred NFC service + * @throws IllegalArgumentException if the activity is not resumed or the caller is not in the + * foreground. + * <p> + * This is a high risk API and only included to support mainline effort + * @hide + */ @SystemApi @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE) public void overrideRoutingTable( @@ -942,26 +950,14 @@ public final class CardEmulation { if (!activity.isResumed()) { throw new IllegalArgumentException("Activity must be resumed."); } - String protocolRoute = switch (protocol) { - case PROTOCOL_AND_TECHNOLOGY_ROUTE_DH -> "DH"; - case PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE -> "ESE"; - case PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC -> "UICC"; - case PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET -> null; - default -> throw new IllegalStateException("Unexpected value: " + protocol); - }; - String technologyRoute = switch (technology) { - case PROTOCOL_AND_TECHNOLOGY_ROUTE_DH -> "DH"; - case PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE -> "ESE"; - case PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC -> "UICC"; - case PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET -> null; - default -> throw new IllegalStateException("Unexpected value: " + protocol); - }; + String protocolRoute = routeIntToString(protocol); + String technologyRoute = routeIntToString(technology); callService(() -> sService.overrideRoutingTable( - mContext.getUser().getIdentifier(), - protocolRoute, - technologyRoute, - mContext.getPackageName())); + mContext.getUser().getIdentifier(), + protocolRoute, + technologyRoute, + mContext.getPackageName())); } /** @@ -1068,4 +1064,16 @@ public final class CardEmulation { } return defaultReturn; } + + /** @hide */ + public static String routeIntToString(@ProtocolAndTechnologyRoute int route) { + return switch (route) { + case PROTOCOL_AND_TECHNOLOGY_ROUTE_DH -> "DH"; + case PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE -> "eSE"; + case PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC -> "SIM"; + case PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET -> null; + case PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT -> "default"; + default -> throw new IllegalStateException("Unexpected value: " + route); + }; + } } diff --git a/nfc/java/android/nfc/flags.aconfig b/nfc/java/android/nfc/flags.aconfig index cc9a97cd52c9..6a7e6939e773 100644 --- a/nfc/java/android/nfc/flags.aconfig +++ b/nfc/java/android/nfc/flags.aconfig @@ -157,3 +157,11 @@ flag { description: "Enable EUICC card emulation" bug: "321314635" } + +flag { + name: "nfc_state_change_security_log_event_enabled" + is_exported: true + namespace: "nfc" + description: "Enabling security log for nfc state change" + bug: "319934052" +} diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml index 798e7d5b083f..6a241b776aef 100644 --- a/packages/CompanionDeviceManager/res/values-af/strings.xml +++ b/packages/CompanionDeviceManager/res/values-af/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Laat <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toe om <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> te bestuur?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"toestel"</string> <string name="summary_glasses" msgid="5469208629679579157">"Hierdie app sal toegang tot hierdie toestemmings op jou <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> hê"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toestemming om jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> se apps na <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong&gt te stroom?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> sal toegang hê tot enigiets wat sigbaar is of gespeel word op die <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, insluitend oudio, foto’s, wagwoorde en boodskappe.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> sal apps na <xliff:g id="DEVICE_NAME">%3$s</xliff:g> kan stroom totdat jy toegang tot hierdie toestemming verwyder."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek toestemming namens jou <xliff:g id="DEVICE_NAME">%2$s</xliff:g> om apps tussen jou toestelle te vertoon en te stroom"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang tot hierdie inligting op jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek tans namens jou <xliff:g id="DEVICE_NAME">%2$s</xliff:g> toegang tot jou <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> se foto’s, media en kennisgewings"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Gee <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> toestemming om jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> se apps en stelselkenmerke na <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> te stroom?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> sal toegang hê tot enigiets wat sigbaar is of gespeel word op jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, insluitend oudio, foto’s, betaalinligting, wagwoorde en boodskappe.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> sal apps en stelselkenmerke na <xliff:g id="DEVICE_NAME">%3$s</xliff:g> kan stroom totdat jy toegang tot hierdie toestemming verwyder."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek tans namens jou <xliff:g id="DEVICE_NAME">%2$s</xliff:g> toestemming om apps en ander stelselkenmerke tussen jou toestelle te stroom"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"toestel"</string> <string name="summary_generic" msgid="1761976003668044801">"Hierdie app sal inligting kan sinkroniseer, soos die naam van iemand wat bel, tussen jou foon en die gekose toestel"</string> <string name="consent_yes" msgid="8344487259618762872">"Laat toe"</string> diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml index 59e1f03a3716..a9f5ed261a72 100644 --- a/packages/CompanionDeviceManager/res/values-am/strings.xml +++ b/packages/CompanionDeviceManager/res/values-am/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ን እንዲያስተዳድር ይፈቅዳሉ?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"መሣሪያ"</string> <string name="summary_glasses" msgid="5469208629679579157">"ይህ መተግበሪያ በእርስዎ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> ላይ እነዚህን ፈቃዶች እንዲደርስ ይፈቀድለታል"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> የእርስዎን <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> መተግበሪያዎች ወደ <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>? በዥረት እንዲለቅ ይፍቀዱ"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ኦዲዮ፣ ፎቶዎች፣ የይለፍ ቃላት እና መልዕክቶችን ጨምሮ በ<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ላይ የሚታየውን ወይም የሚጫወተውን ማንኛውንም ነገር መዳረሻ ይኖረዋል።<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> የዚህን መዳረሻ እስኪያስወግዱ ድረስ መተግበሪያዎችን ወደ <xliff:g id="DEVICE_NAME">%3$s</xliff:g> በዥረት መልቀቅ ይችላል።"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> የእርስዎን <xliff:g id="DEVICE_NAME">%2$s</xliff:g> በመወከል በመሣሪያዎችዎ መካከል ለማሳየት እና መተግበሪያዎችን በዥረት ለመልቀቅ ፈቃድ እየጠየቀ ነው"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ይህን መረጃ ከእርስዎ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> እንዲደርስ ይፍቀዱ"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> የእርስዎን <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> ፎቶዎች፣ ሚዲያ እና ማሳወቂያዎች ለመድረስ የእርስዎን <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ወክሎ ፈቃድ እየጠየቀ ነው"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> የእርስዎን <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> መተግበሪያዎች እና የሥርዓት ባህሪያት ወደ <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>? በዥረት እንዲለቅ ይፍቀዱ"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ኦዲዮ፣ ፎቶዎች፣ የክፍያ መረጃ፣ የይለፍ ቃላት እና መልዕክቶችን ጨምሮ በእርስዎ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ላይ የሚታየውን ወይም የሚጫወተውን የማንኛውም ነገር መዳረሻ ይኖረዋል።<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> የዚህን መዳረሻ እስኪያስወግዱ ድረስ መተግበሪያዎችን እና የሥርዓት ባህሪያትን ወደ <xliff:g id="DEVICE_NAME">%3$s</xliff:g> በዥረት መልቀቅ ይችላል።"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> የእርስዎን <xliff:g id="DEVICE_NAME">%2$s</xliff:g> በመወከል በመሣሪያዎችዎ መካከል መተግበሪያዎችን እና ሌሎች የሥርዓት ባህሪያትን በዥረት ለመልቀቅ ፈቃድ እየጠየቀ ነው"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"መሣሪያ"</string> <string name="summary_generic" msgid="1761976003668044801">"ይህ መተግበሪያ እንደ የሚደውል ሰው ስም ያለ መረጃን በስልክዎ እና በተመረጠው መሣሪያ መካከል ማስመር ይችላል"</string> <string name="consent_yes" msgid="8344487259618762872">"ፍቀድ"</string> diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml index 89c7efb3ae7d..ce68ee1ef366 100644 --- a/packages/CompanionDeviceManager/res/values-ar/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"هل تريد السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بإدارة <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>؟"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"جهاز"</string> <string name="summary_glasses" msgid="5469208629679579157">"سيتم السماح لهذا التطبيق باستخدام هذه الأذونات على <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"هل تريد السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ببث التطبيقات من <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> إلى <xliff:g id="DEVICE_NAME">%3$s</xliff:g>؟"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"سيتمكّن \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" من الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله على <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>، بما في ذلك الملفات الصوتية والصور وكلمات المرور والرسائل.<br/><br/>سيتمكّن \"<xliff:g id="APP_NAME_1">%1$s</xliff:g>\" من بث التطبيقات إلى <xliff:g id="DEVICE_NAME">%3$s</xliff:g> إلى أن توقف إمكانية استخدام هذا الإذن."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"يطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن <xliff:g id="DEVICE_NAME">%2$s</xliff:g> لعرض التطبيقات وبثها بين أجهزتك"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"هل تريد السماح لتطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بالوصول إلى هذه المعلومات من <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>؟"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"يطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن <xliff:g id="DEVICE_NAME">%2$s</xliff:g> للوصول إلى الصور والوسائط والإشعارات في <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"هل تريد السماح لجهاز <xliff:g id="DEVICE_NAME_0">%1$s</xliff:g> ببث التطبيقات وميزات النظام من <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> إلى <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>؟"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"سيتمكّن \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" من الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله على <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>، بما في ذلك الملفات الصوتية والصور ومعلومات الدفع وكلمات المرور والرسائل.<br/><br/>سيتمكّن \"<xliff:g id="APP_NAME_1">%1$s</xliff:g>\" من بث التطبيقات وميزات النظام إلى <xliff:g id="DEVICE_NAME">%3$s</xliff:g> إلى أن توقف إمكانية استخدام هذا الإذن."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"يطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن <xliff:g id="DEVICE_NAME">%2$s</xliff:g> لبثّ التطبيقات وميزات النظام الأخرى بين أجهزتك"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"جهاز"</string> <string name="summary_generic" msgid="1761976003668044801">"سيتمكّن هذا التطبيق من مزامنة المعلومات، مثل اسم المتصل، بين هاتفك والجهاز المحدّد."</string> <string name="consent_yes" msgid="8344487259618762872">"السماح"</string> diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml index 3d252ca615ed..7376cd066d00 100644 --- a/packages/CompanionDeviceManager/res/values-as/strings.xml +++ b/packages/CompanionDeviceManager/res/values-as/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> পৰিচালনা কৰিবলৈ দিবনে?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"ডিভাইচ"</string> <string name="summary_glasses" msgid="5469208629679579157">"এই এপ্টোক আপোনাৰ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>ত এই অনুমতিসমূহ এক্সেছ কৰিবলৈ অনুমতি দিয়া হ’ব"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ এপ্সমূহ <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>ত ষ্ট্ৰীম কৰিবলৈ দিবনে?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>এ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ত দৃশ্যমান হোৱা বা প্লে’ কৰা অডিঅ’, ফট’ পাছৱৰ্ড আৰু বাৰ্তাকে ধৰি যিকোনো বস্তু এক্সেছ কৰিব পাৰিব।<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g>এ আপুনি এই অনুমতিৰ এক্সেছ আঁতৰাই নিদিয়া পৰ্যন্ত <xliff:g id="DEVICE_NAME">%3$s</xliff:g>ত এপ্সমূহ ষ্ট্ৰীম কৰিব পাৰিব।"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_NAME">%2$s</xliff:g>ৰ হৈ আপোনাৰ ডিভাইচসমূহৰ মাজত এপ্সমূহ দেখুৱাবলৈ আৰু ষ্ট্ৰীম কৰিবলৈ অনুমতি বিচাৰি অনুৰোধ জনাইছে"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ পৰা এই তথ্যখিনি এক্সেছ কৰিবলৈ দিয়ক"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_NAME">%2$s</xliff:g>ৰ হৈ আপোনাৰ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>ৰ ফট’, মিডিয়া আৰু জাননী এক্সেছ কৰাৰ বাবে অনুমতি বিচাৰি অনুৰোধ জনাইছে"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong>ক আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ এপ্সমূহ আৰু ছিষ্টেমৰ সুবিধাসমূহ <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>ত ষ্ট্ৰীম কৰিবলৈ দিবনে?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ত দৃশ্যমান বা প্লে’ কৰা অডিঅ’, ফট’ পৰিশোধৰ তথ্য, পাছৱৰ্ড আৰু বাৰ্তাকে ধৰি যিকোনো বস্তু এক্সেছ কৰিব পাৰিব।<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g>এ আপুনি এই অনুমতিৰ এক্সেছ আঁতৰাই নিদিয়া পৰ্যন্ত <xliff:g id="DEVICE_NAME">%3$s</xliff:g>ত এপ্সমূহ আৰু ছিষ্টেমৰ সুবিধাসমূহ ষ্ট্ৰীম কৰিব পাৰিব।"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_NAME">%2$s</xliff:g>ৰ হৈ আপোনাৰ ডিভাইচসমূহৰ মাজত এপ্সমূহ আৰু আন ছিষ্টেমৰ সুবিধাসমূহ ষ্ট্ৰীম কৰিবলৈ অনুমতি বিচাৰি অনুৰোধ জনাইছে"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইচ"</string> <string name="summary_generic" msgid="1761976003668044801">"এই এপ্টোৱে আপোনাৰ ফ’ন আৰু বাছনি কৰা ডিভাইচটোৰ মাজত কল কৰোঁতাৰ নামৰ দৰে তথ্য ছিংক কৰিব পাৰিব"</string> <string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিয়ক"</string> diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml index 2a636a95bf01..dd720935fdb9 100644 --- a/packages/CompanionDeviceManager/res/values-az/strings.xml +++ b/packages/CompanionDeviceManager/res/values-az/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> cihazını idarə etmək icazəsi verilsin?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"cihazda"</string> <string name="summary_glasses" msgid="5469208629679579157">"Bu tətbiq <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> cihazında bu icazələrə daxil ola biləcək"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> üçün <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> tətbiqlərini <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> cihazına sinxronlaşdırmaq icazəsi verilsin?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> audio, foto, parol və mesajlar daxil olmaqla <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazında görünən və ya oxudulan kontentə giriş əldə edəcək.<br/><br/>Siz bu icazəyə girişi silənə qədər <xliff:g id="APP_NAME_1">%1$s</xliff:g>tətbiqləri <xliff:g id="DEVICE_NAME">%3$s</xliff:g> cihazına yayımlaya biləcək."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqləri göstərmək və cihazlar arasında yayımlamaq üçün <xliff:g id="DEVICE_NAME">%2$s</xliff:g> adından icazə tələb edir"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazından əldə edilən bu məlumata giriş icazəsi verin"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> üzrə foto, media və bildirişlərə daxil olmaq üçün <xliff:g id="DEVICE_NAME">%2$s</xliff:g> adından icazə tələb edir"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> üçün <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> tətbiq və sistem funksiyalarını <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> cihazına yayımlamaq icazəsi verilsin?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> audio, foto, ödəniş məlumatı, parol və mesajlar daxil olmaqla <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazında görünən və ya işə salınan kontentə giriş əldə edəcək.<br/><br/>Siz bu icazəyə girişi silənə qədər <xliff:g id="APP_NAME_1">%1$s</xliff:g> tətbiq və sistem funksiyalarını <xliff:g id="DEVICE_NAME">%3$s</xliff:g> cihazına yayımlaya biləcək."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> cihazlar arasında tətbiqləri və digər sistem funksiyalarını yayımlamaq üçün <xliff:g id="DEVICE_NAME">%2$s</xliff:g> adından icazə tələb edir"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string> <string name="summary_generic" msgid="1761976003668044801">"Tətbiq zəng edənin adı kimi məlumatları telefon ilə seçilmiş cihaz arasında sinxronlaşdıracaq"</string> <string name="consent_yes" msgid="8344487259618762872">"İcazə verin"</string> diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml index 010b59ae6b71..2200cecd0256 100644 --- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml +++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Želite li da dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> upravlja uređajem <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"uređaj"</string> <string name="summary_glasses" msgid="5469208629679579157">"Ovoj aplikaciji će biti dozvoljeno da pristupa ovim dozvolama na uređaju <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Želite li da dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> strimuje aplikacije uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> će imati pristup svemu što se vidi ili pušta na uređaju <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, uključujući zvuk, slike, lozinke i poruke.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> će moći da strimuje aplikacije na <xliff:g id="DEVICE_NAME">%3$s</xliff:g> dok ne uklonite pristup ovoj dozvoli."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> traži dozvolu u ime uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> da prikazuje i strimuje aplikacije između uređaja"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa ovim informacijama sa uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> traži dozvolu u ime uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> da pristupa slikama, medijskom sadržaju i obaveštenjima sa uređaja <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Želite li da dozvolite da <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> strimuje aplikacije i sistemske funkcije uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> će imati pristup svemu što se vidi ili pušta na uređaju <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, uključujući zvuk, slike, informacije o plaćanju, lozinke i poruke.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> će moći da strimuje aplikacije i sistemske funkcije na <xliff:g id="DEVICE_NAME">%3$s</xliff:g> dok ne uklonite pristup ovoj dozvoli."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> traži dozvolu u ime uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> da strimuje aplikacije i druge sistemske funkcije između uređaja"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string> <string name="summary_generic" msgid="1761976003668044801">"Ova aplikacija će moći da sinhronizuje podatke, poput imena osobe koja upućuje poziv, između telefona i odabranog uređaja"</string> <string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string> diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml index 5cc26a7f7bb4..7eca403fd5f0 100644 --- a/packages/CompanionDeviceManager/res/values-be/strings.xml +++ b/packages/CompanionDeviceManager/res/values-be/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Дазволіць праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> кіраваць прыладай <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"прылада"</string> <string name="summary_glasses" msgid="5469208629679579157">"Гэта праграма будзе мець на вашай прыладзе тыпу \"<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>\" наступныя дазволы"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Дазволіць праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> трансліраваць праграмы прылады тыпу \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на прыладу <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"Праграма \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" будзе мець доступ да ўсяго, што паказваецца ці прайграецца на прыладзе тыпу \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\", у тым ліку да аўдыя, фота, пароляў і паведамленняў.<br/><br/>Праграма \"<xliff:g id="APP_NAME_1">%1$s</xliff:g>\" зможа трансліраваць праграмы на прыладу \"<xliff:g id="DEVICE_NAME">%3$s</xliff:g>\", пакуль вы не адклічаце гэты дазвол."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" на паказ і трансляцыю праграм паміж прыладамі"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> мець доступ да гэтай інфармацыі з прылады тыпу \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\""</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" на доступ да фота, медыяфайлаў і апавяшчэнняў на прыладзе тыпу \"<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>\""</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Дазволіць прыладзе <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> трансліраваць праграмы і сістэмныя функцыі прылады тыпу \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на прыладу <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"Праграма \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" будзе мець доступ да ўсяго, што паказваецца ці прайграецца на прыладзе тыпу \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\", у тым ліку да аўдыя, фота, пароляў і паведамленняў.<br/><br/>Праграма \"<xliff:g id="APP_NAME_1">%1$s</xliff:g>\" зможа трансліраваць праграмы і сістэмныя функцыі на прыладу \"<xliff:g id="DEVICE_NAME">%3$s</xliff:g>\", пакуль вы не адклічаце гэты дазвол."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" на трансляцыю праграм і іншых сістэмных функцый паміж прыладамі"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"прылада"</string> <string name="summary_generic" msgid="1761976003668044801">"Гэта праграма зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць) паміж тэлефонам і выбранай прыладай"</string> <string name="consent_yes" msgid="8344487259618762872">"Дазволіць"</string> diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml index 747a071699fb..3ebf375cdbee 100644 --- a/packages/CompanionDeviceManager/res/values-bg/strings.xml +++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Разрешавате ли на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да управлява устройството <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"устройство"</string> <string name="summary_glasses" msgid="5469208629679579157">"Това приложение ще има достъп до следните разрешения за вашите <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Да се разреши ли на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да предава поточно към <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> приложенията на устройството ви от тип <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ще има достъп до всичко, което се показва или възпроизвежда на устройството ви от тип <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, включително аудио, снимки, пароли и съобщения.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> ще може да предава поточно приложения към устройството ви <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, докато не премахнете това разрешение."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на ваше устройство (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) да показва и да предава поточно приложения между устройствата ви"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да осъществява достъп до тази информация от вашия <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на ваше устройство (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) за достъп до снимките, мултимедията и известията на вашия <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Да се разреши ли на <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> да предава поточно към <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> приложенията и системните функции на устройството ви от тип <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ще има достъп до всичко, което се показва или възпроизвежда на устройството ви от тип <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, включително аудио, снимки, данни за плащане, пароли и съобщения.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> ще може да предава поточно приложения и системни функции към устройството ви <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, докато не премахнете това разрешение."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на ваше устройство (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) да предава поточно приложения и други системни функции между устройствата ви"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string> <string name="summary_generic" msgid="1761976003668044801">"Това приложение ще може да синхронизира различна информация, като например името на обаждащия се, между телефона ви и избраното устройство"</string> <string name="consent_yes" msgid="8344487259618762872">"Разрешаване"</string> diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml index ef9fddda2e05..d2a0353c9c9b 100644 --- a/packages/CompanionDeviceManager/res/values-bn/strings.xml +++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"আপনি কি <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ম্যানেজ করার জন্য <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-কে অনুমতি দেবেন?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"ডিভাইস"</string> <string name="summary_glasses" msgid="5469208629679579157">"<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>-এ এইসব অনুমতি অ্যাক্সেস করার জন্য এই অ্যাপকে অনুমতি দেওয়া হবে"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"আপনার <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর অ্যাপ <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?-এ স্ট্রিম করার জন্য <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-কে অনুমতি দেবেন?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"অডিও, ফটো, পাসওয়ার্ড ও মেসেজ সহ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এ দেখা ও চালানো যায় এমন সব কিছু <xliff:g id="APP_NAME_0">%1$s</xliff:g> অ্যাক্সেস করতে পারবে।<br/><br/>আপনি এই অনুমতি না সরানো পর্যন্ত <xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%3$s</xliff:g>-এ অ্যাপ স্ট্রিম করতে পারবে।"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"আপনার বিভিন্ন ডিভাইসের মধ্যে অ্যাপ, ডিসপ্লে এবং স্ট্রিম করার জন্য আপনার <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-এর হয়ে <xliff:g id="APP_NAME">%1$s</xliff:g> অনুমতি চাইছে"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"আপনার <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> থেকে এই তথ্য অ্যাক্সেস করার জন্য <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-কে অনুমতি দিন"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"আপনার <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>-এর ফটো, মিডিয়া ও বিজ্ঞপ্তি অ্যাক্সেস করার জন্য, আপনার <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-এর হয়ে <xliff:g id="APP_NAME">%1$s</xliff:g> অনুমতি চাইছে"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"আপনার <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর অ্যাপ ও সিস্টেমের ফিচার <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?-এ স্ট্রিম করার জন্য <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong>-কে অনুমতি দেবেন?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"অডিও, ফটো, পেমেন্টের তথ্য, পাসওয়ার্ড ও মেসেজ সহ আপনার <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এ দেখা ও চালানো যায় এমন সব কিছু <xliff:g id="APP_NAME_0">%1$s</xliff:g> অ্যাক্সেস করতে পারবে।<br/><br/>আপনি এই অনুমতি না সরানো পর্যন্ত <xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%3$s</xliff:g>-এ অ্যাপ ও সিস্টেমের ফিচার স্ট্রিম করতে পারবে।"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"আপনার বিভিন্ন ডিভাইসের মধ্যে অ্যাপ ও সিস্টেমের অন্যান্য ফিচার স্ট্রিম করার জন্য, আপনার <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-এর হয়ে <xliff:g id="APP_NAME">%1$s</xliff:g> অনুমতি চাইছে"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইস"</string> <string name="summary_generic" msgid="1761976003668044801">"এই অ্যাপ, আপনার ফোন এবং বেছে নেওয়া ডিভাইসের মধ্যে তথ্য সিঙ্ক করতে পারবে, যেমন কোনও কলারের নাম"</string> <string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিন"</string> diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml index 69ae96f8547a..84316f299808 100644 --- a/packages/CompanionDeviceManager/res/values-bs/strings.xml +++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Dozvoliti aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da upravlja uređajem <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"uređaj"</string> <string name="summary_glasses" msgid="5469208629679579157">"Aplikaciji će biti dozvoljen pristup ovim odobrenjima koje sadržava vaš <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Dozvoliti aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da prenosi aplikacije koje sadržava vaš <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na uređaju <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> će imati pristup svemu što <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> reproducira ili je vidljivo na njemu, uključujući zvukove, fotografije, lozinke i poruke.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> će moći prenositi aplikacije na uređaju <xliff:g id="DEVICE_NAME">%3$s</xliff:g> dok ne uklonite pristup ovom odobrenju."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> traži odobrenje u ime vašeg uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> da prikazuje i prenosi aplikacije između vaših uređaja"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Dozvolite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da pristupa ovim informacijama koje sadržava vaš <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> traži odobrenje u ime vašeg uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> da pristupa fotografijama, medijima i obavještenjima koje sadržava vaš <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Dozvoliti uređaju <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> da prenosi aplikacije i funkcije sistema koje sadržava vaš <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na uređaju <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> će imati pristup svemu što <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> reproducira ili je vidljivo na njemu, uključujući zvukove, fotografije, podatke o plaćanju, lozinke i poruke.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> će moći prenositi aplikacije i funkcije sistema na uređaju <xliff:g id="DEVICE_NAME">%3$s</xliff:g> dok ne uklonite pristup ovom odobrenju."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> traži odobrenje u ime vašeg uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> da prenosi aplikacije i druge funkcije sistema između vaših uređaja"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string> <string name="summary_generic" msgid="1761976003668044801">"Ova aplikacija će moći sinhronizirati informacije, kao što je ime osobe koja upućuje poziv, između vašeg telefona i odabranog uređaja"</string> <string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string> diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml index f8c408437572..8b115f74b3b5 100644 --- a/packages/CompanionDeviceManager/res/values-ca/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml @@ -25,19 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gestioni <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"dispositiu"</string> <string name="summary_glasses" msgid="5469208629679579157">"Aquesta aplicació podrà accedir a aquests permisos del <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Vols permetre que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> reprodueixi en continu les aplicacions del <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> a <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g><strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> podrà accedir a qualsevol cosa que sigui visible o que es reprodueixi al <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, inclosos àudios, fotos, contrasenyes i missatges.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> podrà reproduir en continu aplicacions a <xliff:g id="DEVICE_NAME">%3$s</xliff:g> fins que suprimeixis l\'accés a aquest permís."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu dispositiu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> per mostrar i reproduir en continu aplicacions entre els dispositius"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> accedeixi a aquesta informació del <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu dispositiu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> per accedir a les fotos, el contingut multimèdia i les notificacions del <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Vols permetre que <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> reprodueixi en continu les aplicacions i les funcions del sistema del <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> a <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>?"</string> - <!-- String.format failed for translation --> - <!-- no translation found for summary_nearby_device_streaming (962267343109051648) --> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> <skip /> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu dispositiu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> per reproduir en continu aplicacions i altres funcions del sistema entre els dispositius"</string> <string name="profile_name_generic" msgid="6851028682723034988">"dispositiu"</string> <string name="summary_generic" msgid="1761976003668044801">"Aquesta aplicació podrà sincronitzar informació, com ara el nom d\'algú que truca, entre el teu telèfon i el dispositiu triat"</string> <string name="consent_yes" msgid="8344487259618762872">"Permet"</string> diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml index 04e73800570b..7bd6e38a919b 100644 --- a/packages/CompanionDeviceManager/res/values-cs/strings.xml +++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Povolit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> spravovat zařízení <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"zařízení"</string> <string name="summary_glasses" msgid="5469208629679579157">"Tato aplikace bude mít na zařízení typu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> přístup k následujícím oprávněním"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Povolit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> streamovat aplikace na zařízení typu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> do zařízení <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"Aplikace <xliff:g id="APP_NAME_0">%1$s</xliff:g> bude mít přístup ke všemu, co na zařízení typu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> zobrazíte nebo přehrajete, včetně zvuku, fotek, hesel a zpráv.<br/><br/>Aplikace <xliff:g id="APP_NAME_1">%1$s</xliff:g> bude moct streamovat aplikace do zařízení typu <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, dokud přístup k tomuto oprávnění neodeberete."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DEVICE_NAME">%2$s</xliff:g> oprávnění k zobrazení a streamování obsahu mezi zařízeními"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Povolte aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> přístup k těmto informacím z vašeho zařízení typu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DEVICE_NAME">%2$s</xliff:g> oprávnění k přístupu k fotkám, médiím a oznámením na zařízení typu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Povolit aplikaci <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> streamovat aplikace a systémové funkce ze zařízení typu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> do zařízení <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"Aplikace <xliff:g id="APP_NAME_0">%1$s</xliff:g> bude mít přístup ke všemu, co na zařízení typu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> zobrazíte nebo přehrajete, včetně zvuku, fotek, platebních údajů, hesel a zpráv.<br/><br/>Aplikace <xliff:g id="APP_NAME_1">%1$s</xliff:g> bude moct streamovat aplikace a systémové funkce do zařízení typu <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, dokud přístup k tomuto oprávnění neodeberete."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DEVICE_NAME">%2$s</xliff:g> oprávnění ke streamování aplikací a dalších systémových funkcí mezi zařízeními"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"zařízení"</string> <string name="summary_generic" msgid="1761976003668044801">"Tato aplikace bude moci synchronizovat údaje, jako je jméno volajícího, mezi vaším telefonem a vybraným zařízením"</string> <string name="consent_yes" msgid="8344487259618762872">"Povolit"</string> diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml index d948804ae36a..4180ef5baa7d 100644 --- a/packages/CompanionDeviceManager/res/values-da/strings.xml +++ b/packages/CompanionDeviceManager/res/values-da/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Vil du tillade, at <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> administrerer <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"enhed"</string> <string name="summary_glasses" msgid="5469208629679579157">"Denne app får adgang til disse tilladelser på din <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Vil du give <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilladelse til at streame apps fra din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får adgang til alt, der er synligt eller afspilles på din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, herunder lyd, billeder, adgangskoder og beskeder.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> kan streame apps til <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, indtil du fjerner adgangen til denne tilladelse."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_NAME">%2$s</xliff:g> til at vise og streame apps mellem dine enheder"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Giv <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> adgang til disse oplysninger fra din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_NAME">%2$s</xliff:g> til at få adgang til billeder, medier og notifikationer på din <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Vil du give <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> tilladelse til at streame apps og systemfunktioner fra din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får adgang til alt, der er synligt eller afspilles på din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, herunder lyd, billeder, betalingsoplysninger, adgangskoder og beskeder.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> kan streame apps og systemfunktioner til <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, indtil du fjerner adgangen til denne tilladelse."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_NAME">%2$s</xliff:g> til at streame apps og andre systemfunktioner mellem dine enheder"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"enhed"</string> <string name="summary_generic" msgid="1761976003668044801">"Denne app vil kunne synkronisere oplysninger som f.eks. navnet på en person, der ringer, mellem din telefon og den valgte enhed"</string> <string name="consent_yes" msgid="8344487259618762872">"Tillad"</string> diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml index 8d65f68475fc..725a42d92b59 100644 --- a/packages/CompanionDeviceManager/res/values-de/strings.xml +++ b/packages/CompanionDeviceManager/res/values-de/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Zulassen, dass <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> das Gerät <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> verwalten darf?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"Gerät"</string> <string name="summary_glasses" msgid="5469208629679579157">"Diese App darf dann auf diese Berechtigungen auf deinem Gerät (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>) zugreifen:"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> erlauben, die Apps auf deinem Gerät (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) auf <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> zu streamen?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> hat dann Zugriff auf alle Inhalte, die auf deinem Gerät (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) sichtbar sind oder abgespielt werden, einschließlich Audioinhalten, Fotos, Zahlungsinformationen, Passwörter und Nachrichten.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> kann so lange Apps auf „<xliff:g id="DEVICE_NAME">%3$s</xliff:g>“ streamen, bis du diese Berechtigung entfernst."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet im Namen von „<xliff:g id="DEVICE_NAME">%2$s</xliff:g>“ um die Berechtigung, Apps zwischen deinen Geräten anzuzeigen und zu streamen"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> Zugriff auf diese Informationen von deinem Gerät (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) gewähren"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet im Namen von „<xliff:g id="DEVICE_NAME">%2$s</xliff:g>“ um die Berechtigung, auf die Fotos, Medien und Benachrichtigungen auf deinem Gerät (<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>) zuzugreifen"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> erlauben, die Apps und Systemfunktionen auf deinem Gerät (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) auf <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> zu streamen?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> hat dann Zugriff auf alle Inhalte, die auf deinem Gerät (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) sichtbar sind oder abgespielt werden, einschließlich Audioinhalten, Fotos, Zahlungsinformationen, Passwörter und Nachrichten.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> kann so lange Apps und Systemfunktionen auf „<xliff:g id="DEVICE_NAME">%3$s</xliff:g>“ streamen, bis du diese Berechtigung entfernst."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet im Namen von „<xliff:g id="DEVICE_NAME">%2$s</xliff:g>“ um die Berechtigung, Apps und andere Systemfunktionen zwischen deinen Geräten zu streamen"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"Gerät"</string> <string name="summary_generic" msgid="1761976003668044801">"Diese App kann dann Daten wie den Namen eines Anrufers zwischen deinem Smartphone und dem ausgewählten Gerät synchronisieren"</string> <string name="consent_yes" msgid="8344487259618762872">"Zulassen"</string> diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml index 4a186d52dc03..57aebc3a90aa 100644 --- a/packages/CompanionDeviceManager/res/values-el/strings.xml +++ b/packages/CompanionDeviceManager/res/values-el/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Να επιτρέπεται στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> να διαχειρίζεται τη συσκευή <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ;"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"συσκευή"</string> <string name="summary_glasses" msgid="5469208629679579157">"Αυτή η εφαρμογή θα μπορεί να έχει πρόσβαση σε αυτές τις άδειες στη συσκευή <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Να επιτρέπεται στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> να κάνει ροή των εφαρμογών της συσκευής <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> στη συσκευή <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>;"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"Η εφαρμογή <xliff:g id="APP_NAME_0">%1$s</xliff:g> θα έχει πρόσβαση σε οτιδήποτε είναι ορατό ή αναπαράγεται στη συσκευή <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, συμπεριλαμβανομένων ήχων, φωτογραφιών, κωδικών πρόσβασης και μηνυμάτων.<br/><br/>Η εφαρμογή <xliff:g id="APP_NAME_1">%1$s</xliff:g> θα μπορεί να κάνει ροή εφαρμογών στη συσκευή <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, μέχρι να καταργήσετε την πρόσβαση σε αυτή την άδεια."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά άδεια εκ μέρους της συσκευής <xliff:g id="DEVICE_NAME">%2$s</xliff:g> για προβολή και ροή εφαρμογών μεταξύ των συσκευών σας"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Να επιτρέπεται στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> η πρόσβαση σε αυτές τις πληροφορίες από τη συσκευή σας <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>."</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά άδεια εκ μέρους της συσκευής σας <xliff:g id="DEVICE_NAME">%2$s</xliff:g>, για πρόσβαση στις φωτογραφίες, τα αρχεία μέσων και τις ειδοποιήσεις της συσκευής <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Να επιτρέπεται στη συσκευή <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> να κάνει ροή των εφαρμογών και των λειτουργιών συστήματος της συσκευής <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> στη συσκευή <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>;"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"Η εφαρμογή <xliff:g id="APP_NAME_0">%1$s</xliff:g> θα έχει πρόσβαση σε οτιδήποτε είναι ορατό ή αναπαράγεται στη συσκευή <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, συμπεριλαμβανομένων ήχων, φωτογραφιών, στοιχείων πληρωμής, κωδικών πρόσβασης και μηνυμάτων.<br/><br/>Η εφαρμογή <xliff:g id="APP_NAME_1">%1$s</xliff:g> θα μπορεί να κάνει ροή εφαρμογών και λειτουργιών συστήματος στη συσκευή <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, μέχρι να καταργήσετε την πρόσβαση σε αυτή την άδεια."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά άδεια εκ μέρους της συσκευής σας <xliff:g id="DEVICE_NAME">%2$s</xliff:g> για ροή εφαρμογών και άλλων λειτουργιών συστήματος μεταξύ των συσκευών σας"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"συσκευή"</string> <string name="summary_generic" msgid="1761976003668044801">"Αυτή η εφαρμογή θα μπορεί να συγχρονίζει πληροφορίες μεταξύ του τηλεφώνου και της επιλεγμένης συσκευής σας, όπως το όνομα ενός ατόμου που σας καλεί."</string> <string name="consent_yes" msgid="8344487259618762872">"Να επιτρέπεται"</string> diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml index 346758a9518f..0a8542819ed5 100644 --- a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml +++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"device"</string> <string name="summary_glasses" msgid="5469208629679579157">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\'s apps to <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that\'s visible or played on the <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including audio, photos, passwords and messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME">%3$s</xliff:g> until you remove access to this permission."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to display and stream apps between your devices"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to access your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>\'s photos, media and notifications"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Allow <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\'s apps and system features to <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that\'s visible or played on your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including audio, photos, payment info, passwords and messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> will be able to stream apps and system features to <xliff:g id="DEVICE_NAME">%3$s</xliff:g> until you remove access to this permission."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps and other system features between your devices"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"device"</string> <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string> <string name="consent_yes" msgid="8344487259618762872">"Allow"</string> diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml index 5716476d5fa3..c40018ffe862 100644 --- a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml +++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml @@ -25,17 +25,17 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"device"</string> <string name="summary_glasses" msgid="5469208629679579157">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>’s apps to <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that’s visible or played on the <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including audio, photos, passwords, and messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME">%3$s</xliff:g> until you remove access to this permission."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to display and stream apps between your devices"</string> + <string name="title_app_streaming" msgid="1047090167914857893">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>’s apps and system features to <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> + <string name="summary_app_streaming" msgid="7990244299655610920">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that’s visible or played on your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including audio, photos, payment info, passwords, and messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME">%3$s</xliff:g> until you remove access to this permission."</string> + <string name="helper_summary_app_streaming" msgid="1872657107404139828">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps and system features from your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to access your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>’s photos, media, and notifications"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Allow <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>’s apps and system features to <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that’s visible or played on your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including audio, photos, payment info, passwords, and messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> will be able to stream apps and system features to <xliff:g id="DEVICE_NAME">%3$s</xliff:g> until you remove access to this permission."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps and other system features between your devices"</string> + <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>’s apps to <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> + <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that’s visible or played on <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, including audio, photos, payment info, passwords, and messages.<br/><br/><xliff:g id="APP_NAME_2">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> until you remove access to this permission."</string> + <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps from your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> <string name="profile_name_generic" msgid="6851028682723034988">"device"</string> <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string> <string name="consent_yes" msgid="8344487259618762872">"Allow"</string> diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml index 346758a9518f..0a8542819ed5 100644 --- a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml +++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"device"</string> <string name="summary_glasses" msgid="5469208629679579157">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\'s apps to <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that\'s visible or played on the <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including audio, photos, passwords and messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME">%3$s</xliff:g> until you remove access to this permission."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to display and stream apps between your devices"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to access your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>\'s photos, media and notifications"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Allow <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\'s apps and system features to <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that\'s visible or played on your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including audio, photos, payment info, passwords and messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> will be able to stream apps and system features to <xliff:g id="DEVICE_NAME">%3$s</xliff:g> until you remove access to this permission."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps and other system features between your devices"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"device"</string> <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string> <string name="consent_yes" msgid="8344487259618762872">"Allow"</string> diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml index 346758a9518f..0a8542819ed5 100644 --- a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml +++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"device"</string> <string name="summary_glasses" msgid="5469208629679579157">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\'s apps to <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that\'s visible or played on the <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including audio, photos, passwords and messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME">%3$s</xliff:g> until you remove access to this permission."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to display and stream apps between your devices"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to access your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>\'s photos, media and notifications"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Allow <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\'s apps and system features to <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that\'s visible or played on your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including audio, photos, payment info, passwords and messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> will be able to stream apps and system features to <xliff:g id="DEVICE_NAME">%3$s</xliff:g> until you remove access to this permission."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps and other system features between your devices"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"device"</string> <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string> <string name="consent_yes" msgid="8344487259618762872">"Allow"</string> diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml index 6c6a000e19ff..80b02cbd490a 100644 --- a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml +++ b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml @@ -25,17 +25,17 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"device"</string> <string name="summary_glasses" msgid="5469208629679579157">"This app will be allowed to access these permissions on your <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>’s apps to <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that’s visible or played on the <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including audio, photos, passwords, and messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME">%3$s</xliff:g> until you remove access to this permission."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to display and stream apps between your devices"</string> + <string name="title_app_streaming" msgid="1047090167914857893">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>’s apps and system features to <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> + <string name="summary_app_streaming" msgid="7990244299655610920">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that’s visible or played on your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including audio, photos, payment info, passwords, and messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME">%3$s</xliff:g> until you remove access to this permission."</string> + <string name="helper_summary_app_streaming" msgid="1872657107404139828">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps and system features from your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to access your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>’s photos, media, and notifications"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Allow <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>’s apps and system features to <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that’s visible or played on your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including audio, photos, payment info, passwords, and messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> will be able to stream apps and system features to <xliff:g id="DEVICE_NAME">%3$s</xliff:g> until you remove access to this permission."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps and other system features between your devices"</string> + <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>’s apps to <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> + <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that’s visible or played on <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, including audio, photos, payment info, passwords, and messages.<br/><br/><xliff:g id="APP_NAME_2">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> until you remove access to this permission."</string> + <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps from your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> <string name="profile_name_generic" msgid="6851028682723034988">"device"</string> <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string> <string name="consent_yes" msgid="8344487259618762872">"Allow"</string> diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml index 63d57c40aa5a..9f6219274258 100644 --- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml +++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> administre <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string> <string name="summary_glasses" msgid="5469208629679579157">"Esta app podrá acceder a los siguientes permisos en tu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"¿Quieres permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> transmita las apps de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> a <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> tendrá acceso a todo el contenido visible o que se reproduzca en <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, lo que incluye audio, fotos, contraseñas y mensajes.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> podrá transmitir apps a <xliff:g id="DEVICE_NAME">%3$s</xliff:g> hasta que se quite el acceso a este permiso."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para mostrar y transmitir apps entre dispositivos"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para acceder a las fotos, el contenido multimedia y las notificaciones de tu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"¿Quieres permitir que <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> transmita las apps y las funciones del sistema de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> a <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> tendrá acceso a todo el contenido visible o que se reproduzca en tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, lo que incluye audio, fotos, información de pago, contraseñas y mensajes.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> podrá transmitir apps y funciones del sistema a <xliff:g id="DEVICE_NAME">%3$s</xliff:g> hasta que se quite el acceso a este permiso."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para transmitir apps y otras funciones del sistema entre dispositivos"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="1761976003668044801">"Esta app podrá sincronizar información, como el nombre de la persona que llama, entre el teléfono y el dispositivo elegido"</string> <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string> diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml index f929d24fa081..44474b96b44c 100644 --- a/packages/CompanionDeviceManager/res/values-es/strings.xml +++ b/packages/CompanionDeviceManager/res/values-es/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"¿Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gestione <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string> <string name="summary_glasses" msgid="5469208629679579157">"Esta aplicación podrá acceder a estos permisos de tu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"¿Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> emita las aplicaciones de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> en <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> tendrá acceso a todo lo que se vea o se reproduzca en tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, incluidos audio, fotos, contraseñas y mensajes.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> podrá emitir aplicaciones en <xliff:g id="DEVICE_NAME">%3$s</xliff:g> hasta que quites el acceso a este permiso."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para mostrar y emitir aplicaciones en otros dispositivos tuyos"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para acceder a las fotos, los archivos multimedia y las notificaciones de tu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"¿Permitir que <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> emita las aplicaciones y funciones del sistema de tu<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> en <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> tendrá acceso a todo lo que se vea o se reproduzca en tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, incluidos audio, fotos, información para pagos, contraseñas y mensajes.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> podrá emitir aplicaciones y funciones del sistema en <xliff:g id="DEVICE_NAME">%3$s</xliff:g> hasta que quites el acceso a este permiso."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para emitir aplicaciones y otras funciones del sistema en otros dispositivos tuyos"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="1761976003668044801">"Esta aplicación podrá sincronizar información (por ejemplo, el nombre de la persona que te llama) entre tu teléfono y el dispositivo que elijas"</string> <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string> diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml index 5fcadcc9774e..a1cb0c6e857d 100644 --- a/packages/CompanionDeviceManager/res/values-et/strings.xml +++ b/packages/CompanionDeviceManager/res/values-et/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Lubage rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> hallata seadet <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"seade"</string> <string name="summary_glasses" msgid="5469208629679579157">"Sellel rakendusel lubatakse juurde pääseda nendele lubadele, mille asukoht on teie <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Kas lubate rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> voogesitada seadmes <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> rakendusi, mille asukoht on teie <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> saab juurdepääsu kõigele, mida teie <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> saab kuvada või esitada sh heli, fotod, paroolid ja sõnumid.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> saab voogesitada rakendusi ja süsteemifunktsioone seadmes <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, kuni eemaldate juurdepääsu sellele loale."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi kuvada ja voogesitada"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Lubage rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pääseda juurde sellele teabele, mille asukoht on teie <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nimel luba pääseda juurde fotodele, meediale ja märguannetele, mille asukoht on teie <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Kas lubate rakendusel <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> voogesitada seadmes <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> rakendusi ja süsteemifunktsioone, mille asukoht on teie <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> saab juurdepääsu kõigele, mida teie <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> saab kuvada või esitada, sh heli, fotod, makseteave, paroolid ja sõnumid.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> saab voogesitada rakendusi ja süsteemifunktsioone seadmes <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, kuni eemaldate juurdepääsu sellele loale."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nimel luba voogesitada teie seadmete vahel rakendusi ja muid süsteemifunktsioone"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"seade"</string> <string name="summary_generic" msgid="1761976003668044801">"See rakendus saab sünkroonida teavet, näiteks helistaja nime, teie telefoni ja valitud seadme vahel"</string> <string name="consent_yes" msgid="8344487259618762872">"Luba"</string> diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml index 46da125399aa..f88af3ce76e5 100644 --- a/packages/CompanionDeviceManager/res/values-eu/strings.xml +++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> kudeatzeko baimena eman nahi diozu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"gailua"</string> <string name="summary_glasses" msgid="5469208629679579157">"Baimen hauek izango ditu aplikazioak <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> erabiltzean:"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari zure <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuko aplikazioak <xliff:g id="DEVICE_NAME">%3$s</xliff:g> gailura zuzenean igortzeko baimena eman nahi diozu?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> aplikazioak <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuan ikusgai dagoen edo erreproduzitzen den eduki guztia atzitu ahal izango du, audioa, argazkiak, pasahitzak eta mezuak barne.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%3$s</xliff:g> gailura aplikazioak zuzenean igortzeko gai izango da, baimen hori kentzen diozun arte."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Aplikazioak gailuen artean bistaratzeko eta zuzenean igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%2$s</xliff:g> gailuaren izenean"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Eman informazioa <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailutik hartzeko baimena <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioari"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="DEVICE_TYPE">%3$s</xliff:g> gailuko argazkiak, multimedia-edukia eta jakinarazpenak atzitzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%2$s</xliff:g> gailuaren izenean"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> aplikazioari zure <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuko aplikazioak eta sistemaren eginbideak <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> gailura zuzenean igortzeko baimena eman nahi diozu?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> aplikazioak <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuan ikusgai dagoen edo erreproduzitzen den eduki guztia atzitu ahal izango du, audioa, argazkiak, ordainketa-informazioa, pasahitzak eta mezuak barne.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%3$s</xliff:g> gailura aplikazioak eta sistemaren eginbideak zuzenean igortzeko gai izango da, baimen hori kentzen diozun arte."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Aplikazioak eta sistemaren beste eginbide batzuk zure gailuen artean igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%2$s</xliff:g> gailuaren izenean"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"gailua"</string> <string name="summary_generic" msgid="1761976003668044801">"Telefonoaren eta hautatutako gailuaren artean informazioa sinkronizatzeko gai izango da aplikazioa (esate baterako, deitzaileen izenak)"</string> <string name="consent_yes" msgid="8344487259618762872">"Eman baimena"</string> diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml index 6a651d9738f0..9066c6a1cb7c 100644 --- a/packages/CompanionDeviceManager/res/values-fa/strings.xml +++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> اجازه داده شود <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> را مدیریت کند؟"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"دستگاه"</string> <string name="summary_glasses" msgid="5469208629679579157">"این برنامه قادر خواهد بود به این اجازهها در <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> شما دسترسی پیدا کند"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> اجازه میدهید برنامههای <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> را در <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> جاریسازی کند؟"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> به هرچیزی که در <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> نمایان است یا پخش میشود، ازجمله صداها، عکسها، گذرواژهها، و پیامها دسترسی خواهد داشت.<br/><br/>تا زمانیکه دسترسی به این اجازه را حذف نکنید، <xliff:g id="APP_NAME_1">%1$s</xliff:g> میتواند برنامهها را در <xliff:g id="DEVICE_NAME">%3$s</xliff:g> جاریسازی کند."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> ازطرف <xliff:g id="DEVICE_NAME">%2$s</xliff:g> اجازه میخواهد برنامهها را بین دستگاههای شما نمایش دهد و جاریسازی کند"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"اجازه دادن به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> برای دسترسی به این اطلاعات در <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> شما"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> ازطرف <xliff:g id="DEVICE_NAME">%2$s</xliff:g> اجازه میخواهد به عکسها، رسانهها، و اعلانهای <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> شما دسترسی پیدا کند"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"به <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> اجازه میدهید برنامهها و ویژگیهای سیستم <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> را در <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> جاریسازی کند؟"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> به هرچیزی که در <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> شما نمایان است یا پخش میشود، ازجمله صداها، عکسها، اطلاعات پرداخت، گذرواژهها، و پیامها دسترسی خواهد داشت.<br/><br/>تا زمانیکه دسترسی به این اجازه را حذف نکنید، <xliff:g id="APP_NAME_1">%1$s</xliff:g> میتواند برنامهها و ویژگیهای سیستم را در <xliff:g id="DEVICE_NAME">%3$s</xliff:g> جاریسازی کند."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> ازطرف <xliff:g id="DEVICE_NAME">%2$s</xliff:g> اجازه میخواهد برنامهها و دیگر ویژگیهای سیستم را بین دستگاههای شما جاریسازی کند"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"دستگاه"</string> <string name="summary_generic" msgid="1761976003668044801">"این برنامه مجاز میشود اطلاعتی مثل نام شخصی را که تماس میگیرد بین تلفن شما و دستگاه انتخابشده همگامسازی کند"</string> <string name="consent_yes" msgid="8344487259618762872">"اجازه دادن"</string> diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml index 5626f0a788aa..e155077142b0 100644 --- a/packages/CompanionDeviceManager/res/values-fi/strings.xml +++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Salli, että <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> saa ylläpitää laitetta: <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"laite"</string> <string name="summary_glasses" msgid="5469208629679579157">"Sovellus saa käyttää näitä lupia <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Saako <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> striimata <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> olevia sovelluksia laitteelle (<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>)?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> saa pääsyn kaikkeen <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> näkyvään tai pelattavaan sisältöön, mukaan lukien audioon, kuviin, salasanoihin ja viesteihin.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> voi striimata sovelluksia laitteelle (<xliff:g id="DEVICE_NAME">%3$s</xliff:g>), kunnes poistat luvan."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteesi (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) puolesta lupaa näyttää ja striimata sovelluksia laitteidesi välillä"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Salli, että <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> saa pääsyn näihin <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> oleviin tietoihin"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteesi (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) puolesta lupaa päästä <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> oleviin kuviin, mediaan ja ilmoituksiin"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Saako <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> striimata <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> olevia sovelluksia ja järjestelmäominaisuuksia laitteelle (<strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>)?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> saa pääsyn kaikkeen <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> näkyvään tai pelattavaan sisältöön, mukaan lukien audioon, kuviin, maksutietoihin, salasanoihin ja viesteihin.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> voi striimata sovelluksia ja järjestelmäominaisuuksia laitteelle (<xliff:g id="DEVICE_NAME">%3$s</xliff:g>), kunnes poistat luvan."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteesi (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) puolesta lupaa striimata sovelluksia ja muita järjestelmän ominaisuuksia laitteidesi välillä"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"laite"</string> <string name="summary_generic" msgid="1761976003668044801">"Sovellus voi synkronoida tietoja (esimerkiksi soittajan nimen) puhelimesi ja valitun laitteen välillä"</string> <string name="consent_yes" msgid="8344487259618762872">"Salli"</string> diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml index 61a8b735fd6d..b5de650d356b 100644 --- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml +++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à gérer <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"appareil"</string> <string name="summary_glasses" msgid="5469208629679579157">"Cette appli pourra accéder à ces autorisations sur votre <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à diffuser les applis de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> vers <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> aura accès à tout ce qui est visible ou lu sur votre<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, y compris le contenu audio, les photos, les mots de passe et les messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> pourra diffuser des applis vers <xliff:g id="DEVICE_NAME">%3$s</xliff:g> jusqu\'à ce que vous retiriez l\'accès à cette autorisation."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_NAME">%2$s</xliff:g> pour afficher et diffuser des applis entre vos appareils"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à ces informations à partir de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_NAME">%2$s</xliff:g> pour accéder aux photos, aux fichiers multimédias et aux notifications de votre <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Autoriser <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> à diffuser les applis et les fonctionnalités du système de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> vers <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> aura accès à tout ce qui est visible ou lu sur votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, y compris le contenu audio, les photos, les infos de paiement, les mots de passe et les messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> pourra diffuser des applis et des fonctionnalités du système vers <xliff:g id="DEVICE_NAME">%3$s</xliff:g> jusqu\'à ce que vous retiriez l\'accès à cette autorisation."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_NAME">%2$s</xliff:g> pour diffuser des applis et d\'autres fonctionnalités du système entre vos appareils"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string> <string name="summary_generic" msgid="1761976003668044801">"Cette appli pourra synchroniser des informations, comme le nom de l\'appelant, entre votre téléphone et l\'appareil sélectionné"</string> <string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string> diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml index b3193648a00f..b4933ee2279f 100644 --- a/packages/CompanionDeviceManager/res/values-fr/strings.xml +++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à gérer <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"appareil"</string> <string name="summary_glasses" msgid="5469208629679579157">"Cette appli sera autorisée à accéder à ces autorisations sur votre <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à caster les applis de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> sur <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> aura accès à tout ce qui est visible ou lu sur votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, y compris les contenus audio, les photos, les mots de passe et les messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> pourra caster des applis sur <xliff:g id="DEVICE_NAME">%3$s</xliff:g> jusqu\'à ce que vous supprimiez l\'accès à cette autorisation."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_NAME">%2$s</xliff:g> pour afficher et caster des applis d\'un appareil à l\'autre"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à ces informations depuis votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_NAME">%2$s</xliff:g> pour accéder aux photos, multimédias et notifications de votre <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Autoriser <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> à caster les applis et les fonctionnalités système de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> sur <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> ?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> aura accès à tout ce qui est visible ou lu sur votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, y compris les contenus audio, les photos, les infos de paiement, les mots de passe et les messages.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> pourra caster des applis et des fonctionnalités système sur <xliff:g id="DEVICE_NAME">%3$s</xliff:g> jusqu\'à ce que vous supprimiez l\'accès à cette autorisation."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_NAME">%2$s</xliff:g> pour caster des applis et d\'autres fonctionnalités système d\'un appareil à l\'autre"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string> <string name="summary_generic" msgid="1761976003668044801">"Cette appli pourra synchroniser des infos, comme le nom de l\'appelant, entre votre téléphone et l\'appareil choisi"</string> <string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string> diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml index ccab521efd76..85bfdc0f33a5 100644 --- a/packages/CompanionDeviceManager/res/values-gl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Queres permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> xestione o dispositivo (<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>)?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string> <string name="summary_glasses" msgid="5469208629679579157">"Esta aplicación poderá acceder a estes permisos do dispositivo (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Queres permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> emita as aplicacións do dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) en <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> terá acceso a todo o que se vexa ou reproduza no dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>), como audio, fotos, contrasinais e mensaxes.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> poderá emitir aplicacións en <xliff:g id="DEVICE_NAME">%3$s</xliff:g> ata que quites o acceso a este permiso."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) para mostrar e emitir aplicacións entre dispositivos"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información do dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>)"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) para acceder ás fotos, ao contido multimedia e ás notificacións do seguinte aparello: <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Queres permitir que <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> emita as aplicacións e as funcións do sistema do dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) en <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> terá acceso a todo o que se vexa ou reproduza no dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>), como audio, fotos, contrasinais e mensaxes.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> poderá emitir aplicacións e outras funcións do sistema en <xliff:g id="DEVICE_NAME">%3$s</xliff:g> ata que quites o acceso a este permiso."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) para emitir aplicacións e outras funcións do sistema entre dispositivos"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="1761976003668044801">"Esta aplicación poderá sincronizar información (por exemplo, o nome de quen chama) entre o teléfono e o dispositivo escollido"</string> <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string> diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml index 816717b784a4..9effe2ce2226 100644 --- a/packages/CompanionDeviceManager/res/values-gu/strings.xml +++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> મેનેજ કરવા માટે મંજૂરી આપીએ?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"ડિવાઇસ"</string> <string name="summary_glasses" msgid="5469208629679579157">"આ ઍપને તમારા <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> પર આ પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી મળશે"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"શું <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ની ઍપને <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> પર સ્ટ્રીમ કરવાની મંજૂરી આપીએ?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>ની પાસે એવી બધી બાબતોનો ઍક્સેસ રહેશે જે <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> પર જોઈ શકાતી કે ચલાવી શકાતી હોય, જેમાં ઑડિયો, ફોટા, પાસવર્ડ અને મેસેજ શામેલ છે.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> ત્યાં સુધી ઍપને <xliff:g id="DEVICE_NAME">%3$s</xliff:g> પર સ્ટ્રીમ કરી શકશે, જ્યાં સુધી તમે આ પરવાનગીનો ઍક્સેસ કાઢી નહીં નાખો."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"તમારા એક ડિવાઇસ પરથી બીજા ડિવાઇસ પર ઍપને ડિસ્પ્લે તેમજ સ્ટ્રીમ કરવા માટે, <xliff:g id="APP_NAME">%1$s</xliff:g> તમારા <xliff:g id="DEVICE_NAME">%2$s</xliff:g> વતી પરવાનગી માગી રહી છે"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"તમારા <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>માંથી આ માહિતી ઍક્સેસ કરવા માટે, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને મંજૂરી આપો"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> તમારા <xliff:g id="DEVICE_NAME">%2$s</xliff:g> વતી તમારા <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>ના ફોટા, મીડિયા અને નોટિફિકેશન ઍક્સેસ કરવાની પરવાનગીની વિનંતી કરી રહી છે"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"શું <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong>ને <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ની ઍપ અને સિસ્ટમની સુવિધાઓને <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> પર સ્ટ્રીમ કરવાની મંજૂરી આપીએ?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>ની પાસે એવી બધી બાબતોનો ઍક્સેસ રહેશે જે <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> પર જોઈ શકાતી કે ચલાવી શકાતી હોય, જેમાં ઑડિયો, ફોટા, ચુકવણીની માહિતી, પાસવર્ડ અને મેસેજ શામેલ છે.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> ત્યાં સુધી ઍપ અને સિસ્ટમની સુવિધાઓને <xliff:g id="DEVICE_NAME">%3$s</xliff:g> પર સ્ટ્રીમ કરી શકશે, જ્યાં સુધી તમે આ પરવાનગીનો ઍક્સેસ કાઢી નહીં નાખો."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> તમારા ડિવાઇસ વચ્ચે ઍપ અને સિસ્ટમની અન્ય સુવિધાઓ સ્ટ્રીમ કરવા તમારા <xliff:g id="DEVICE_NAME">%2$s</xliff:g> વતી પરવાનગીની વિનંતી કરી રહી છે"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"ડિવાઇસ"</string> <string name="summary_generic" msgid="1761976003668044801">"આ ઍપ તમારા ફોન અને પસંદ કરેલા ડિવાઇસ વચ્ચે, કૉલ કરનાર કોઈ વ્યક્તિનું નામ જેવી માહિતી સિંક કરી શકશે"</string> <string name="consent_yes" msgid="8344487259618762872">"મંજૂરી આપો"</string> diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml index b5a40e95fb0f..2a08e0030f8f 100644 --- a/packages/CompanionDeviceManager/res/values-hi/strings.xml +++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"क्या <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> मैनेज करने की अनुमति देनी है?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"डिवाइस"</string> <string name="summary_glasses" msgid="5469208629679579157">"यह ऐप्लिकेशन, आपके <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> पर इन अनुमतियों को ऐक्सेस कर पाएगा"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"क्या <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> के ऐप्लिकेशन <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> पर स्ट्रीम करने की अनुमति देनी है?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> के पास ऐसे किसी भी कॉन्टेंट का ऐक्सेस होगा जो इस <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> पर दिखता है या चलाया जाता है. इसमें ऑडियो, फ़ोटो, पासवर्ड, और मैसेज भी शामिल हैं.<br/><br/>.<xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%3$s</xliff:g> पर तब तक ऐप्लिकेशन स्ट्रीम कर पाएगा, जब तक आप यह अनुमति हटा न दें."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"आपके <xliff:g id="DEVICE_NAME">%2$s</xliff:g> की ओर से <xliff:g id="APP_NAME">%1$s</xliff:g>, आपके डिवाइस में मौजूद ऐप्लिकेशन को अन्य डिवाइसों पर दिखाने और स्ट्रीम करने की अनुमति मांग रहा है"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> की यह जानकारी ऐक्सेस करने दें"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"आपके <xliff:g id="DEVICE_NAME">%2$s</xliff:g> की ओर से <xliff:g id="APP_NAME">%1$s</xliff:g>, आपके <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> में मौजूद फ़ोटो, मीडिया, और सूचनाओं को ऐक्सेस करने की अनुमति मांग रहा है"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"क्या <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> को आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> के ऐप्लिकेशन और सिस्टम की सुविधाओं को <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> पर स्ट्रीम करने की अनुमति देनी है?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> के पास ऐसे किसी भी कॉन्टेंट का ऐक्सेस होगा जो आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> पर दिखता है या चलाया जाता है. इसमें ऑडियो, फ़ोटो, पेमेंट की जानकारी, पासवर्ड, और मैसेज भी शामिल हैं.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%3$s</xliff:g> पर तब ऐप्लिकेशन और सिस्टम की सुविधाओं को स्ट्रीम कर सकेगा, जब तक आप यह अनुमति हटा न दें."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"आपके <xliff:g id="DEVICE_NAME">%2$s</xliff:g> की ओर से <xliff:g id="APP_NAME">%1$s</xliff:g>, आपके डिवाइस में मौजूद ऐप्लिकेशन और सिस्टम की अन्य सुविधाओं को आपके दूसरे डिवाइसों पर स्ट्रीम करने की अनुमति मांग रहा है"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"डिवाइस"</string> <string name="summary_generic" msgid="1761976003668044801">"यह ऐप्लिकेशन, आपके फ़ोन और चुने हुए डिवाइस के बीच जानकारी सिंक करेगा. जैसे, कॉल करने वाले व्यक्ति का नाम"</string> <string name="consent_yes" msgid="8344487259618762872">"अनुमति दें"</string> diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml index 2d94b6766d7f..6b3e20419be5 100644 --- a/packages/CompanionDeviceManager/res/values-hr/strings.xml +++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Dopustiti aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da upravlja uređajem <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"uređaj"</string> <string name="summary_glasses" msgid="5469208629679579157">"Aplikacija će moći pristupati ovim dopuštenjima na vašem uređaju <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Želite li dopustiti aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da streama aplikacije uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na uređaj <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> imat će pristup svemu što je vidljivo ili se reproducira na uređaju <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, uključujući zvuk, fotografije, zaporke i poruke.<br/><br/>Aplikacija <xliff:g id="APP_NAME_1">%1$s</xliff:g> moći će streamati aplikacije na uređaj <xliff:g id="DEVICE_NAME">%3$s</xliff:g> dok ne uklonite pristup za to dopuštenje."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> za prikaz i streaming aplikacija s jednog uređaja na drugi"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Omogućite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da pristupa informacijama s vašeg uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> za pristup fotografijama, medijskim sadržajima i obavijestima na uređaju <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Želite li dopustiti uređaju <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> da streama aplikacije i značajke sustava uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na uređaj <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> imat će pristup svemu što je vidljivo ili se reproducira na vašem uređaju <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, uključujući zvuk, fotografije, informacije o plaćanju, zaporke i poruke.<br/><br/>Aplikacija <xliff:g id="APP_NAME_1">%1$s</xliff:g> moći će streamati aplikacije i značajke sustava na uređaj <xliff:g id="DEVICE_NAME">%3$s</xliff:g> dok ne uklonite pristup za to dopuštenje."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtjeva dopuštenja u ime vašeg uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> za stream aplikacija i drugih značajki sustava između vaših uređaja"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string> <string name="summary_generic" msgid="1761976003668044801">"Ta će aplikacija moći sinkronizirati podatke između vašeg telefona i odabranog uređaja, primjerice ime pozivatelja"</string> <string name="consent_yes" msgid="8344487259618762872">"Dopusti"</string> diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml index b63f8ab80f42..31d98283fed6 100644 --- a/packages/CompanionDeviceManager/res/values-hu/strings.xml +++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Engedélyezi, hogy a(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> kezelje a következő eszközt: <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"eszköz"</string> <string name="summary_glasses" msgid="5469208629679579157">"Az alkalmazás hozzáférhet majd ezekhez az engedélyekhez a következőn: <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Engedélyezi a(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> számára a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> alkalmazásainak streamelését a következőre: <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"A(z) <xliff:g id="APP_NAME_0">%1$s</xliff:g> hozzáférhet a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> minden látható vagy lejátszható tartalmához, így az audiotartalmakhoz, fényképekhez, jelszavakhoz és üzenetekhez is.<br/><br/>Amíg Ön el nem távolítja az ehhez az engedélyhez való hozzáférést, a(z) <xliff:g id="APP_NAME_1">%1$s</xliff:g> képes lesz majd az alkalmazások és a rendszerfunkciók <xliff:g id="DEVICE_NAME">%3$s</xliff:g> eszközre való streamelésére."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nevében az alkalmazások eszközök közötti megjelenítéséhez és streameléséhez."</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Engedélyezi a(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazás számára az ehhez az információhoz való hozzáférést a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> esetén"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nevében a(z) <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> fotóihoz, médiatartalmaihoz és értesítéseihez való hozzáféréshez"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Engedélyezi a(z) <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> számára a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> alkalmazásainak és rendszerfunkcióinak streamelését a következőre: <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"A(z) <xliff:g id="APP_NAME_0">%1$s</xliff:g> hozzáférhet a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> minden látható vagy lejátszható tartalmához, így az audiotartalmakhoz, fényképekhez, fizetési adatokhoz, jelszavakhoz és üzenetekhez is.<br/><br/>Amíg Ön el nem távolítja az ehhez az engedélyhez való hozzáférést, a(z) <xliff:g id="APP_NAME_1">%1$s</xliff:g> képes lesz majd az alkalmazások és a rendszerfunkciók <xliff:g id="DEVICE_NAME">%3$s</xliff:g> eszközre való streamelésére."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nevében az alkalmazások és más rendszerfunkcióknak eszközök közötti streameléséhez"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"eszköz"</string> <string name="summary_generic" msgid="1761976003668044801">"Ez az alkalmazás képes lesz szinkronizálni az olyan információkat a telefon és a kiválasztott eszköz között, mint például a hívó fél neve."</string> <string name="consent_yes" msgid="8344487259618762872">"Engedélyezés"</string> diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml index f90a324383ac..a4238c0ef46c 100644 --- a/packages/CompanionDeviceManager/res/values-hy/strings.xml +++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Թույլատրե՞լ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին կառավարել <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> սարքը"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"սարք"</string> <string name="summary_glasses" msgid="5469208629679579157">"Այս հավելվածը կստանա հետևյալ թույլտվությունները ձեր <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>ում"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Թույլատրե՞լ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին հեռարձակել ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ի հավելվածները <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> սարքին։"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> հավելվածին հասանելի կլինի ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ում ցուցադրվող կամ նվագարկվող բովանդակությունը՝ ներառյալ աուդիոն, լուսանկարները, գաղտնաբառերը և հաղորդագրությունները։<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> հավելվածը կկարողանա հավելվածներ հեռարձակել <xliff:g id="DEVICE_NAME">%3$s</xliff:g> սարքին, քանի դեռ չեք չեղարկել այս թույլտվությունը։"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_NAME">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր սարքերի միջև հավելվածներ հեռարձակելու համար"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Թույլատրեք <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին օգտագործել այս տեղեկությունները ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ից"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_NAME">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>ի լուսանկարները, մեդիաֆայլերն ու ծանուցումները տեսնելու համար"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Թույլատրե՞լ <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> սարքին հեռարձակել ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ի հավելվածները և համակարգի գործառույթները <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> սարքին։"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> հավելվածին հասանելի կլինի ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ում ցուցադրվող կամ նվագարկվող բովանդակությունը՝ ներառյալ աուդիոն, լուսանկարները, վճարային տեղեկությունները, գաղտնաբառերը և հաղորդագրությունները։<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> հավելվածը կկարողանա հավելվածներ և համակարգի գործառույթներ հեռարձակել <xliff:g id="DEVICE_NAME">%3$s</xliff:g> սարքին, քանի դեռ չեք չեղարկել այս թույլտվությունը։"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_NAME">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր սարքերի միջև հավելվածներ հեռարձակելու համար"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"սարք"</string> <string name="summary_generic" msgid="1761976003668044801">"Այս հավելվածը կկարողանա համաժամացնել ձեր հեռախոսի և ընտրված սարքի տվյալները, օր․՝ զանգողի անունը"</string> <string name="consent_yes" msgid="8344487259618762872">"Թույլատրել"</string> diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml index 7a9f4854cfab..2ee4e89a448d 100644 --- a/packages/CompanionDeviceManager/res/values-in/strings.xml +++ b/packages/CompanionDeviceManager/res/values-in/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> mengelola <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"perangkat"</string> <string name="summary_glasses" msgid="5469208629679579157">"Aplikasi ini akan diizinkan mengakses izin ini di <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> Anda"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> men-streaming aplikasi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ke <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> akan memiliki akses ke apa pun yang ditampilkan atau diputar di <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, termasuk audio, foto, sandi, dan pesan.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> akan dapat men-streaming aplikasi ke <xliff:g id="DEVICE_NAME">%3$s</xliff:g> hingga Anda menghapus izin ini."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_NAME">%2$s</xliff:g> untuk menampilkan dan men-streaming aplikasi di antara perangkat Anda"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk mengakses informasi ini dari <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> Anda"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_NAME">%2$s</xliff:g> untuk mengakses foto, media, dan notifikasi <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> Anda"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Izinkan <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> men-streaming aplikasi dan fitur sistem <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ke <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> akan memiliki akses ke apa pun yang ditampilkan atau diputar di <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, termasuk audio, foto, info pembayaran, sandi, dan pesan.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> akan dapat men-streaming aplikasi dan fitur sistem ke <xliff:g id="DEVICE_NAME">%3$s</xliff:g> hingga Anda menghapus izin ini."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_NAME">%2$s</xliff:g> untuk men-streaming aplikasi dan fitur sistem lainnya di antara perangkat Anda"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"perangkat"</string> <string name="summary_generic" msgid="1761976003668044801">"Aplikasi ini akan dapat menyinkronkan info, seperti nama penelepon, antara ponsel dan perangkat yang dipilih"</string> <string name="consent_yes" msgid="8344487259618762872">"Izinkan"</string> diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml index 3a4170675bec..d86f5da3f3fa 100644 --- a/packages/CompanionDeviceManager/res/values-is/strings.xml +++ b/packages/CompanionDeviceManager/res/values-is/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Leyfa <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> að stjórna <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"tæki"</string> <string name="summary_glasses" msgid="5469208629679579157">"Þetta forrit fær aðgang að eftirfarandi heimildum í <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Leyfa <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> að streyma forritum í <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> í ;strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> fær aðgang að öllu sem er sýnilegt eða spilað í <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, þ.m.t. hljóði, myndum, greiðsluupplýsingum, aðgangsorðum og skilaboðum.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> getur streymt forritum í <xliff:g id="DEVICE_NAME">%3$s</xliff:g> þar til þú fjarlægir aðgang að þessari heimild."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> biður um heimild fyrir <xliff:g id="DEVICE_NAME">%2$s</xliff:g> til að birta og streyma forritum á milli tækjanna þinna"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Veita <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aðgang að þessum upplýsingum úr <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> biður um heimild fyrir <xliff:g id="DEVICE_NAME">%2$s</xliff:g> vegna aðgangs að myndum, margmiðlunarefni og tilkynningum í <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Leyfa <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> að streyma forritum og kerfiseiginleikum í <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> í <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> fær aðgang að öllu sem er sýnilegt eða spilað í <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, þ.m.t. hljóði, myndum, greiðsluupplýsingum, aðgangsorðum og skilaboðum.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> getur streymt forritum og kerfiseiginleikum í <xliff:g id="DEVICE_NAME">%3$s</xliff:g> þar til þú fjarlægir aðgang að þessari heimild."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> biður um heimild fyrir <xliff:g id="DEVICE_NAME">%2$s</xliff:g> til að streyma forritum og öðrum kerfiseiginleikum á milli tækjanna þinna"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"tæki"</string> <string name="summary_generic" msgid="1761976003668044801">"Þetta forrit mun geta samstillt upplýsingar, t.d. nafn þess sem hringir, á milli símans og valins tækis"</string> <string name="consent_yes" msgid="8344487259618762872">"Leyfa"</string> diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml index b85ce64857e0..2fdcaf0d9852 100644 --- a/packages/CompanionDeviceManager/res/values-it/strings.xml +++ b/packages/CompanionDeviceManager/res/values-it/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Vuoi consentire all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di gestire <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string> <string name="summary_glasses" msgid="5469208629679579157">"Questa app potrà accedere alle seguenti autorizzazioni <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>:"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Consentire all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di riprodurre in streaming le app <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> su <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> avrà accesso a tutti i contenuti visibili o riprodotti <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, inclusi audio, foto, password e messaggi.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> sarà in grado di riprodurre in streaming le app su <xliff:g id="DEVICE_NAME">%3$s</xliff:g> finché non rimuoverai l\'accesso a questa autorizzazione."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto di <xliff:g id="DEVICE_NAME">%2$s</xliff:g> l\'autorizzazione a mostrare e riprodurre in streaming app tra i dispositivi"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Consenti all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di accedere a queste informazioni <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto di <xliff:g id="DEVICE_NAME">%2$s</xliff:g> l\'autorizzazione ad accedere a foto, contenuti multimediali e notifiche <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Consentire all\'app <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> di riprodurre in streaming le app e le funzionalità di sistema <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> su <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> avrà accesso a tutti i contenuti visibili o riprodotti <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, inclusi audio, foto, dati di pagamento, password e messaggi.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> sarà in grado di riprodurre in streaming app e funzionalità di sistema su <xliff:g id="DEVICE_NAME">%3$s</xliff:g> finché non rimuoverai l\'accesso a questa autorizzazione."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto di <xliff:g id="DEVICE_NAME">%2$s</xliff:g> l\'autorizzazione a riprodurre in streaming app e altre funzionalità di sistema tra i dispositivi"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="1761976003668044801">"Questa app potrà sincronizzare informazioni, ad esempio il nome di un chiamante, tra il telefono e il dispositivo scelto"</string> <string name="consent_yes" msgid="8344487259618762872">"Consenti"</string> diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml index 8148f564da8d..2efb77e31905 100644 --- a/packages/CompanionDeviceManager/res/values-iw/strings.xml +++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"מתן הרשאה לאפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong&g; לנהל את <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"מכשיר"</string> <string name="summary_glasses" msgid="5469208629679579157">"האפליקציה הזו תוכל לגשת להרשאות האלה ב<xliff:g id="DEVICE_TYPE">%1$s</xliff:g> שלך"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"לאשר לאפליקציית <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לשדר את האפליקציות של ה<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ל-<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"לאפליקציה <xliff:g id="APP_NAME_0">%1$s</xliff:g> תהיה גישה לכל מה שרואים או מפעילים ב<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, כולל אודיו, תמונות, סיסמאות והודעות.<br/><br/>לאפליקציה <xliff:g id="APP_NAME_1">%1$s</xliff:g> תהיה אפשרות לשדר אפליקציות ל-<xliff:g id="DEVICE_NAME">%3$s</xliff:g> עד שהגישה להרשאה הזו תוסר."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה ל-<xliff:g id="DEVICE_NAME">%2$s</xliff:g> כדי להציג ולשדר אפליקציות בין המכשירים שלך"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"מתן אישור לאפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לגשת למידע הזה מה<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> שלך"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה ל-<xliff:g id="DEVICE_NAME">%2$s</xliff:g> כדי לגשת לתמונות, למדיה ולהתראות ב<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"לאשר ל-<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> לשדר אפליקציות ותכונות מערכת אחרות של ה<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> למכשיר <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"לאפליקציה <xliff:g id="APP_NAME_0">%1$s</xliff:g> תהיה גישה לכל מה שרואים או מפעילים ב<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, כולל אודיו, תמונות, פרטי תשלום, סיסמאות והודעות.<br/><br/>לאפליקציה <xliff:g id="APP_NAME_1">%1$s</xliff:g> תהיה אפשרות לשדר אפליקציות ותכונות מערכת ל-<xliff:g id="DEVICE_NAME">%3$s</xliff:g> עד שהגישה להרשאה הזו תוסר."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה ל<xliff:g id="DEVICE_NAME">%2$s</xliff:g> כדי לשדר אפליקציות ותכונות מערכת אחרות בין המכשירים שלך"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"מכשיר"</string> <string name="summary_generic" msgid="1761976003668044801">"האפליקציה הזו תוכל לסנכרן מידע, כמו השם של מישהו שמתקשר, מהטלפון שלך למכשיר שבחרת"</string> <string name="consent_yes" msgid="8344487259618762872">"יש אישור"</string> diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml index 173a72f0b63d..639e8bca45a5 100644 --- a/packages/CompanionDeviceManager/res/values-ja/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml @@ -25,17 +25,17 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> の管理を許可しますか?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"デバイス"</string> <string name="summary_glasses" msgid="5469208629679579157">"このアプリは、<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>の以下の権限にアクセスできるようになります"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> のアプリを <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> にストリーミングすることを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可しますか?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> は、音声、写真、パスワード、メッセージを含め、<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>で表示、再生されるすべてのコンテンツにアクセスできるようになります。<br/><br/>この権限へのアクセス権を削除するまで、<xliff:g id="APP_NAME_1">%1$s</xliff:g> は <xliff:g id="DEVICE_NAME">%3$s</xliff:g> にアプリをストリーミングできます。"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_NAME">%2$s</xliff:g> に代わってデバイス間でアプリを表示およびストリーミングする権限をリクエストしています"</string> + <string name="title_app_streaming" msgid="1047090167914857893">"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> のアプリとシステム機能を <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> にストリーミングすることを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可しますか?"</string> + <string name="summary_app_streaming" msgid="7990244299655610920">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> は、音声、写真、お支払い情報、パスワード、メッセージを含め、<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> で表示、再生されるすべてのコンテンツにアクセスできるようになります。<br/><br/>この権限へのアクセス権を削除するまで、<xliff:g id="APP_NAME_1">%1$s</xliff:g> は <xliff:g id="DEVICE_NAME">%3$s</xliff:g> にアプリをストリーミングできます。"</string> + <string name="helper_summary_app_streaming" msgid="1872657107404139828">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_NAME">%2$s</xliff:g> に代わって、アプリやシステム機能を <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> からストリーミングする権限をリクエストしています"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>のこの情報へのアクセスを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_NAME">%2$s</xliff:g> に代わって<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>の写真、メディア、通知にアクセスする権限をリクエストしています"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> のアプリとシステム機能を <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> にストリーミングすることを <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> に許可しますか?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> は、音声、写真、お支払い情報、パスワード、メッセージを含め、<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>で表示、再生されるすべてのコンテンツにアクセスできるようになります。<br/><br/>この権限へのアクセス権を削除するまで、<xliff:g id="APP_NAME_1">%1$s</xliff:g> は <xliff:g id="DEVICE_NAME">%3$s</xliff:g> にアプリとシステム機能をストリーミングできます。"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_NAME">%2$s</xliff:g> に代わって、アプリやその他のシステム機能をデバイス間でストリーミングする権限をリクエストしています"</string> + <string name="title_nearby_device_streaming" msgid="2727103756701741359">"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> のアプリを <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> にストリーミングすることを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可しますか?"</string> + <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> は、音声、写真、お支払い情報、パスワード、メッセージを含め、<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> で表示、再生されるすべてのコンテンツにアクセスできるようになります。<br/><br/>この権限へのアクセス権を削除するまで、<xliff:g id="APP_NAME_2">%1$s</xliff:g> は <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> にアプリをストリーミングできます。"</string> + <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_NAME">%2$s</xliff:g> に代わって、アプリを <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> からストリーミングする権限をリクエストしています"</string> <string name="profile_name_generic" msgid="6851028682723034988">"デバイス"</string> <string name="summary_generic" msgid="1761976003668044801">"このアプリは、あなたのスマートフォンと選択したデバイスとの間で、通話相手の名前などの情報を同期できるようになります"</string> <string name="consent_yes" msgid="8344487259618762872">"許可"</string> diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml index 507d13c2c7e0..949d64b821c0 100644 --- a/packages/CompanionDeviceManager/res/values-ka/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml @@ -25,17 +25,17 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"ნება დართეთ <strong><xliff:g id="APP_NAME">%1$s</xliff:g>-ს</strong> მართოს <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"მოწყობილობა"</string> <string name="summary_glasses" msgid="5469208629679579157">"ეს აპი შეძლებს წვდომას თქვენს <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>-ზე არსებულ ამ ნებართვებზე"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"გსურთ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ს მისცეთ თქვენი <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ის აპების სტრიმინგის საშუალება <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>-ზე?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>-ს ექნება წვდომა ყველაფერზე, რაც ჩანს ან უკრავს <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ზე, მათ შორის, აუდიოზე, ფოტოებზე, პაროლებსა და შეტყობინებებზე.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> შეძლებს აპების სტრიმინგს <xliff:g id="DEVICE_NAME">%3$s</xliff:g>-ზე მანამ, სანამ თქვენ არ გააუქმებთ წვდომას ამ ნებართვაზე."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს ნებართვას თქვენი (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) სახელით, რათა წარმოაჩინოს და მოახდინოს აპების სტრიმინგი თქვენს მოწყობილობებს შორის"</string> + <string name="title_app_streaming" msgid="1047090167914857893">"გსურთ, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ს მისცეთ თქვენი <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ის აპებისა და სისტემის ფუნქციების სტრიმინგის საშუალება <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>-ზე?"</string> + <string name="summary_app_streaming" msgid="7990244299655610920">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> მიიღებს წვდომას ყველაფერზე, რაც ჩანს ან უკრავს თქვენს <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ზე, მათ შორის, აუდიოზე, ფოტოებზე, გადახდის ინფორმაციაზე, პაროლებსა და შეტყობინებებზე.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> შეძლებს აპების სტრიმინგს <xliff:g id="DEVICE_NAME">%3$s</xliff:g>-ზე მანამ, სანამ თქვენ არ გააუქმებთ წვდომას ამ ნებართვაზე."</string> + <string name="helper_summary_app_streaming" msgid="1872657107404139828">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს ნებართვას <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-ის სახელით აპებისა და სისტემური ფუნქციების სტრიმინგისთვის თქვენი <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>-იდან"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ის წვდომის დაშვება თქვენს <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ში არსებულ ამ ინფორმაციაზე"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს ნებართვას თქვენი (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) სახელით, რათა მოიპოვოს წვდომა თქვენი <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>-ის ფოტოებზე, მედიასა და შეტყობინებებზე"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"გსურთ <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong>-ს მისცეთ თქვენი <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ის აპებისა და სისტემის ფუნქციების სტრიმინგის საშუალება <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>-ზე?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>-ს ექნება წვდომა ყველაფერზე, რაც ჩანს ან უკრავს თქვენს <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ზე, მათ შორის, აუდიოზე, ფოტოებზე, გადახდის ინფორმაციაზე, პაროლებსა და შეტყობინებებზე.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> შეძლებს აპებისა და სისტემის ფუნქციების სტრიმინგს <xliff:g id="DEVICE_NAME">%3$s</xliff:g>-ზე მანამ, სანამ თქვენ არ გააუქმებთ წვდომას ამ ნებართვაზე."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს ნებართვას თქვენი (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) სახელით, რათა მოახდინოს აპებისა და სისტემის სხვა ფუნქციების სტრიმინგი თქვენს მოწყობილობებს შორის"</string> + <string name="title_nearby_device_streaming" msgid="2727103756701741359">"გსურთ, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-ს მისცეთ თქვენი <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ის აპების სტრიმინგის საშუალება <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>-ზე?"</string> + <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> მიიღებს წვდომას ყველაფერზე, რაც ჩანს ან უკრავს <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>-ზე, მათ შორის, აუდიოზე, ფოტოებზე, პაროლებსა და შეტყობინებებზე.<br/><br/><xliff:g id="APP_NAME_2">%1$s</xliff:g> შეძლებს აპების სტრიმინგს <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>-ზე მანამ, სანამ თქვენ არ გააუქმებთ წვდომას ამ ნებართვაზე."</string> + <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს ნებართვას <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-ის სახელით აპების სტრიმინგისთვის თქვენი <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>-იდან"</string> <string name="profile_name_generic" msgid="6851028682723034988">"მოწყობილობა"</string> <string name="summary_generic" msgid="1761976003668044801">"ეს აპი შეძლებს ინფორმაციის სინქრონიზებას თქვენს ტელეფონსა და თქვენ მიერ არჩეულ მოწყობილობას შორის, მაგალითად, იმ ადამიანის სახელის, რომელიც გირეკავთ"</string> <string name="consent_yes" msgid="8344487259618762872">"დაშვება"</string> diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml index 16a02dcde559..f392c1050006 100644 --- a/packages/CompanionDeviceManager/res/values-kk/strings.xml +++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> құрылғысын басқаруға рұқсат беру керек пе?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"құрылғы"</string> <string name="summary_glasses" msgid="5469208629679579157">"Бұл қолданба құрылғыда (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>) осы рұқсаттарды пайдалана алады."</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына құрылғыңыздағы (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) қолданбаларды <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> құрылғысына трансляциялауға рұқсат берілсін бе?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> қолданбасы құрылғыда (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) көрінетін не ойнатылатын барлық контентті (аудиофайлдарды, фотосуреттерді, құпия сөздер мен хабарларды қоса алғанда) пайдалана алады.<br/><br/>Осы рұқсатты өшірмесеңіз, <xliff:g id="APP_NAME_1">%1$s</xliff:g> қолданбасы құрылғысына (<xliff:g id="DEVICE_NAME">%3$s</xliff:g>) қолданбаларды трансляциялай алады."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_NAME">%2$s</xliff:g> атынан құрылғыларыңыздың арасында қолданбаларды көрсетуге және трансляциялауға рұқсат сұрайды."</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына құрылғыңыздағы (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) осы ақпаратты пайдалануға рұқсат беріңіз."</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_NAME">%2$s</xliff:g> атынан құрылғыңыздағы (<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>) фотосуреттерді, медиафайлдар мен хабарландыруларды пайдалануға рұқсат сұрайды."</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> қолданбасына құрылғыңыздағы (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) қолданбалар мен жүйе функцияларын <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> құрылғысына трансляциялауға рұқсат берілсін бе?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> қолданбасы құрылғыңызда (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) көрінетін не ойнатылатын барлық контентті (аудиофайлдарды, фотосуреттерді, төлем туралы ақпаратты, құпия сөздер мен хабарларды қоса алғанда) пайдалана алады.<br/><br/>Осы рұқсатты өшірмесеңіз, <xliff:g id="APP_NAME_1">%1$s</xliff:g> қолданбасы құрылғыға (<xliff:g id="DEVICE_NAME">%3$s</xliff:g>) қолданбаларды және жүйе функцияларын трансляциялай алады."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_NAME">%2$s</xliff:g> атынан құрылғыларыңыздың арасында қолданбаларды және басқа жүйе функцияларын трансляциялауға рұқсат сұрайды."</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"құрылғы"</string> <string name="summary_generic" msgid="1761976003668044801">"Бұл қолданба телефон мен таңдалған құрылғы арасында деректі (мысалы, қоңырау шалушының атын) синхрондай алады."</string> <string name="consent_yes" msgid="8344487259618762872">"Рұқсат беру"</string> diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml index e59db722dc64..149c62440309 100644 --- a/packages/CompanionDeviceManager/res/values-km/strings.xml +++ b/packages/CompanionDeviceManager/res/values-km/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> គ្រប់គ្រង <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ឬ?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"ឧបករណ៍"</string> <string name="summary_glasses" msgid="5469208629679579157">"កម្មវិធីនេះនឹងត្រូវបានអនុញ្ញាតឱ្យចូលប្រើការអនុញ្ញាតទាំងនេះនៅលើ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> របស់អ្នក"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ផ្សាយកម្មវិធីលើ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នកទៅ <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ឬ?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> នឹងមានសិទ្ធិចូលប្រើអ្វីៗដែលអាចមើលឃើញ ឬត្រូវបានចាក់នៅលើ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> រួមទាំងសំឡេង រូបថត ពាក្យសម្ងាត់ និងសារ។<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> នឹងអាចផ្សាយកម្មវិធី <xliff:g id="DEVICE_NAME">%3$s</xliff:g> រហូតទាល់តែអ្នកដកសិទ្ធិចូលប្រើការអនុញ្ញាតនេះចេញ។"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> របស់អ្នក ដើម្បីបង្ហាញ និងផ្សាយកម្មវិធីរវាងឧបករណ៍នានារបស់អ្នក"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ចូលប្រើព័ត៌មាននេះពី <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នក"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> របស់អ្នក ដើម្បីចូលប្រើរូបថត មេឌៀ និងការជូនដំណឹងរបស់ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> អ្នក"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"អនុញ្ញាតឱ្យ <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> ផ្សាយមុខងារប្រព័ន្ធ និងកម្មវិធីលើ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នកទៅ <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> ឬ?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> នឹងមានសិទ្ធិចូលប្រើអ្វីៗដែលអាចមើលឃើញ ឬត្រូវបានចាក់នៅលើ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នក រួមទាំងសំឡេង រូបថត ព័ត៌មាននៃការទូទាត់ប្រាក់ ពាក្យសម្ងាត់ និងសារ។<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> នឹងអាចផ្សាយកម្មវិធី និងមុខងារប្រព័ន្ធទៅ <xliff:g id="DEVICE_NAME">%3$s</xliff:g> រហូតទាល់តែអ្នកដកសិទ្ធិចូលប្រើការអនុញ្ញាតនេះចេញ។"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> របស់អ្នក ដើម្បីផ្សាយកម្មវិធី និងមុខងារប្រព័ន្ធផ្សេងទៀតរវាងឧបករណ៍របស់អ្នក"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"ឧបករណ៍"</string> <string name="summary_generic" msgid="1761976003668044801">"កម្មវិធីនេះនឹងអាចធ្វើសមកាលកម្មព័ត៌មាន ដូចជាឈ្មោះមនុស្សដែលហៅទូរសព្ទជាដើម រវាងឧបករណ៍ដែលបានជ្រើសរើស និងទូរសព្ទរបស់អ្នក"</string> <string name="consent_yes" msgid="8344487259618762872">"អនុញ្ញាត"</string> diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml index ea7d8242b174..df7f4f461219 100644 --- a/packages/CompanionDeviceManager/res/values-kn/strings.xml +++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>? ನಿರ್ವಹಿಸಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"ಸಾಧನ"</string> <string name="summary_glasses" msgid="5469208629679579157">"ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> ನಲ್ಲಿ ಈ ಅನುಮತಿಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಈ ಆ್ಯಪ್ ಅನ್ನು ಅನುಮತಿಸಲಾಗುತ್ತದೆ"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನ ಆ್ಯಪ್ಗಳನ್ನು <xliff:g id="DEVICE_NAME">%3$s</xliff:g> ಗೆ ಸ್ಟ್ರೀಮ್ ಮಾಡಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನಲ್ಲಿನ ಆಡಿಯೋ, ಫೋಟೋಗಳು, ಪಾಸ್ವರ್ಡ್ಗಳು ಮತ್ತು ಸಂದೇಶಗಳು ಸೇರಿದಂತೆ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ನಲ್ಲಿ ಗೋಚರಿಸುವ ಅಥವಾ ಪ್ಲೇ ಆಗುವ ಯಾವುದಕ್ಕೂ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ನೀವು ಈ ಅನುಮತಿಗೆ <xliff:g id="DEVICE_NAME">%3$s</xliff:g> ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ತೆಗೆದುಹಾಕುವವರೆಗೆ <xliff:g id="APP_NAME_1">%1$s</xliff:g> ಗೆ ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್ಗಳನ್ನು ಪ್ರದರ್ಶಿಸಲು ಮತ್ತು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನಿಂದ ಈ ಮಾಹಿತಿಯನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸಿ"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> ನ ಫೋಟೋಗಳು, ಮೀಡಿಯಾ ಮತ್ತು ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನ ಆ್ಯಪ್ಗಳು ಮತ್ತು ಸಿಸ್ಟಮ್ ಫೀಚರ್ಗಳನ್ನು <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> ಗೆ ಸ್ಟ್ರೀಮ್ ಮಾಡಲು <xliff:g id="DEVICE_NAME_0">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನಲ್ಲಿನ ಆಡಿಯೋ, ಫೋಟೋಗಳು, ಪಾವತಿ ಮಾಹಿತಿ, ಪಾಸ್ವರ್ಡ್ಗಳು ಮತ್ತು ಸಂದೇಶಗಳು ಸೇರಿದಂತೆ ನಿಮ್ಮ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ನಲ್ಲಿ ಗೋಚರಿಸುವ ಅಥವಾ ಪ್ಲೇ ಆಗುವ ಯಾವುದಕ್ಕೂ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ನೀವು ಈ ಅನುಮತಿಗೆ <xliff:g id="DEVICE_NAME">%3$s</xliff:g> ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ತೆಗೆದುಹಾಕುವವರೆಗೆ <xliff:g id="APP_NAME_1">%1$s</xliff:g> ಗೆ ಆ್ಯಪ್ಗಳು ಮತ್ತು ಸಿಸ್ಟಮ್ ಫೀಚರ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ ."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್ಗಳು ಮತ್ತು ಇತರ ಸಿಸ್ಟಮ್ ಫೀಚರ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ಪರವಾಗಿ ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"ಸಾಧನ"</string> <string name="summary_generic" msgid="1761976003668044801">"ಮೊಬೈಲ್ ಫೋನ್ ಮತ್ತು ಆಯ್ಕೆಮಾಡಿದ ಸಾಧನದ ನಡುವೆ, ಕರೆ ಮಾಡುವವರ ಹೆಸರಿನಂತಹ ಮಾಹಿತಿಯನ್ನು ಸಿಂಕ್ ಮಾಡಲು ಈ ಆ್ಯಪ್ಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ"</string> <string name="consent_yes" msgid="8344487259618762872">"ಅನುಮತಿಸಿ"</string> diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml index 4ff768e5a1e5..0192eea3d644 100644 --- a/packages/CompanionDeviceManager/res/values-ko/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> 기기를 관리하도록 허용하시겠습니까?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"기기"</string> <string name="summary_glasses" msgid="5469208629679579157">"앱이 <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>에서 이러한 권한에 액세스할 수 있게 됩니다."</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>의 앱을 <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> 기기로 스트리밍하도록 허용하시겠습니까?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>에서 오디오, 사진, 비밀번호, 메시지 등 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>에 표시되거나 해당 기기에서 재생되는 모든 항목에 액세스할 수 있습니다.<br/><br/>이 권한에 대한 액세스를 삭제할 때까지 <xliff:g id="APP_NAME_1">%1$s</xliff:g>에서 <xliff:g id="DEVICE_NAME">%3$s</xliff:g> 기기로 앱을 스트리밍할 수 있습니다."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 대신 기기 간에 앱을 표시하고 스트리밍할 수 있는 권한을 요청하고 있습니다."</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 앱이 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>에서 이 정보에 액세스하도록 허용합니다."</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 대신 <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>의 사진, 미디어, 알림에 액세스할 수 있는 권한을 요청하고 있습니다."</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>의 앱 및 시스템 기능을 <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> 기기로 스트리밍하도록 허용하시겠습니까?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>에서 오디오, 사진, 결제 정보, 비밀번호, 메시지 등 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>에 표시되거나 해당 기기에서 재생되는 모든 항목에 액세스할 수 있습니다.<br/><br/>이 권한에 대한 액세스를 삭제할 때까지 <xliff:g id="APP_NAME_1">%1$s</xliff:g>에서 <xliff:g id="DEVICE_NAME">%3$s</xliff:g> 기기로 앱 및 시스템 기능을 스트리밍할 수 있습니다."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 대신 기기 간에 앱 및 다른 시스템 기능을 스트리밍할 권한을 요청하고 있습니다."</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"기기"</string> <string name="summary_generic" msgid="1761976003668044801">"이 앱에서 휴대전화와 선택한 기기 간에 정보(예: 발신자 이름)를 동기화할 수 있게 됩니다."</string> <string name="consent_yes" msgid="8344487259618762872">"허용"</string> diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml index 3e265a2678bc..d74436f03d28 100644 --- a/packages/CompanionDeviceManager/res/values-ky/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> түзмөгүн тескөөгө уруксат бересизби?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"түзмөк"</string> <string name="summary_glasses" msgid="5469208629679579157">"Бул колдонмого <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> түзмөгүңүздө төмөнкүлөрдү аткарууга уруксат берилет"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздөгү колдонмолорду <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> түзмөгүнө алып ойнотууга уруксат бересизби?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүндө көрүнгөн же ойнотулган бардык нерселерге, анын ичинде аудио, сүрөттөр, сырсөздөр жана билдирүүлөргө кире алат.<br/><br/>Бул уруксатты алып салмайынча, <xliff:g id="APP_NAME_1">%1$s</xliff:g> колдонмолорду <xliff:g id="DEVICE_NAME">%3$s</xliff:g> түзмөгүнө алып ойното алат."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу <xliff:g id="DEVICE_NAME">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрдүн ортосунда колдонмолорду көрсөтүү жана алып ойнотуу үчүн уруксат сурап жатат"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздөгү ушул маалыматты көрүүгө уруксат бериңиз"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу <xliff:g id="DEVICE_NAME">%2$s</xliff:g> түзмөгүңүздүн атынан <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> сүрөттөрүн, медиа файлдарын жана билдирмелерин колдонууга уруксат сурап жатат"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> түзмөгүнө <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүндөгү колдонмолорду жана тутумдун функцияларын <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> түзмөгүндө алып ойнотууга уруксат бересизби?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздө көрүнгөн же ойнотулган бардык нерселерге, анын ичинде аудио, сүрөттөр, төлөм маалыматы, сырсөздөр жана билдирүүлөргө кире алат.<br/><br/>Бул уруксатты алып салмайынча, <xliff:g id="APP_NAME_1">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%3$s</xliff:g> түзмөгүндөгү колдонмолорду жана тутум функцияларын алып ойното алат."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрдүн ортосунда колдонмолорду жана тутумдун башка функцияларын алып ойнотууга уруксат сурап жатат"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string> <string name="summary_generic" msgid="1761976003668044801">"Бул колдонмо маалыматты шайкештире алат, мисалы, чалып жаткан кишинин атын телефон жана тандалган түзмөк менен шайкештирет"</string> <string name="consent_yes" msgid="8344487259618762872">"Ооба"</string> diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml index 2917c3ea81d7..f8da499e63ba 100644 --- a/packages/CompanionDeviceManager/res/values-lo/strings.xml +++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml @@ -25,17 +25,17 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"ອະນຸຍາດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ຈັດການ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ບໍ?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"ອຸປະກອນ"</string> <string name="summary_glasses" msgid="5469208629679579157">"ແອັບນີ້ຈະໄດ້ຮັບສິດເຂົ້າເຖິງການອະນຸຍາດເຫຼົ່ານີ້ຢູ່ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> ຂອງທ່ານ"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"ອະນຸຍາດໃຫ້ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ສະຕຣີມແອັບຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ຂອງທ່ານໄປຫາ <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ບໍ?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ຈະມີສິດເຂົ້າເຖິງທຸກຢ່າງທີ່ປາກົດ ຫຼື ຫຼິ້ນຢູ່ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, ເຊິ່ງຮວມທັງສຽງ, ຮູບພາບ, ລະຫັດຜ່ານ ແລະ ຂໍ້ຄວາມ.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> ຈະສາມາດສະຕຣີມແອັບໄປຫາ <xliff:g id="DEVICE_NAME">%3$s</xliff:g> ໄດ້ຈົນກວ່າທ່ານຈະລຶບສິດເຂົ້າເຖິງການອະນຸຍາດນີ້ອອກ."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກໍາລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມຂອງ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ຂອງທ່ານເພື່ອສະແດງ ແລະ ສະຕຣີມແອັບລະຫວ່າງອຸປະກອນຕ່າງໆຂອງທ່ານ"</string> + <string name="title_app_streaming" msgid="1047090167914857893">"ອະນຸຍາດໃຫ້ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ສະຕຣີມແອັບ ແລະ ຄຸນສົມບັດຂອງລະບົບຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ຂອງທ່ານໄປຫາ <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ບໍ?"</string> + <string name="summary_app_streaming" msgid="7990244299655610920">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ຈະມີສິດເຂົ້າເຖິງທຸກຢ່າງທີ່ປາກົດ ຫຼື ຫຼິ້ນຢູ່ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ຂອງທ່ານ, ເຊິ່ງຮວມທັງສຽງ, ຮູບພາບ, ຂໍ້ມູນການຈ່າຍເງິນ ລະຫັດຜ່ານ ແລະ ຂໍ້ຄວາມ.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> ຈະສາມາດສະຕຣີມແອັບໄປຫາ <xliff:g id="DEVICE_NAME">%3$s</xliff:g> ໄດ້ຈົນກວ່າທ່ານຈະລຶບສິດເຂົ້າເຖິງການອະນຸຍາດນີ້ອອກ."</string> + <string name="helper_summary_app_streaming" msgid="1872657107404139828">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ເພື່ອສະຕຣີມແອັລ ແລະ ຄຸນສົມບັດລະບົບຈາກ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> ຂອງທ່ານ"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"ອະນຸຍາດໃຫ້ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ເຂົ້າເຖິງຂໍ້ມູນນີ້ຈາກ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ຂອງທ່ານ"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມຂອງ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ຂອງທ່ານເພື່ອເຂົ້າເຖິງຮູບພາບ, ສື່ ແລະ ການແຈ້ງເຕືອນໃນ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> ຂອງທ່ານ"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"ອະນຸຍາດໃຫ້ <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> ສະຕຣີມແອັບ ແລະ ຄຸນສົມບັດຂອງລະບົບຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ຂອງທ່ານໄປຫາ <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> ບໍ?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ຈະມີສິດເຂົ້າເຖິງທຸກຢ່າງທີ່ປາກົດ ຫຼື ຫຼິ້ນຢູ່ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ຂອງທ່ານ, ເຊິ່ງຮວມທັງສຽງ, ຮູບພາບ, ຂໍ້ມູນການຈ່າຍເງິນ ລະຫັດຜ່ານ ແລະ ຂໍ້ຄວາມ.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> ຈະສາມາດສະຕຣີມແອັບ ແລະ ຄຸນສົມບັດຂອງລະບົບໄປຫາ <xliff:g id="DEVICE_NAME">%3$s</xliff:g> ໄດ້ຈົນກວ່າທ່ານຈະລຶບສິດເຂົ້າເຖິງການອະນຸຍາດນີ້ອອກ."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມຂອງ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ຂອງທ່ານເພື່ອສະຕຣີມແອັບ ແລະ ຄຸນສົມບັດອື່ນໆຂອງລະບົບລະຫວ່າງອຸປະກອນຕ່າງໆຂອງທ່ານ"</string> + <string name="title_nearby_device_streaming" msgid="2727103756701741359">"ອະນຸຍາດໃຫ້ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ສະຕຣີມແອັບຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ຂອງທ່ານໄປຫາ <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ບໍ?"</string> + <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ຈະມີສິດເຂົ້າເຖິງທຸກຢ່າງທີ່ປາກົດ ຫຼື ຫຼິ້ນຢູ່ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, ເຊິ່ງຮວມທັງສຽງ, ຮູບພາບ, ຂໍ້ມູນການຈ່າຍເງິນ, ລະຫັດຜ່ານ ແລະ ຂໍ້ຄວາມ.<br/><br/><xliff:g id="APP_NAME_2">%1$s</xliff:g> ຈະສາມາດສະຕຣີມແອັບໄປຫາ <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> ໄດ້ຈົນກວ່າທ່ານຈະລຶບສິດເຂົ້າເຖິງການອະນຸຍາດນີ້ອອກ."</string> + <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ເພື່ອສະຕຣີມແອັບຈາກ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> ຂອງທ່ານ"</string> <string name="profile_name_generic" msgid="6851028682723034988">"ອຸປະກອນ"</string> <string name="summary_generic" msgid="1761976003668044801">"ແອັບນີ້ຈະສາມາດຊິ້ງຂໍ້ມູນ ເຊັ່ນ: ຊື່ຂອງຄົນທີ່ໂທເຂົ້າ, ລະຫວ່າງໂທລະສັບຂອງທ່ານ ແລະ ອຸປະກອນທີ່ເລືອກໄວ້ໄດ້"</string> <string name="consent_yes" msgid="8344487259618762872">"ອະນຸຍາດ"</string> diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml index a1b5cd9c0c50..8a6a564c39a7 100644 --- a/packages/CompanionDeviceManager/res/values-lt/strings.xml +++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Leisti <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> valdyti <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"įrenginio"</string> <string name="summary_glasses" msgid="5469208629679579157">"Šiai programai bus leidžiama pasiekti toliau nurodytus leidimus jūsų <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>."</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Leisti programai <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> srautu perduoti <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> programas į <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"Programa „<xliff:g id="APP_NAME_0">%1$s</xliff:g>“ galės pasiekti visą „<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>“ matomą ar leidžiamą turinį, įskaitant garso įrašus, nuotraukas, slaptažodžius ir pranešimus.<br/><br/>Programa „<xliff:g id="APP_NAME_1">%1$s</xliff:g>“ galės perduoti srautu programas į „<xliff:g id="DEVICE_NAME">%3$s</xliff:g>“, kol pašalinsite prieigą prie šio leidimo."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DEVICE_NAME">%2$s</xliff:g>“ vardu, kad galėtų rodyti ir srautu perduoti programas iš vieno įrenginio į kitą"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Leisti programai <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pasiekti šią informaciją iš jūsų <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DEVICE_NAME">%2$s</xliff:g>“ vardu, kad galėtų pasiekti <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> nuotraukas, mediją ir pranešimus"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Leisti programai <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> srautu perduoti <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> programas ir sistemos funkcijas į <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"Programa „<xliff:g id="APP_NAME_0">%1$s</xliff:g>“ galės pasiekti visą <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> matomą ar leidžiamą turinį, įskaitant garso įrašus, nuotraukas, mokėjimo informaciją, slaptažodžius ir pranešimus.<br/><br/>Programa „<xliff:g id="APP_NAME_1">%1$s</xliff:g>“ galės perduoti srautu programas ir sistemos funkcijas į „<xliff:g id="DEVICE_NAME">%3$s</xliff:g>“, kol pašalinsite prieigą prie šio leidimo."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DEVICE_NAME">%2$s</xliff:g>“ vardu, kad galėtų srautu perduoti programas ir kitas sistemos funkcijas iš vieno įrenginio į kitą"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"įrenginys"</string> <string name="summary_generic" msgid="1761976003668044801">"Ši programa galės sinchronizuoti tam tikrą informaciją, pvz., skambinančio asmens vardą, su jūsų telefonu ir pasirinktu įrenginiu"</string> <string name="consent_yes" msgid="8344487259618762872">"Leisti"</string> diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml index 880b981336bf..26f0968d9e50 100644 --- a/packages/CompanionDeviceManager/res/values-lv/strings.xml +++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Vai atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> piekļūt ierīcei <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"ierīce"</string> <string name="summary_glasses" msgid="5469208629679579157">"Šī lietotne drīkstēs piekļūt norādītajām <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> atļaujām."</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Vai atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> straumēt <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> lietotnes ierīcē <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> varēs piekļūt visam <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ekrānā parādītajam vai atskaņotajam saturam, tostarp audio, fotoattēliem, parolēm un ziņojumiem.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> varēs straumēt lietotnes ierīcē <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, līdz noņemsiet piekļuvi šai atļaujai."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju attēlot un straumēt lietotnes starp jūsu ierīcēm šīs ierīces vārdā: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Vai atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> piekļūt šai informācijai no jūsu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>?"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju piekļūt jūsu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> fotoattēliem, multivides saturam un paziņojumiem šīs ierīces vārdā: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>."</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Vai atļaut lietotnei <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> straumēt <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> lietotnes un sistēmas funkcijas ierīcē <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> varēs piekļūt visam <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ekrānā parādītajam vai atskaņotajam saturam, tostarp audio, fotoattēliem, maksājumu informācijai, parolēm un ziņojumiem.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> varēs straumēt lietotnes un sistēmas funkcijas ierīcē <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, līdz noņemsiet piekļuvi šai atļaujai."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju straumēt lietotnes un citas sistēmas funkcijas starp jūsu ierīcēm šīs ierīces vārdā: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>."</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"ierīce"</string> <string name="summary_generic" msgid="1761976003668044801">"Šī lietotne varēs sinhronizēt informāciju (piemēram, zvanītāja vārdu) starp jūsu tālruni un izvēlēto ierīci"</string> <string name="consent_yes" msgid="8344487259618762872">"Atļaut"</string> diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml index 219f9d14f64c..c0e48b32b1a5 100644 --- a/packages/CompanionDeviceManager/res/values-mk/strings.xml +++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Ќе дозволите <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да управува со <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"уред"</string> <string name="summary_glasses" msgid="5469208629679579157">"Апликацијава ќе може да пристапува до овие дозволи на <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Да се дозволи <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да ги стримува апликациите од <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> на <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ќе има пристап до сè што е видливо или репродуцирано на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, including вклучувајќи ги и аудиото, фотографиите, лозинките и пораките.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> ќе може да стримува апликации на <xliff:g id="DEVICE_NAME">%3$s</xliff:g> додека не ја повлечете дозволава."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_NAME">%2$s</xliff:g> за да прикажува и стримува апликации меѓу вашите уреди"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Дозволете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да пристапува до овие податоци на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_NAME">%2$s</xliff:g> за да пристапува до фотографиите, аудиовизуелните содржини и известувањата на <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Да се дозволи <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> да ги стримува апликациите и системските функции од <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> на <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ќе има пристап до сè што е видливо или репродуцирано на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, вклучувајќи ги и аудиото, фотографиите, податоците за плаќање, лозинките и пораките.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> ќе може да стримува апликации и системски функции на <xliff:g id="DEVICE_NAME">%3$s</xliff:g> додека не ја повлечете дозволава."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_NAME">%2$s</xliff:g> за да стримува апликации и други системски функции на вашите уреди"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"уред"</string> <string name="summary_generic" msgid="1761976003668044801">"Оваа апликација ќе може да ги синхронизира податоците како што се имињата на јавувачите помеѓу вашиот телефон и избраниот уред"</string> <string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string> diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml index 199f7827c82a..2439adc48bb8 100644 --- a/packages/CompanionDeviceManager/res/values-ml/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ml/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>? മാനേജ് ചെയ്യാൻ, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> എന്നതിനെ അനുവദിക്കുക"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"ഉപകരണം"</string> <string name="summary_glasses" msgid="5469208629679579157">"നിങ്ങളുടെ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> എന്നതിൽ ഇനിപ്പറയുന്ന അനുമതികൾ ആക്സസ് ചെയ്യാൻ ഈ ആപ്പിനെ അനുവദിക്കും"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"നിങ്ങളുടെ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> എന്നതിന്റെ ആപ്പുകൾ <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> എന്നതിലേക്ക് സ്ട്രീം ചെയ്യാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> എന്നതിനെ അനുവദിക്കണോ?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"ഓഡിയോ, ഫോട്ടോകൾ, പാസ്വേഡുകൾ, സന്ദേശങ്ങൾ എന്നിവ ഉൾപ്പെടെ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> എന്നതിൽ ദൃശ്യമാകുന്നതോ പ്ലേ ചെയ്യുന്നതോ എല്ലാ എല്ലാത്തിലേക്കും <xliff:g id="APP_NAME_0">%1$s</xliff:g> എന്നതിന് ആക്സസ് ഉണ്ടായിരിക്കും.<br/><br/>നിങ്ങൾ ഈ അനുമതിയിലേക്കുള്ള ആക്സസ് നീക്കം ചെയ്യുന്നത് വരെ <xliff:g id="APP_NAME_1">%1$s</xliff:g> എന്നതിന് <xliff:g id="DEVICE_NAME">%3$s</xliff:g> എന്നതിലേക്ക് ആപ്പുകൾ സ്ട്രീം ചെയ്യാനാകും."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"നിങ്ങളുടെ ഉപകരണങ്ങൾക്കിടയിൽ ആപ്പുകൾ സ്ട്രീം ചെയ്യാനും പ്രദർശിപ്പിക്കാനും നിങ്ങളുടെ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> എന്ന ഉപകരണത്തിന് വേണ്ടി <xliff:g id="APP_NAME">%1$s</xliff:g> അനുമതി അഭ്യർത്ഥിക്കുന്നു"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"നിങ്ങളുടെ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> എന്നതിൽ നിന്ന് ഈ വിവരങ്ങൾ ആക്സസ് ചെയ്യാൻ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> എന്നതിനെ അനുവദിക്കുക"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"നിങ്ങളുടെ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> എന്നതിലെ ഫോട്ടോകൾ, മീഡിയ, അറിയിപ്പുകൾ എന്നിവ ആക്സസ് ചെയ്യാൻ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> എന്ന ഉപകരണത്തിന് വേണ്ടി <xliff:g id="APP_NAME">%1$s</xliff:g> അനുമതി അഭ്യർത്ഥിക്കുന്നു"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"നിങ്ങളുടെ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> എന്നതിന്റെ ആപ്പുകളും സിസ്റ്റം ഫീച്ചറുകളും <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> എന്നതിലേക്ക് സ്ട്രീം ചെയ്യാൻ <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> എന്നതിനെ അനുവദിക്കണോ?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"ഓഡിയോ, ഫോട്ടോകൾ, പാസ്വേഡുകൾ, സന്ദേശങ്ങൾ എന്നിവ ഉൾപ്പെടെ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> എന്നതിൽ ദൃശ്യമാകുന്നതോ പ്ലേ ചെയ്യുന്നതോ എല്ലാ എല്ലാത്തിലേക്കും <xliff:g id="APP_NAME_0">%1$s</xliff:g> എന്നതിന് ആക്സസ് ഉണ്ടായിരിക്കും.<br/><br/>നിങ്ങൾ ഈ അനുമതിയിലേക്കുള്ള ആക്സസ് നീക്കം ചെയ്യുന്നത് വരെ <xliff:g id="APP_NAME_1">%1$s</xliff:g> എന്നതിന് <xliff:g id="DEVICE_NAME">%3$s</xliff:g> എന്നതിലേക്ക് ആപ്പുകളും മറ്റ് സിസ്റ്റം ഫീച്ചറുകളും സ്ട്രീം ചെയ്യാനാകും."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"നിങ്ങളുടെ ഉപകരണങ്ങളിൽ ഒന്നിൽ നിന്ന് അടുത്തതിലേക്ക് ആപ്പുകളും മറ്റ് സിസ്റ്റം ഫീച്ചറുകളും സ്ട്രീം ചെയ്യാൻ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> എന്ന ഉപകരണത്തിന് വേണ്ടി <xliff:g id="APP_NAME">%1$s</xliff:g> എന്നത് അനുമതി അഭ്യർത്ഥിക്കുന്നു"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"ഉപകരണം"</string> <string name="summary_generic" msgid="1761976003668044801">"വിളിക്കുന്നയാളുടെ പേര് പോലുള്ള വിവരങ്ങൾ നിങ്ങളുടെ ഫോണിനും തിരഞ്ഞെടുത്ത ഉപകരണത്തിനും ഇടയിൽ സമന്വയിപ്പിക്കുന്നതിന് ഈ ആപ്പിന് കഴിയും"</string> <string name="consent_yes" msgid="8344487259618762872">"അനുവദിക്കുക"</string> diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml index 94f862c08e78..543bdfa03eed 100644 --- a/packages/CompanionDeviceManager/res/values-mn/strings.xml +++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-г удирдахыг зөвшөөрөх үү?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"төхөөрөмж"</string> <string name="summary_glasses" msgid="5469208629679579157">"Энэ аппад таны <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> дээрх эдгээр зөвшөөрөлд хандахыг зөвшөөрнө"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н аппуудыг <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>-д дамжуулахыг зөвшөөрөх үү?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> аудио, зураг, нууц үг, мессеж зэрэг <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> дээр харагдаж эсвэл тоглуулж буй аливаа зүйлд хандах эрхтэй болно.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> таныг энэ зөвшөөрлийн хандалтыг хасах хүртэл <xliff:g id="DEVICE_NAME">%3$s</xliff:g>-д апп дамжуулах боломжтой байх болно."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-н өмнөөс таны төхөөрөмжүүдийн хооронд апп үзүүлж, дамжуулах зөвшөөрлийг хүсэж байна"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н энэ мэдээлэлд хандахыг зөвшөөрнө үү"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-н өмнөөс <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>-н зураг, медиа, мэдэгдэлд хандах зөвшөөрлийг хүсэж байна"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong>-д таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н апп болон системийн онцлогуудыг <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>-д дамжуулахыг зөвшөөрөх үү?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> аудио, зураг, төлбөрийн мэдээлэл, нууц үг, мессеж зэрэг таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> дээр харагдаж эсвэл тоглуулж буй аливаа зүйлд хандах эрхтэй байх болно.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> таныг энэ зөвшөөрлийн хандалтыг хасах хүртэл <xliff:g id="DEVICE_NAME">%3$s</xliff:g>-д апп болон системийн онцлогуудыг дамжуулах боломжтой байх болно."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-н өмнөөс таны төхөөрөмжүүдийн хооронд апп болон системийн бусад онцлогийг дамжуулах зөвшөөрлийг хүсэж байна"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"төхөөрөмж"</string> <string name="summary_generic" msgid="1761976003668044801">"Энэ апп залгаж буй хүний нэр зэрэг мэдээллийг таны утас болон сонгосон төхөөрөмжийн хооронд синк хийх боломжтой болно"</string> <string name="consent_yes" msgid="8344487259618762872">"Зөвшөөрөх"</string> diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml index c758d29871bd..6a7e10ef8212 100644 --- a/packages/CompanionDeviceManager/res/values-mr/strings.xml +++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> व्यवस्थापित करण्याची अनुमती द्यायची आहे?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"डिव्हाइस"</string> <string name="summary_glasses" msgid="5469208629679579157">"या अॅपला तुमच्या <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> वर या परवानग्या अॅक्सेस करण्याची अनुमती दिली जाईल"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> अॅप्स <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>वर स्ट्रीम करण्याची अनुमती द्यायची आहे का?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ला ऑडिओ, फोटो, पासवर्ड आणि मेसेज यांसह <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> वर दिसणाऱ्या किंवा प्ले होणाऱ्या सर्व गोष्टींचा अॅक्सेस असेल.<br/><br/>तुम्ही या परवानगीचा अॅक्सेस काढून टाकेपर्यंत <xliff:g id="APP_NAME_1">%1$s</xliff:g> हे <xliff:g id="DEVICE_NAME">%3$s</xliff:g> वर ॲप्स स्ट्रीम करू शकेल."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"तुमच्या डिव्हाइसदरम्यान ॲप्स दाखवण्यासाठी आणि स्ट्रीम करण्यासाठी <xliff:g id="APP_NAME">%1$s</xliff:g> हे तुमच्या <xliff:g id="DEVICE_NAME">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला ही माहिती तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> वरून अॅक्सेस करण्यासाठी अनुमती द्या"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"तुमच्या <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> मधील फोटो, मीडिया आणि नोटिफिकेशन अॅक्सेस करण्यासाठी <xliff:g id="APP_NAME">%1$s</xliff:g> हे तुमच्या <xliff:g id="DEVICE_NAME">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> ला तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> अॅप्स आणि सिस्टीमची वैशिष्ट्ये <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>वर स्ट्रीम करण्याची अनुमती द्यायची आहे का?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ला ऑडिओ, फोटो, पेमेंट माहिती, पासवर्ड आणि मेसेज यांसह तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> वर दिसणाऱ्या किंवा प्ले होणाऱ्या सर्व गोष्टींचा अॅक्सेस असेल.<br/><br/>तुम्ही या परवानगीचा अॅक्सेस काढून टाकेपर्यंत <xliff:g id="APP_NAME_1">%1$s</xliff:g> हे ॲप्स आणि सिस्टीमची वैशिष्ट्ये <xliff:g id="DEVICE_NAME">%3$s</xliff:g> वर स्ट्रीम करू शकेल."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"तुमच्या डिव्हाइसदरम्यान ॲप्स आणि इतर सिस्टीम वैशिष्ट्ये स्ट्रीम करण्यासाठी <xliff:g id="APP_NAME">%1$s</xliff:g> हे तुमच्या <xliff:g id="DEVICE_NAME">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"डिव्हाइस"</string> <string name="summary_generic" msgid="1761976003668044801">"हे ॲप तुमचा फोन आणि निवडलेल्या डिव्हाइसदरम्यान कॉल करत असलेल्या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करू शकेल"</string> <string name="consent_yes" msgid="8344487259618762872">"अनुमती द्या"</string> diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml index 424b815b5ce3..13916b7c84ab 100644 --- a/packages/CompanionDeviceManager/res/values-ms/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml @@ -25,17 +25,17 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> mengurus <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"peranti"</string> <string name="summary_glasses" msgid="5469208629679579157">"Apl ini akan dibenarkan untuk mengakses kebenaran yang berikut pada <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> anda"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk menstrim apl <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda kepada <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> akan mendapat akses kepada semua perkara yang dipaparkan atau dimainkan pada <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, termasuk audio, foto, kata laluan dan mesej.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> akan dapat menstrim apl kepada <xliff:g id="DEVICE_NAME">%3$s</xliff:g> sehingga anda mengalih keluar akses kepada kebenaran ini."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta kebenaran bagi pihak <xliff:g id="DEVICE_NAME">%2$s</xliff:g> anda untuk memaparkan dan menstrim apl antara peranti anda"</string> + <string name="title_app_streaming" msgid="1047090167914857893">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk menstrim apl dan ciri sistem <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda kepada <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> + <string name="summary_app_streaming" msgid="7990244299655610920">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> akan mendapat akses kepada semua perkara yang dipaparkan atau dimainkan pada <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda, termasuk audio, foto, maklumat pembayaran, kata laluan dan mesej.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> akan dapat menstrim apl kepada <xliff:g id="DEVICE_NAME">%3$s</xliff:g> sehingga anda mengalih keluar akses kepada kebenaran ini."</string> + <string name="helper_summary_app_streaming" msgid="1872657107404139828">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta kebenaran bagi pihak <xliff:g id="DEVICE_NAME">%2$s</xliff:g> untuk menstrim apl dan ciri sistem daripada <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> anda"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk mengakses maklumat ini daripada <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang meminta kebenaran bagi pihak <xliff:g id="DEVICE_NAME">%2$s</xliff:g> anda untuk mengakses foto, media dan pemberitahuan <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> anda"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Benarkan <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> untuk menstrim apl dan ciri sistem <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda kepada <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> akan mendapat akses kepada semua perkara yang dipaparkan atau dimainkan pada <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda, termasuk audio, foto, maklumat pembayaran, kata laluan dan mesej.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> akan dapat menstrim apl dan ciri sistem kepada <xliff:g id="DEVICE_NAME">%3$s</xliff:g> sehingga anda mengalih keluar akses kepada kebenaran ini."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang meminta kebenaran bagi pihak <xliff:g id="DEVICE_NAME">%2$s</xliff:g> anda untuk menstrim apl dan ciri sistem lain antara peranti anda"</string> + <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk menstrim apl <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda kepada <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> + <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> akan mendapat akses kepada semua perkara yang dipaparkan atau dimainkan pada <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, termasuk audio, foto, maklumat pembayaran, kata laluan dan mesej.<br/><br/><xliff:g id="APP_NAME_2">%1$s</xliff:g> akan dapat menstrim apl kepada <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> sehingga anda mengalih keluar akses kepada kebenaran ini."</string> + <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta kebenaran bagi pihak <xliff:g id="DEVICE_NAME">%2$s</xliff:g> untuk menstrim apl daripada <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> anda"</string> <string name="profile_name_generic" msgid="6851028682723034988">"peranti"</string> <string name="summary_generic" msgid="1761976003668044801">"Apl ini akan dapat menyegerakkan maklumat seperti nama individu yang memanggil, antara telefon anda dengan peranti yang dipilih"</string> <string name="consent_yes" msgid="8344487259618762872">"Benarkan"</string> diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml index 6185f314111c..dea62f69fa9c 100644 --- a/packages/CompanionDeviceManager/res/values-my/strings.xml +++ b/packages/CompanionDeviceManager/res/values-my/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ကို <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> အား စီမံခွင့်ပြုမလား။"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"စက်"</string> <string name="summary_glasses" msgid="5469208629679579157">"သင့် <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> တွင် ၎င်းခွင့်ပြုချက်များရယူရန် ဤအက်ပ်ကိုခွင့်ပြုမည်"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> အား သင့် <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ၏ အက်ပ်များကို <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> တွင် တိုက်ရိုက်ဖွင့်ခွင့်ပြုမလား။"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> သည် အသံ၊ ဓာတ်ပုံ၊ စကားဝှက်နှင့် မက်ဆေ့ဂျ်များအပါအဝင် <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> တွင် မြင်နိုင်သော (သို့) ဖွင့်ထားသော အရာအားလုံးကို သုံးခွင့်ရှိပါမည်။<br/><br/>ဤခွင့်ပြုချက်သုံးခွင့်ကို သင်မဖယ်ရှားမချင်း <xliff:g id="APP_NAME_1">%1$s</xliff:g> သည် အက်ပ်များကို <xliff:g id="DEVICE_NAME">%3$s</xliff:g> တွင် တိုက်ရိုက်ဖွင့်နိုင်ပါမည်။"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် သင့်စက်များအကြား အက်ပ်များ ပြပြီး တိုက်ရိုက်ဖွင့်ရန် <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ကိုယ်စား ခွင့်ပြုချက်တောင်းနေသည်"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> အား သင့် <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> မှ ဤအချက်အလက်ကို သုံးခွင့်ပြုမည်"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် သင့် <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> ၏ ဓာတ်ပုံ၊ မီဒီယာနှင့် အကြောင်းကြားချက်များသုံးရန် <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ကိုယ်စား ခွင့်ပြုချက်တောင်းနေသည်"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> အား သင့် <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ၏ အက်ပ်နှင့် စနစ်တူးလ်များကို <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> တွင် တိုက်ရိုက်ဖွင့်ခွင့်ပြုမလား။"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> သည် အသံ၊ ဓာတ်ပုံ၊ ငွေချေအချက်အလက်၊ စကားဝှက်နှင့် မက်ဆေ့ဂျ်များအပါအဝင် သင့် <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> တွင် မြင်နိုင်သော (သို့) ဖွင့်ထားသော အရာအားလုံးကို သုံးခွင့်ရှိပါမည်။<br/><br/>ဤခွင့်ပြုချက်သုံးခွင့်ကို သင်မဖယ်ရှားမချင်း <xliff:g id="APP_NAME_1">%1$s</xliff:g> သည် အက်ပ်နှင့် စနစ်တူးလ်များကို <xliff:g id="DEVICE_NAME">%3$s</xliff:g> တွင် တိုက်ရိုက်ဖွင့်နိုင်ပါမည်။"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် သင့်စက်များအကြား အက်ပ်နှင့် အခြားစနစ်တူးလ်များ တိုက်ရိုက်ဖွင့်ရန် <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ကိုယ်စား ခွင့်ပြုချက်တောင်းနေသည်"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"စက်"</string> <string name="summary_generic" msgid="1761976003668044801">"ဤအက်ပ်သည် သင့်ဖုန်းနှင့် ရွေးထားသောစက်အကြား ခေါ်ဆိုသူ၏အမည်ကဲ့သို့ အချက်အလက်ကို စင့်ခ်လုပ်နိုင်ပါမည်"</string> <string name="consent_yes" msgid="8344487259618762872">"ခွင့်ပြုရန်"</string> @@ -61,7 +67,7 @@ <string name="permission_call_logs_summary" msgid="7545243592757693321">"ဖုန်းခေါ်ဆိုမှတ်တမ်းကို ဖတ်နိုင်၊ ရေးနိုင်သည်"</string> <string name="permission_sms_summary" msgid="8499509535410068616">"SMS မက်ဆေ့ဂျ်များ ပို့နိုင်၊ ကြည့်နိုင်သည်"</string> <string name="permission_contacts_summary" msgid="2840800622763086808">"သင့်အဆက်အသွယ်များကို ဝင်ကြည့်နိုင်သည်"</string> - <string name="permission_calendar_summary" msgid="8430353935747336165">"သင့်ပြက္ခဒိန်ကို ဝင်ကြည့်နိုင်သည်"</string> + <string name="permission_calendar_summary" msgid="8430353935747336165">"သင့်ပြက္ခဒိန်အား ဝင်သုံးနိုင်သည်"</string> <string name="permission_microphone_summary" msgid="4862628553869973259">"အသံသွင်းနိုင်သည်"</string> <string name="permission_nearby_devices_summary" msgid="1306752848196464817">"အနီးတစ်ဝိုက်ရှိ စက်များ၏ ဆက်စပ်နေရာကို ရှာခြင်း၊ ချိတ်ဆက်ခြင်းနှင့် သတ်မှတ်ခြင်းတို့ လုပ်နိုင်သည်"</string> <string name="permission_notification_listener_access_summary" msgid="7856071768185367749">"အဆက်အသွယ်၊ မက်ဆေ့ဂျ်နှင့် ဓာတ်ပုံများကဲ့သို့ အချက်အလက်များအပါအဝင် အကြောင်းကြားချက်အားလုံးကို ဖတ်နိုင်သည်"</string> diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml index 00700ec7f97e..9a40b6bb3d32 100644 --- a/packages/CompanionDeviceManager/res/values-nb/strings.xml +++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Vil du la <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> administrere <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"enheten"</string> <string name="summary_glasses" msgid="5469208629679579157">"Denne appen får disse tillatelsene på <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Vil du la <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> strømme apper fra <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får tilgang til alt som vises eller spilles av på <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, inkludert lyd, bilder, passord og meldinger.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> får muligheten til å strømme apper til <xliff:g id="DEVICE_NAME">%3$s</xliff:g> frem til du fjerner tilgangen til denne tillatelsen."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse til å vise og strømme apper mellom enhetene dine, på vegne av <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Vil du gi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilgang til denne informasjonen fra <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>?"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tilgang til bilder, medieinnhold og varsler fra <xliff:g id="DEVICE_NAME">%2$s</xliff:g> på vegne av <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Vil du la <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> strømme apper og systemfunksjoner fra <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får tilgang til alt som vises eller spilles av på <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, inkludert lyd, bilder, betalingsopplysninger, passord og meldinger.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> får muligheten til å strømme apper og systemfunksjoner til <xliff:g id="DEVICE_NAME">%3$s</xliff:g> frem til du fjerner tilgangen til denne tillatelsen."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse til å strømme apper og andre systemfunksjoner mellom enhetene dine på vegne av <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string> <string name="summary_generic" msgid="1761976003668044801">"Denne appen kan synkronisere informasjon som navnet til noen som ringer, mellom telefonen og den valgte enheten"</string> <string name="consent_yes" msgid="8344487259618762872">"Tillat"</string> diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml index 1af4d85f905a..fdd011b4e4a6 100644 --- a/packages/CompanionDeviceManager/res/values-ne/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ne/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> लाई <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> व्यवस्थापन गर्ने अनुमति दिने हो?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"डिभाइस"</string> <string name="summary_glasses" msgid="5469208629679579157">"तपाईंको <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> मा यो एपलाई निम्न अनुमति दिइने छ:"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> लाई तपाईंको <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> मा भएका एपहरू <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> मा स्ट्रिम गर्न दिने हो?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ले तपाईंको <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> मा देखिने वा प्ले गरिने अडियो, फोटो, पासवर्ड र म्यासेजलगायतका सबै कुरा एक्सेस गर्न सक्ने छ।<br/><br/>तपाईंले यो अनुमति रद्द नगरेसम्म <xliff:g id="APP_NAME_1">%1$s</xliff:g> ले एपहरू <xliff:g id="DEVICE_NAME">%3$s</xliff:g> मा स्ट्रिम गर्न पाइराख्ने छ।"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> तपाईंको डिभाइस <xliff:g id="DEVICE_NAME">%2$s</xliff:g> को तर्फबाट तपाईंका कुनै एउटा डिभाइसबाट अर्को डिभाइसमा एप देखाउने तथा स्ट्रिम गर्ने अनुमति माग्दै छ"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> लाई तपाईंको <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> मा भएको यो जानकारी एक्सेस गर्ने अनुमति दिनुहोस्"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> तपाईंको डिभाइस <xliff:g id="DEVICE_NAME">%2$s</xliff:g> को तर्फबाट तपाईंको <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> मा भएका फोटो, मिडिया र सूचनाहरू एक्सेस गर्ने अनुमति माग्दै छ"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> लाई तपाईंको <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> मा भएका एप तथा सिस्टमका सुविधाहरू <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> मा स्ट्रिम गर्न दिने हो?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ले तपाईंको <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> मा देखिने वा प्ले गरिने अडियो, फोटो, भुक्तानीसम्बन्धी जानकारी, पासवर्ड र म्यासेजलगायतका सबै कुरा एक्सेस गर्न सक्ने छ।<br/><br/>तपाईंले यो अनुमति रद्द नगरेसम्म <xliff:g id="APP_NAME_1">%1$s</xliff:g> ले एप तथा सिस्टमका सुविधाहरू <xliff:g id="DEVICE_NAME">%3$s</xliff:g> मा स्ट्रिम गर्न पाइराख्ने छ।"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> तपाईंको डिभाइस <xliff:g id="DEVICE_NAME">%2$s</xliff:g> को तर्फबाट तपाईंका कुनै एउटा डिभाइसबाट अर्को डिभाइसमा एप र सिस्टमका अन्य सुविधाहरूमा स्ट्रिम गर्ने अनुमति माग्दै छ"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"यन्त्र"</string> <string name="summary_generic" msgid="1761976003668044801">"यो एपले तपाईंको फोन र तपाईंले छनौट गर्ने डिभाइसका बिचमा कल गर्ने व्यक्तिको नाम जस्ता जानकारी सिंक गर्न सक्ने छ।"</string> <string name="consent_yes" msgid="8344487259618762872">"अनुमति दिनुहोस्"</string> diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml index ad1cfe0d0b1b..d71e8c16f182 100644 --- a/packages/CompanionDeviceManager/res/values-nl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toestaan <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> te beheren?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"apparaat"</string> <string name="summary_glasses" msgid="5469208629679579157">"Deze app krijgt toegang tot deze rechten op je <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toestaan om apps van je <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> naar <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> te streamen?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> krijgt toegang tot alles wat zichtbaar is of wordt afgespeeld op je <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, waaronder audio, foto\'s, wachtwoorden en berichten.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> kan apps naar <xliff:g id="DEVICE_NAME">%3$s</xliff:g> streamen totdat je dit recht verwijdert."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens jouw <xliff:g id="DEVICE_NAME">%2$s</xliff:g> toestemming om apps tussen je apparaten weer te geven en te streamen"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang geven tot deze informatie op je <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>?"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens jouw <xliff:g id="DEVICE_NAME">%2$s</xliff:g> toegang tot de foto\'s, media en meldingen van je <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> toestaan om apps en systeemfuncties van je <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> naar <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> te streamen?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> krijgt toegang tot alles wat zichtbaar is of wordt afgespeeld op je <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, waaronder audio, foto\'s, betalingsgegevens, wachtwoorden en berichten.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> kan apps en systeemfuncties naar <xliff:g id="DEVICE_NAME">%3$s</xliff:g> streamen totdat je dit recht verwijdert."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens jouw <xliff:g id="DEVICE_NAME">%2$s</xliff:g> toestemming om apps en andere systeemfuncties te streamen tussen je apparaten"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"apparaat"</string> <string name="summary_generic" msgid="1761976003668044801">"Deze app kan informatie, zoals de naam van iemand die belt, synchroniseren tussen je telefoon en het gekozen apparaat"</string> <string name="consent_yes" msgid="8344487259618762872">"Toestaan"</string> diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml index 58c64768dd21..1e8ed0bbb661 100644 --- a/packages/CompanionDeviceManager/res/values-or/strings.xml +++ b/packages/CompanionDeviceManager/res/values-or/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>କୁ ପରିଚାଳନା କରିବା ପାଇଁ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ଅନୁମତି ଦେବେ?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"ଡିଭାଇସ"</string> <string name="summary_glasses" msgid="5469208629679579157">"ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>ରେ ଏହି ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଏହି ଆପକୁ ଅନୁମତି ଦିଆଯିବ"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ର ଆପ୍ସକୁ <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>ରେ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ଅନୁମତି ଦେବେ?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"ଅଡିଓ, ଫଟୋ, ପାସୱାର୍ଡ ଏବଂ ମେସେଜ ସମେତ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ <xliff:g id="APP_NAME_0">%1$s</xliff:g>ର ଆକ୍ସେସ ରହିବ।<br/><br/>ଆପଣ ଏହି ଅନୁମତିକୁ ଆକ୍ସେସ କାଢ଼ି ନଦେବା ପର୍ଯ୍ୟନ୍ତ <xliff:g id="APP_NAME_1">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%3$s</xliff:g>ରେ ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ ସକ୍ଷମ ହେବ।"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"ଆପଣଙ୍କ ଡିଭାଇସଗୁଡ଼ିକ ମଧ୍ୟରେ ଆପ୍ସକୁ ଡିସପ୍ଲେ ଏବଂ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କର <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ରୁ ଏହି ସୂଚନାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>ର ଫଟୋ, ମିଡିଆ ଏବଂ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କର <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ର ଆପ୍ସ ଏବଂ ସିଷ୍ଟମ ଫିଚରଗୁଡ଼ିକୁ <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>ରେ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong>କୁ ଅନୁମତି ଦେବେ?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"ଅଡିଓ, ଫଟୋ, ପେମେଣ୍ଟ ସୂଚନା, ପାସୱାର୍ଡ ଏବଂ ମେସେଜ ସମେତ ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ <xliff:g id="APP_NAME_0">%1$s</xliff:g>ର ଆକ୍ସେସ ରହିବ।<br/><br/>ଆପଣ ଏହି ଅନୁମତିକୁ ଆକ୍ସେସ କାଢ଼ି ନଦେବା ପର୍ଯ୍ୟନ୍ତ <xliff:g id="APP_NAME_1">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%3$s</xliff:g>ରେ ଆପ୍ସ ଏବଂ ସିଷ୍ଟମ ଫିଚରଗୁଡ଼ିକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ ସକ୍ଷମ ହେବ।"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"ଆପଣଙ୍କ ଡିଭାଇସଗୁଡ଼ିକ ମଧ୍ୟରେ ଆପ୍ସ ଏବଂ ଅନ୍ୟ ସିଷ୍ଟମ ଫିଚରଗୁଡ଼ିକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କର <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"ଡିଭାଇସ୍"</string> <string name="summary_generic" msgid="1761976003668044801">"ଆପଣଙ୍କ ଫୋନ ଏବଂ ବଛାଯାଇଥିବା ଡିଭାଇସ ମଧ୍ୟରେ, କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବାକୁ ଏହି ଆପ ସକ୍ଷମ ହେବ"</string> <string name="consent_yes" msgid="8344487259618762872">"ଅନୁମତି ଦିଅନ୍ତୁ"</string> diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml index d80c667c1ed2..94a858496f76 100644 --- a/packages/CompanionDeviceManager/res/values-pa/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"ਕੀ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"ਡੀਵਾਈਸ"</string> <string name="summary_glasses" msgid="5469208629679579157">"ਇਸ ਐਪ ਨੂੰ ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> \'ਤੇ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"ਕੀ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ਦੀਆਂ ਐਪਾਂ ਨੂੰ <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> \'ਤੇ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ਕੋਲ ਆਡੀਓ, ਫ਼ੋਟੋਆਂ, ਪਾਸਵਰਡਾਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਸਮੇਤ, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> \'ਤੇ ਦਿਖਾਈ ਦੇਣ ਵਾਲੀ ਜਾਂ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ।<br/><br/>ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਤੱਕ ਪਹੁੰਚ ਨੂੰ ਹਟਾ ਨਹੀਂ ਦਿੰਦੇ, ਉਦੋਂ ਤੱਕ <xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%3$s</xliff:g> \'ਤੇ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰ ਸਕੇਗੀ।"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਐਪਾਂ ਨੂੰ ਦਿਖਾਉਣ ਅਤੇ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਤੋਂ ਇਸ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> ਦੀਆਂ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਸੂਚਨਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"ਕੀ <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਦੀਆਂ ਐਪਾਂ ਨੂੰ <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> \'ਤੇ ਸਟ੍ਰੀਮ ਕਰਨ ਅਤੇ ਸਿਸਟਮ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ਕੋਲ ਆਡੀਓ, ਫ਼ੋਟੋਆਂ, ਪਾਸਵਰਡਾਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਸਮੇਤ ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> \'ਤੇ ਦਿਖਾਈ ਦੇਣ ਵਾਲੀ ਜਾਂ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ।<br/><br/>ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਤੱਕ ਪਹੁੰਚ ਨੂੰ ਹਟਾ ਨਹੀਂ ਦਿੰਦੇ, ਉਦੋਂ ਤੱਕ <xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%3$s</xliff:g> \'ਤੇ ਐਪਾਂ ਅਤੇ ਸਿਸਟਮ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰ ਸਕੇਗੀ।"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਐਪਾਂ ਅਤੇ ਹੋਰ ਸਿਸਟਮ ਸੰਬੰਧੀ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"ਡੀਵਾਈਸ"</string> <string name="summary_generic" msgid="1761976003668044801">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ ਅਤੇ ਚੁਣੇ ਗਏ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰ ਸਕੇਗੀ"</string> <string name="consent_yes" msgid="8344487259618762872">"ਆਗਿਆ ਦਿਓ"</string> diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml index 42a05b4fd2aa..949957dae84e 100644 --- a/packages/CompanionDeviceManager/res/values-pl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Zezwolić na dostęp aplikacji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> do urządzenia <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"urządzenie"</string> <string name="summary_glasses" msgid="5469208629679579157">"Aplikacja będzie miała dostęp do tych uprawnień na Twoim urządzeniu (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Zezwolić aplikacji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na strumieniowanie aplikacji na <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na urządzenie <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"Aplikacja <xliff:g id="APP_NAME_0">%1$s</xliff:g> będzie miała dostęp do wszystkiego, co jest widoczne i odtwarzane na <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, w tym do dźwięku, zdjęć, haseł i wiadomości.<br/><br/>Aplikacja <xliff:g id="APP_NAME_1">%1$s</xliff:g> będzie mogła strumieniować aplikacje na urządzenie <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, dopóki nie usuniesz dostępu do tego uprawnienia."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_NAME">%2$s</xliff:g> o pozwolenie na wyświetlanie i strumieniowanie aplikacji między Twoimi urządzeniami"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Zezwól aplikacji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na dostęp do tych informacji na Twoim <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_NAME">%2$s</xliff:g> o uprawnienia dotyczące dostępu do zdjęć, multimediów i powiadomień na <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Zezwolić aplikacji <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> na strumieniowanie aplikacji i funkcji systemowych na <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na urządzenie <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"Aplikacja <xliff:g id="APP_NAME_0">%1$s</xliff:g> będzie miała dostęp do wszystkiego, co jest widoczne i odtwarzane na <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, w tym do dźwięku, zdjęć, danych do płatności, haseł i wiadomości.<br/><br/>Aplikacja <xliff:g id="APP_NAME_1">%1$s</xliff:g> będzie mogła strumieniować aplikacje i funkcje systemowe na urządzenie <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, dopóki nie usuniesz dostępu do tego uprawnienia."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_NAME">%2$s</xliff:g> o pozwolenie na strumieniowanie aplikacji i innych funkcji systemowych między Twoimi urządzeniami"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"urządzenie"</string> <string name="summary_generic" msgid="1761976003668044801">"Ta aplikacja może synchronizować informacje takie jak imię i nazwisko osoby dzwoniącej między Twoim telefonem i wybranym urządzeniem"</string> <string name="consent_yes" msgid="8344487259618762872">"Zezwól"</string> diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml index 1ef96354e460..cce096871838 100644 --- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gerencie o dispositivo <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string> <string name="summary_glasses" msgid="5469208629679579157">"O app poderá acessar estas permissões no seu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> faça streaming dos aplicativos do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para o <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> terá acesso a tudo que estiver visível ou for aberto no <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, incluindo áudios, fotos, senhas e mensagens.<br/><br/>O app <xliff:g id="APP_NAME_1">%1$s</xliff:g> poderá fazer streaming de aplicativos para o <xliff:g id="DEVICE_NAME">%3$s</xliff:g> até que você remova o acesso a essa permissão."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para mostrar e fazer streaming de apps entre seus dispositivos"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acesse essas informações do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para acessar fotos, mídia e notificações do seu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Permitir que <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> faça streaming dos apps e recursos do sistema do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para o <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> terá acesso a tudo que estiver visível ou for aberto no <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, incluindo áudios, fotos, informações de pagamento, senhas e mensagens.<br/><br/>O app <xliff:g id="APP_NAME_1">%1$s</xliff:g> poderá fazer streaming de aplicativos e recursos do sistema para o <xliff:g id="DEVICE_NAME">%3$s</xliff:g> até que você remova o acesso a essa permissão."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer streaming de aplicativos e outros recursos do sistema entre seus dispositivos"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="1761976003668044801">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo escolhido"</string> <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string> diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml index 8a464e3804d6..1443b137a9a6 100644 --- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> faça a gestão do dispositivo <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string> <string name="summary_glasses" msgid="5469208629679579157">"Esta app vai poder aceder a estas autorizações no seu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Permitir que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> faça stream das apps do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>para o dispositivo <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"A app <xliff:g id="APP_NAME_0">%1$s</xliff:g> vai ter acesso a tudo o que seja visível ou reproduzido no dispositivo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, incluindo áudio, fotos, palavras-passe e mensagens.<br/><br/>A app <xliff:g id="APP_NAME_1">%1$s</xliff:g> vai poder fazer stream de apps para o dispositivo <xliff:g id="DEVICE_NAME">%3$s</xliff:g> até remover o acesso a esta autorização."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para apresentar e fazer stream de apps entre os seus dispositivos"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aceda a estas informações do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para aceder às fotos, ao conteúdo multimédia e às notificações do seu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Permitir que o dispositivo <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> faça stream das apps e funcionalidades do sistema do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para o dispositivo <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"A app <xliff:g id="APP_NAME_0">%1$s</xliff:g> vai ter acesso a tudo o que seja visível ou reproduzido no seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, incluindo áudio, fotos, informações de pagamento, palavras-passe e mensagens.<br/><br/>A app <xliff:g id="APP_NAME_1">%1$s</xliff:g> vai poder fazer stream de apps e funcionalidades do sistema para o dispositivo <xliff:g id="DEVICE_NAME">%3$s</xliff:g> até remover o acesso a esta autorização."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer stream de apps e outras funcionalidades do sistema entre os seus dispositivos"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="1761976003668044801">"Esta app vai poder sincronizar informações, como o nome do autor de uma chamada, entre o telemóvel e o dispositivo escolhido"</string> <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string> diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml index 1ef96354e460..cce096871838 100644 --- a/packages/CompanionDeviceManager/res/values-pt/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gerencie o dispositivo <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"dispositivo"</string> <string name="summary_glasses" msgid="5469208629679579157">"O app poderá acessar estas permissões no seu <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> faça streaming dos aplicativos do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para o <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> terá acesso a tudo que estiver visível ou for aberto no <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, incluindo áudios, fotos, senhas e mensagens.<br/><br/>O app <xliff:g id="APP_NAME_1">%1$s</xliff:g> poderá fazer streaming de aplicativos para o <xliff:g id="DEVICE_NAME">%3$s</xliff:g> até que você remova o acesso a essa permissão."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para mostrar e fazer streaming de apps entre seus dispositivos"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Permitir que o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acesse essas informações do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para acessar fotos, mídia e notificações do seu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Permitir que <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> faça streaming dos apps e recursos do sistema do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para o <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> terá acesso a tudo que estiver visível ou for aberto no <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, incluindo áudios, fotos, informações de pagamento, senhas e mensagens.<br/><br/>O app <xliff:g id="APP_NAME_1">%1$s</xliff:g> poderá fazer streaming de aplicativos e recursos do sistema para o <xliff:g id="DEVICE_NAME">%3$s</xliff:g> até que você remova o acesso a essa permissão."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer streaming de aplicativos e outros recursos do sistema entre seus dispositivos"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string> <string name="summary_generic" msgid="1761976003668044801">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo escolhido"</string> <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string> diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml index cb0572ddf197..528a73fd607d 100644 --- a/packages/CompanionDeviceManager/res/values-ro/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permiți ca <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să gestioneze <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"dispozitiv"</string> <string name="summary_glasses" msgid="5469208629679579157">"Aplicația va putea să acceseze următoarele permisiuni pe <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Permiți ca <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să redea în stream aplicații de pe <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pe <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> va avea acces la tot conținutul vizibil sau redat pe <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, inclusiv conținut audio, fotografii, parole și mesaje.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> va putea să redea în stream aplicații pe <xliff:g id="DEVICE_NAME">%3$s</xliff:g> până când elimini accesul la această permisiune."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_NAME">%2$s</xliff:g> de a afișa și a reda în stream aplicații între dispozitive"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Permite ca <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să acceseze aceste informații de pe <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_NAME">%2$s</xliff:g> de a accesa fotografiile, conținutul media și notificările de pe <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Permiți ca <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> să redea în stream aplicații și funcții de sistem de pe <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pe <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> va avea acces la tot conținutul vizibil sau redat pe <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, inclusiv conținut audio, fotografii, informații de plată, parole și mesaje.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> va putea să redea în stream aplicații și funcții de sistem pe <xliff:g id="DEVICE_NAME">%3$s</xliff:g> până când elimini accesul la această permisiune."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_NAME">%2$s</xliff:g> de a reda în stream aplicații și alte funcții de sistem între dispozitive"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"dispozitiv"</string> <string name="summary_generic" msgid="1761976003668044801">"Aplicația va putea să sincronizeze informații, cum ar fi numele unui apelant, între telefonul tău și dispozitivul ales"</string> <string name="consent_yes" msgid="8344487259618762872">"Permite"</string> diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml index f2e03677faf7..6d21bebc5012 100644 --- a/packages/CompanionDeviceManager/res/values-ru/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Разрешить приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> управлять устройством <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"устройстве"</string> <string name="summary_glasses" msgid="5469208629679579157">"Это приложение получит указанные разрешения на вашем устройстве (<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>)."</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Разрешить приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> транслировать приложения с вашего устройства (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) на устройство <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"У приложения \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" будет доступ ко всему, что показывается или воспроизводится на устройстве (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>), включая аудиофайлы, фотографии, пароли и сообщения.<br/><br/>Приложение \"<xliff:g id="APP_NAME_1">%1$s</xliff:g>\" сможет транслировать приложения на устройство \"<xliff:g id="DEVICE_NAME">%3$s</xliff:g>\", пока вы не отзовете разрешение."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" от имени вашего устройства \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" запрашивает разрешение транслировать приложения между устройствами."</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Разрешить приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> доступ к этой информации с вашего устройства (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>)?"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" от имени вашего устройства \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" запрашивает разрешение на доступ к фотографиям, медиаконтенту и уведомлениям на устройстве (<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>)."</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Разрешить устройству <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> транслировать приложения и системные функции с вашего устройства (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) на устройство <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"У приложения \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" будет доступ ко всему, что показывается или воспроизводится на вашем устройстве (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>), включая аудиофайлы, фотографии, платежные данные, пароли и сообщения.<br/><br/>Приложение \"<xliff:g id="APP_NAME_1">%1$s</xliff:g>\" сможет транслировать приложения и системные функции на устройство \"<xliff:g id="DEVICE_NAME">%3$s</xliff:g>\", пока вы не отзовете разрешение."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" от имени вашего устройства \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" запрашивает разрешение транслировать приложения и системные функции между устройствами."</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string> <string name="summary_generic" msgid="1761976003668044801">"Приложение сможет синхронизировать информацию между телефоном и выбранным устройством, например данные из журнала звонков."</string> <string name="consent_yes" msgid="8344487259618762872">"Разрешить"</string> diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml index 0b2369a089fa..e8b119759f7b 100644 --- a/packages/CompanionDeviceManager/res/values-si/strings.xml +++ b/packages/CompanionDeviceManager/res/values-si/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> කළමනා කිරීමට ඉඩ දෙන්න ද?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"උපාංගය"</string> <string name="summary_glasses" msgid="5469208629679579157">"මෙම යෙදුමට ඔබේ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> මත මෙම අවසර වෙත ප්රවේශ වීමට ඉඩ දෙනු ඇත"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"ඔබේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> හි යෙදුම් <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> වෙත ප්රවාහ කිරීමට <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට ඉඩ දෙන්න ද?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> හට ශ්රව්ය, ඡායාරූප, මුරපද සහ පණිවිඩ ඇතුළුව <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> හි දෘශ්යමාන හෝ වාදනය වන ඕනෑම දෙයකට ප්රවේශය ඇත.<br/><br/>ඔබ මෙම අවසරයට ප්රවේශය ඉවත් කරන තෙක් <xliff:g id="APP_NAME_1">%1$s</xliff:g> හට <xliff:g id="DEVICE_NAME">%3$s</xliff:g> වෙත යෙදුම් ප්රවාහ කිරීමට හැකි වනු ඇත."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"ඔබේ උපාංග අතර යෙදුම් සංදර්ශනය කිරීමට සහ ප්රවාහ කිරීමට <xliff:g id="APP_NAME">%1$s</xliff:g> ඔබේ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> වෙනුවෙන් අවසර ඉල්ලා සිටියි"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට ඔබේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> වෙතින් මෙම තොරතුරු වෙත ප්රවේශ වීමට ඉඩ දෙන්න"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබේ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> වෙනුවෙන් ඔබේ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> හි ඡායාරූප, මාධ්ය, සහ දැනුම්දීම් වෙත ප්රවේශ වීමට අවසරය ඉල්ලමින් සිටියි"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"ඔබේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> හි යෙදුම් සහ පද්ධති විශේෂාංග <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> වෙත ප්රවාහ කිරීමට <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> හට ඉඩ දෙන්න ද?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> හට ශ්රව්ය, ඡායාරූප, ගෙවීම් තොරතුරු, මුරපද සහ පණිවිඩ ඇතුළුව ඔබේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> හි දෘශ්යමාන හෝ වාදනය වන ඕනෑම දෙයකට ප්රවේශය ඇත.<br/><br/>ඔබ මෙම අවසරයට ප්රවේශය ඉවත් කරන තෙක් <xliff:g id="APP_NAME_1">%1$s</xliff:g> හට යෙදුම් සහ පද්ධති විශේෂාංග <xliff:g id="DEVICE_NAME">%3$s</xliff:g> වෙත ප්රවාහ කිරීමට හැකි වනු ඇත."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබේ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> වෙනුවෙන් ඔබේ උපාංග අතර යෙදුම් සහ අනෙකුත් පද්ධති විශේෂාංග ප්රවාහ කිරීමට අවසර ඉල්ලයි"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"උපාංගය"</string> <string name="summary_generic" msgid="1761976003668044801">"මෙම යෙදුමට ඔබේ දුරකථනය සහ තෝරා ගත් උපාංගය අතර, අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට හැකි වනු ඇත"</string> <string name="consent_yes" msgid="8344487259618762872">"ඉඩ දෙන්න"</string> diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml index 2819a92a6efb..41afcd525e42 100644 --- a/packages/CompanionDeviceManager/res/values-sk/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Chcete povoliť aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> spravovať zariadenie <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"zariadenie"</string> <string name="summary_glasses" msgid="5469208629679579157">"Táto aplikácia bude mať prístup k týmto povoleniam v zariadení <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Chcete povoliť aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> streamovať aplikácie zo zariadenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> do zariadenia <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"Aplikácia <xliff:g id="APP_NAME_0">%1$s</xliff:g> bude mať prístup k všetkému, čo sa zobrazuje alebo prehráva v zariadení <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> vrátane zvuku, fotiek, hesiel a správ.<br/><br/>Aplikácia <xliff:g id="APP_NAME_1">%1$s</xliff:g> bude môcť streamovať aplikácie do zariadenia <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, kým prístup k tomuto povoleniu neodstránite."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DEVICE_NAME">%2$s</xliff:g> povolenie zobrazovať a streamovať aplikácie medzi zariadeniami"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prístup k týmto informáciám zo zariadenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DEVICE_NAME">%2$s</xliff:g> povolenie na prístup k fotkám, médiám a upozorneniam zariadenia <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Chcete povoliť zariadeniu <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> streamovať aplikácie a funkcie systému zo zariadenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> do zariadenia <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"Aplikácia <xliff:g id="APP_NAME_0">%1$s</xliff:g> bude mať prístup k všetkému, čo sa zobrazuje alebo prehráva v zariadení <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> vrátane zvuku, fotiek, platobných údajov, hesiel a správ.<br/><br/>Aplikácia <xliff:g id="APP_NAME_1">%1$s</xliff:g> bude môcť streamovať aplikácie a funkcie systému do zariadenia <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, kým prístup k tomuto povoleniu neodstránite."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DEVICE_NAME">%2$s</xliff:g> povolenie streamovať aplikácie a ďalšie funkcie systému medzi zariadeniami"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"zariadenie"</string> <string name="summary_generic" msgid="1761976003668044801">"Táto aplikácia bude môcť synchronizovať informácie, napríklad meno volajúceho, medzi telefónom a vybraným zariadením"</string> <string name="consent_yes" msgid="8344487259618762872">"Povoliť"</string> diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml index 3e4f8dbc2c90..2c1edcd01899 100644 --- a/packages/CompanionDeviceManager/res/values-sl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml @@ -25,17 +25,17 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Želite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovoliti upravljanje naprave <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"naprava"</string> <string name="summary_glasses" msgid="5469208629679579157">"Ta aplikacija bo lahko dostopala do teh dovoljenj v napravi »<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>«."</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Ali aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovolite, da pretočno predvaja aplikacije naprave »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« v napravi <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> bo imela dostop do vsega, kar je prikazano ali se predvaja v napravi »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>«, vključno z zvokom, fotografijami, gesli in sporočili.<br/><br/>Aplikacija <xliff:g id="APP_NAME_1">%1$s</xliff:g> bo lahko pretočno predvajala aplikacije v napravo »<xliff:g id="DEVICE_NAME">%3$s</xliff:g>«, dokler ne odstranite dostopa do tega dovoljenja."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_NAME">%2$s</xliff:g>« zahteva dovoljenje za prikaz in pretočno predvajanje aplikacij v vaših napravah."</string> + <string name="title_app_streaming" msgid="1047090167914857893">"Ali aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovolite, da pretočno predvaja aplikacije in sistemske funkcije naprave <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> v napravi <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> + <string name="summary_app_streaming" msgid="7990244299655610920">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> bo imela dostop do vsega, kar je prikazano ali se predvaja v vaši napravi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, vključno z zvokom, fotografijami, podatki za plačilo, gesli in sporočili.<br/><br/>Aplikacija <xliff:g id="APP_NAME_1">%1$s</xliff:g> bo lahko pretočno predvajala aplikacije v napravo <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, dokler ne odstranite dostopa do tega dovoljenja."</string> + <string name="helper_summary_app_streaming" msgid="1872657107404139828">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave <xliff:g id="DEVICE_NAME">%2$s</xliff:g> zahteva dovoljenje za pretočno predvajanje aplikacij in sistemskih funkcij iz naprave <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Dovolite, da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dostopa do teh podatkov v vaši napravi »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>«."</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_NAME">%2$s</xliff:g>« zahteva dovoljenje za dostop do fotografij, predstavnosti in obvestil v napravi »<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>«."</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Ali napravi <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> dovolite, da pretočno predvaja aplikacije in sistemske funkcije naprave »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« v napravi <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> bo imela dostop do vsega, kar je prikazano ali se predvaja v napravi »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>«, vključno z zvokom, fotografijami, podatki za plačilo, gesli in sporočili.<br/><br/>Aplikacija <xliff:g id="APP_NAME_1">%1$s</xliff:g> bo lahko pretočno predvajala aplikacije in sistemske funkcije v napravo »<xliff:g id="DEVICE_NAME">%3$s</xliff:g>«, dokler ne odstranite dostopa do tega dovoljenja."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_NAME">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje aplikacij in drugih sistemskih funkcij v vaših napravah."</string> + <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Ali aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovolite, da pretočno predvaja aplikacije naprave <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> v napravi <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> + <string name="summary_nearby_device_streaming" msgid="70434958004946884">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> bo imela dostop do vsega, kar je prikazano ali se predvaja v napravi <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, vključno z zvokom, fotografijami, podatki za plačilo, gesli in sporočili.<br/><br/>Aplikacija <xliff:g id="APP_NAME_2">%1$s</xliff:g> bo lahko pretočno predvajala aplikacije v napravo <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, dokler ne odstranite dostopa do tega dovoljenja."</string> + <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave <xliff:g id="DEVICE_NAME">%2$s</xliff:g> zahteva dovoljenje za pretočno predvajanje aplikacij iz naprave <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> <string name="profile_name_generic" msgid="6851028682723034988">"naprava"</string> <string name="summary_generic" msgid="1761976003668044801">"Ta aplikacija bo lahko sinhronizirala podatke, na primer ime klicatelja, v telefonu in izbrani napravi."</string> <string name="consent_yes" msgid="8344487259618762872">"Dovoli"</string> diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml index 9d52281f16e1..14acdf0d3158 100644 --- a/packages/CompanionDeviceManager/res/values-sq/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Të lejohet që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të menaxhojë <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"pajisje"</string> <string name="summary_glasses" msgid="5469208629679579157">"Këtij aplikacioni do t\'i lejohet qasja te këto leje te <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Të lejohet që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të transmetojë aplikacionet nga <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> te <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> do të ketë qasje te çdo gjë që është e dukshme ose që luhet te <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, duke përfshirë audion, fotografitë, fjalëkalimet dhe mesazhet.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> do të mund t\'i transmetojë aplikacionet në <xliff:g id="DEVICE_NAME">%3$s</xliff:g> derisa ta heqësh qasjen për këtë leje."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_NAME">%2$s</xliff:g> për të shfaqur dhe transmetuar aplikacionet mes pajisjeve të tua"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ketë qasje në këto informacione te <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_NAME">%2$s</xliff:g> për të marrë qasje te fotografitë, media dhe njoftimet te <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Të lejohet që <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> të transmetojë aplikacionet dhe veçoritë e sistemit nga <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> te <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> do të ketë qasje te çdo gjë që është e dukshme ose që luhet te <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, duke përfshirë audion, fotografitë, informacionet për pagesën, fjalëkalimet dhe mesazhet.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> do të mund t\'i transmetojë aplikacionet dhe veçoritë e sistemit në <xliff:g id="DEVICE_NAME">%3$s</xliff:g> derisa ta heqësh qasjen për këtë leje."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_NAME">%2$s</xliff:g> për të transmetuar aplikacione dhe veçori të tjera të sistemit ndërmjet pajisjeve të tua"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"pajisja"</string> <string name="summary_generic" msgid="1761976003668044801">"Ky aplikacion do të mund të sinkronizojë informacione, si p.sh emrin e dikujt që po telefonon, mes telefonit tënd dhe pajisjes së zgjedhur."</string> <string name="consent_yes" msgid="8344487259618762872">"Lejo"</string> diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml index 69af8ab6a3dd..3f1420b0ec8f 100644 --- a/packages/CompanionDeviceManager/res/values-sr/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Желите ли да дозволите да <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> управља уређајем <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"уређај"</string> <string name="summary_glasses" msgid="5469208629679579157">"Овој апликацији ће бити дозвољено да приступа овим дозволама на уређају <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Желите ли да дозволите да <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> стримује апликације уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> на <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ће имати приступ свему што се види или пушта на уређају <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, укључујући звук, слике, лозинке и поруке.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> ће моћи да стримује апликације на <xliff:g id="DEVICE_NAME">%3$s</xliff:g> док не уклоните приступ овој дозволи."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> тражи дозволу у име уређаја <xliff:g id="DEVICE_NAME">%2$s</xliff:g> да приказује и стримује апликације између уређаја"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Дозволите да <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> приступа овим информацијама са уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> тражи дозволу у име уређаја <xliff:g id="DEVICE_NAME">%2$s</xliff:g> да приступа сликама, медијском садржају и обавештењима са уређаја <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Желите ли да дозволите да <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> стримује апликације и системске функције уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> на <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ће имати приступ свему што се види или пушта на уређају <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, укључујући звук, слике, информације о плаћању, лозинке и поруке.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> ће моћи да стримује апликације и системске функције на <xliff:g id="DEVICE_NAME">%3$s</xliff:g> док не уклоните приступ овој дозволи."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> тражи дозволу у име уређаја <xliff:g id="DEVICE_NAME">%2$s</xliff:g> да стримује апликације и друге системске функције између уређаја"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"уређај"</string> <string name="summary_generic" msgid="1761976003668044801">"Ова апликација ће моћи да синхронизује податке, попут имена особе која упућује позив, између телефона и одабраног уређаја"</string> <string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string> diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml index 6ec27d224e92..cb7b7094fa1d 100644 --- a/packages/CompanionDeviceManager/res/values-sv/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml @@ -25,17 +25,17 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Tillåt att <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> hanterar <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"enhet"</string> <string name="summary_glasses" msgid="5469208629679579157">"Appen får åtkomst till dessa behörigheter på din <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Vill du tillåta <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> att streama appar på din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> till <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får åtkomst till allt som visas eller spelas upp på din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, inklusive ljud, foton, lösenord och meddelanden.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> kan streama appar till <xliff:g id="DEVICE_NAME">%3$s</xliff:g> tills du tar bort åtkomsten till den här behörigheten."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet för din <xliff:g id="DEVICE_NAME">%2$s</xliff:g> att visa och streama appar mellan dina enheter"</string> + <string name="title_app_streaming" msgid="1047090167914857893">"Vill du tillåta <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> att streama appar och systemfunktioner på din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> till <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> + <string name="summary_app_streaming" msgid="7990244299655610920">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får åtkomst till allt som visas eller spelas upp på din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, inklusive ljud, foton, betalningsuppgifter, lösenord och meddelanden.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> kan streama appar till <xliff:g id="DEVICE_NAME">%3$s</xliff:g> tills du tar bort åtkomsten till den här behörigheten."</string> + <string name="helper_summary_app_streaming" msgid="1872657107404139828">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet för <xliff:g id="DEVICE_NAME">%2$s</xliff:g> att streama appar och systemfunktioner från din <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Ge <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> åtkomst till denna information på din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet för din <xliff:g id="DEVICE_NAME">%2$s</xliff:g> att få åtkomst till foton, mediefiler och aviseringar på din <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Vill du tillåta <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> att streama appar och systemfunktioner på din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> till <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får åtkomst till allt som visas eller spelas upp på din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, inklusive ljud, foton, betalningsuppgifter, lösenord och meddelanden.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> kan streama appar och systemfunktioner till <xliff:g id="DEVICE_NAME">%3$s</xliff:g> tills du tar bort åtkomsten till den här behörigheten."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet för din <xliff:g id="DEVICE_NAME">%2$s</xliff:g> att streama appar och andra systemfunktioner mellan dina enheter"</string> + <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Vill du tillåta <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> att streama appar på din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> till <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> + <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får åtkomst till allt som visas eller spelas upp på <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, inklusive ljud, foton, betalningsuppgifter, lösenord och meddelanden.<br/><br/><xliff:g id="APP_NAME_2">%1$s</xliff:g> kan streama appar till <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> tills du tar bort åtkomsten till den här behörigheten."</string> + <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet för <xliff:g id="DEVICE_NAME">%2$s</xliff:g> att streama appar från din <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> <string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string> <string name="summary_generic" msgid="1761976003668044801">"Den här appen kommer att kunna synkronisera information mellan telefonen och den valda enheten, till exempel namnet på någon som ringer"</string> <string name="consent_yes" msgid="8344487259618762872">"Tillåt"</string> diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml index 8efcb2ba0f8d..ca8fd2257922 100644 --- a/packages/CompanionDeviceManager/res/values-sw/strings.xml +++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Ungependa kuruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> idhibiti <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"kifaa"</string> <string name="summary_glasses" msgid="5469208629679579157">"Programu hii itaruhusiwa kufikia ruhusa hizi kwenye <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> yako"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Ungependa kuruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> itiririshe programu za <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yako kwenye <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> itafikia chochote kinachoonekana au kuchezwa kwenye <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, ikiwa ni pamoja na sauti, picha, manenosiri na ujumbe.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> itaweza kutiririsha programu kwenye <xliff:g id="DEVICE_NAME">%3$s</xliff:g> hadi utakapoondoa ruhusa hii."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Programu ya <xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_NAME">%2$s</xliff:g> yako ili ionyeshe na kutiririsha programu kati ya vifaa vyako"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Ruhusu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ifikie maelezo haya kutoka kwenye <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yako"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Programu ya <xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_NAME">%2$s</xliff:g> yako ili ifikie picha, maudhui na arifa za <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> yako"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Ungependa kuruhusu <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> itiririshe programu na vipengele vya mfumo vya <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yako kwenye <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> itafikia chochote kinachoonekana au kuchezwa kwenye <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yako, ikiwa ni pamoja na sauti, picha, maelezo ya malipo, manenosiri na ujumbe.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> itaweza kutiririsha programu na vipengele vya mfumo kwenye <xliff:g id="DEVICE_NAME">%3$s</xliff:g> hadi utakapoondoa ruhusa hii."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Programu ya <xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_NAME">%2$s</xliff:g> yako ili itiririshe programu na vipengele vingine vya mfumo kati ya vifaa vyako"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"kifaa"</string> <string name="summary_generic" msgid="1761976003668044801">"Programu hii itaweza kusawazisha maelezo, kama vile jina la mtu anayepiga simu, kati ya simu yako na kifaa ulichochagua"</string> <string name="consent_yes" msgid="8344487259618762872">"Ruhusu"</string> diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml index 1a59c09c73a4..76e6410e8d32 100644 --- a/packages/CompanionDeviceManager/res/values-ta/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong&gt சாதனத்தை நிர்வகிக்க <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கவா?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"சாதனம்"</string> <string name="summary_glasses" msgid="5469208629679579157">"உங்கள் <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> சாதனத்தில் இந்த அனுமதிகளை அணுக இந்த ஆப்ஸ் அனுமதிக்கப்படும்"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சாதனத்தின் ஆப்ஸை <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> சாதனத்தில் ஸ்ட்ரீம் செய்ய <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கவா?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"ஆடியோ, படங்கள், கடவுச்சொற்கள், மெசேஜ்கள் உட்பட <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சாதனத்தில் காட்டப்படுகின்ற/பிளே செய்யப்படுகின்ற அனைத்தையும் <xliff:g id="APP_NAME_0">%1$s</xliff:g> அணுகும்.<br/><br/>இந்த அனுமதிக்கான அணுகலை நீங்கள் அகற்றும் வரை <xliff:g id="DEVICE_NAME">%3$s</xliff:g> சாதனத்தில் ஆப்ஸை <xliff:g id="APP_NAME_1">%1$s</xliff:g> ஸ்ட்ரீம் செய்ய முடியும்."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"உங்கள் சாதனங்களுக்கு இடையே ஆப்ஸைக் காட்சிப்படுத்தவும் ஸ்ட்ரீம் செய்யவும் உங்கள் <xliff:g id="DEVICE_NAME">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> அனுமதி கேட்கிறது"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சாதனத்தில் உள்ள இந்தத் தகவல்களை அணுக, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அனுமதிக்கவும்"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"உங்கள் <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> சாதனத்தில் உள்ள படங்கள், மீடியா, அறிவிப்புகள் ஆகியவற்றை அணுக உங்கள் <xliff:g id="DEVICE_NAME">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> அனுமதி கேட்கிறது"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சாதனத்தின் ஆப்ஸையும் சிஸ்டம் அம்சங்களையும் <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> சாதனத்தில் ஸ்ட்ரீம் செய்ய <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> சாதனத்தை அனுமதிக்கவா?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"ஆடியோ, படங்கள், பேமெண்ட் தகவல்கள், கடவுச்சொற்கள், மெசேஜ்கள் உட்பட <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சாதனத்தில் காட்டப்படுகின்ற/பிளே செய்யப்படுகின்ற அனைத்தையும் <xliff:g id="APP_NAME_0">%1$s</xliff:g> அணுகும்.<br/><br/>இந்த அனுமதிக்கான அணுகலை நீங்கள் அகற்றும் வரை <xliff:g id="DEVICE_NAME">%3$s</xliff:g> சாதனத்தில் ஆப்ஸையும் சிஸ்டம் அம்சங்களையும் <xliff:g id="APP_NAME_1">%1$s</xliff:g> ஸ்ட்ரீம் செய்ய முடியும்."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"உங்கள் சாதனங்களுக்கு இடையே ஆப்ஸையும் பிற சிஸ்டம் அம்சங்களையும் ஸ்ட்ரீம் செய்ய உங்கள் <xliff:g id="DEVICE_NAME">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> அனுமதி கேட்கிறது"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"சாதனம்"</string> <string name="summary_generic" msgid="1761976003668044801">"அழைப்பவரின் பெயர் போன்ற தகவலை உங்கள் மொபைல் மற்றும் தேர்வுசெய்த சாதனத்திற்கு இடையில் இந்த ஆப்ஸால் ஒத்திசைக்க முடியும்"</string> <string name="consent_yes" msgid="8344487259618762872">"அனுமதி"</string> diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml index 63d86fc724ad..2d3f2f3a89be 100644 --- a/packages/CompanionDeviceManager/res/values-te/strings.xml +++ b/packages/CompanionDeviceManager/res/values-te/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ను మేనేజ్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించాలా?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"పరికరం"</string> <string name="summary_glasses" msgid="5469208629679579157">"మీ <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>లో ఈ అనుమతులను యాక్సెస్ చేయడానికి ఈ యాప్ అనుమతించబడుతుంది"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> యాప్లను <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>కు స్ట్రీమ్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించాలా?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"ఆడియో, ఫోటోలు, పాస్వర్డ్లు, మెసేజ్లతో సహా మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>లో కనిపించే లేదా ప్లే అయ్యే దేనికైనా <xliff:g id="APP_NAME_0">%1$s</xliff:g>కు యాక్సెస్ ఉంటుంది.<br/><br/>మీరు ఈ అనుమతికి యాక్సెస్ను తీసివేసే వరకు <xliff:g id="APP_NAME_1">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%3$s</xliff:g>కు యాప్లను స్ట్రీమ్ చేయగలదు."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"మీ పరికరాలలో యాప్లను డిస్ప్లే చేయడానికి, స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ<xliff:g id="DEVICE_NAME">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> నుండి ఈ సమాచారాన్ని యాక్సెస్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించండి"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"మీ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> ఫోటోలను, మీడియాను, ఇంకా నోటిఫికేషన్లను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> యాప్లను, సిస్టమ్ ఫీచర్లను <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>కు స్ట్రీమ్ చేయడానికి <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong>ను అనుమతించాలా?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"ఆడియో, ఫోటోలు, పేమెంట్ సమాచారం, పాస్వర్డ్లతో సహా మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>లో కనిపించే లేదా ప్లే అయ్యే దేనికైనా <xliff:g id="APP_NAME_0">%1$s</xliff:g>కు యాక్సెస్ ఉంటుంది.<br/><br/>మీరు ఈ అనుమతికి యాక్సెస్ను తీసివేసే వరకు <xliff:g id="APP_NAME_1">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%3$s</xliff:g>కు యాప్లను, సిస్టమ్ ఫీచర్లను స్ట్రీమ్ చేయగలదు."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"మీ పరికరాలలో యాప్లను, ఇతర సిస్టమ్ ఫీచర్లను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"పరికరం"</string> <string name="summary_generic" msgid="1761976003668044801">"కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని ఈ యాప్ మీ ఫోన్ కు, ఎంచుకున్న పరికరానికీ మధ్య సింక్ చేయగలుగుతుంది"</string> <string name="consent_yes" msgid="8344487259618762872">"అనుమతించండి"</string> diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml index eb9a6edbe3d6..c15718620d55 100644 --- a/packages/CompanionDeviceManager/res/values-th/strings.xml +++ b/packages/CompanionDeviceManager/res/values-th/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> จัดการ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ไหม"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"อุปกรณ์"</string> <string name="summary_glasses" msgid="5469208629679579157">"แอปนี้จะได้รับสิทธิ์ดังต่อไปนี้ใน<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>ของคุณ"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> สตรีมแอปใน<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ของคุณไปยัง <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ไหม"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> จะมีสิทธิ์เข้าถึงทุกอย่างที่ปรากฏหรือเล่นบน<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ซึ่งรวมถึงเสียง รูปภาพ รหัสผ่าน และข้อความ<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> จะสามารถสตรีมแอปไปยัง <xliff:g id="DEVICE_NAME">%3$s</xliff:g> ได้จนกว่าคุณจะนำสิทธิ์เข้าถึงนี้ออก"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> เพื่อแสดงและสตรีมแอประหว่างอุปกรณ์ต่างๆ ของคุณ"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> เข้าถึงข้อมูลนี้จาก<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ของคุณ"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> เพื่อเข้าถึงรูปภาพ สื่อ และการแจ้งเตือนใน<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>ของคุณ"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"อนุญาตให้ <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> สตรีมแอปและฟีเจอร์ของระบบใน<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ของคุณไปยัง <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> ไหม"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> จะมีสิทธิ์เข้าถึงทุกอย่างที่ปรากฏหรือเล่นบน<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ซึ่งรวมถึงเสียง รูปภาพ ข้อมูลการชำระเงิน รหัสผ่าน และข้อความ<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> จะสามารถสตรีมแอปและฟีเจอร์ของระบบไปยัง <xliff:g id="DEVICE_NAME">%3$s</xliff:g> ได้จนกว่าคุณจะนำสิทธิ์เข้าถึงนี้ออก"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> เพื่อสตรีมแอปและฟีเจอร์อื่นๆ ของระบบระหว่างอุปกรณ์"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"อุปกรณ์"</string> <string name="summary_generic" msgid="1761976003668044801">"แอปนี้จะสามารถซิงค์ข้อมูล เช่น ชื่อของบุคคลที่โทรเข้ามา ระหว่างโทรศัพท์ของคุณและอุปกรณ์ที่เลือกไว้ได้"</string> <string name="consent_yes" msgid="8344487259618762872">"อนุญาต"</string> diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml index bce6c7ce5d9b..ffa91b19d83f 100644 --- a/packages/CompanionDeviceManager/res/values-tl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na pamahalaan ang <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"device"</string> <string name="summary_glasses" msgid="5469208629679579157">"Papayagan ang app na ito na ma-access ang mga pahintulot na ito sa iyong <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na i-stream ang mga app ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> sa <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"Magkakaroon ang <xliff:g id="APP_NAME_0">%1$s</xliff:g> ng access sa kahit anong nakikita o pine-play sa <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, kasama na ang audio, mga larawan, password, at mensahe.<br/><br/>Magagawa ng <xliff:g id="APP_NAME_1">%1$s</xliff:g> na mag-stream ng mga app sa <xliff:g id="DEVICE_NAME">%3$s</xliff:g> hanggang sa alisin mo ang access sa pahintulot na ito."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Humihiling ng pahintulot ang <xliff:g id="APP_NAME">%1$s</xliff:g> para sa iyong <xliff:g id="DEVICE_NAME">%2$s</xliff:g> na makapagpakita at makapag-stream ng mga app sa mga device mo"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na i-access ang impormasyong ito sa iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Humihiling ng pahintulot ang <xliff:g id="APP_NAME">%1$s</xliff:g> para sa iyong <xliff:g id="DEVICE_NAME">%2$s</xliff:g> na ma-access ang mga larawan, media, at notification ng <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> mo"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Payagan ang <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> na i-stream ang mga app at feature ng system ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>’ sa <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"Magkakaroon ng access ang <xliff:g id="APP_NAME_0">%1$s</xliff:g> sa kahit anong nakikita o pine-play sa iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, kasama ang audio, mga larawan, impormasyon sa pagbabayad, mga password, at mga mensahe.<br/><br/>Magagawa ng <xliff:g id="APP_NAME_1">%1$s</xliff:g> na mag-stream ng mga app sa <xliff:g id="DEVICE_NAME">%3$s</xliff:g> hanggang sa alisin mo ang access sa pahintulot na ito."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Humihiling ng pahintulot ang <xliff:g id="APP_NAME">%1$s</xliff:g> para sa iyong <xliff:g id="DEVICE_NAME">%2$s</xliff:g> na mag-stream ng mga app at iba pang feature ng system sa pagitan ng mga device mo"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"device"</string> <string name="summary_generic" msgid="1761976003668044801">"Magagawa ng app na ito na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, sa pagitan ng iyong telepono at ng napiling device"</string> <string name="consent_yes" msgid="8344487259618762872">"Payagan"</string> diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml index 131f2e330354..44d6bf7da32c 100644 --- a/packages/CompanionDeviceManager/res/values-tr/strings.xml +++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasına <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> cihazını yönetmesi için izin verilsin mi?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"Cihaz"</string> <string name="summary_glasses" msgid="5469208629679579157">"Bu uygulamanın <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> cihazınızda şu izinlere erişmesine izin verilecek:"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> adlı uygulamanın <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınızdaki uygulamaları <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> cihazına aktarmasına izin verilsin mi?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>; ses, fotoğraflar, şifreler ve mesajlar da dahil olmak üzere <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazında görünen veya oynatılan her şeye erişebilecek.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> siz bu iznin erişimini kaldırana kadar uygulamaları <xliff:g id="DEVICE_NAME">%3$s</xliff:g> cihazına aktarabilecek."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g>, cihazlarınız arasında uygulamaları göstermek ve aktarmak için <xliff:g id="DEVICE_NAME">%2$s</xliff:g> cihazınız adına izin istiyor"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınızdaki bu bilgilere erişmesine izin verin"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> içindeki fotoğraf, medya ve bildirimlere erişmek için <xliff:g id="DEVICE_NAME">%2$s</xliff:g> cihazınız adına izin istiyor"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> adlı uygulamanın <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınızdaki uygulamaları ve sistem özelliklerini <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> cihazına aktarmasına izin verilsin mi?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>; ses, fotoğraflar, ödeme bilgileri, şifreler ve mesajlar da dahil olmak üzere <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınızda görünen veya oynatılan her şeye erişebilecek.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> siz bu iznin erişimini kaldırana kadar uygulamaları ve diğer sistem özelliklerini <xliff:g id="DEVICE_NAME">%3$s</xliff:g> cihazına aktarabilecek."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g>, cihazlarınız arasında uygulamaları ve diğer sistem özelliklerini aktarmak için <xliff:g id="DEVICE_NAME">%2$s</xliff:g> cihazınız adına izin istiyor"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string> <string name="summary_generic" msgid="1761976003668044801">"Bu uygulama, arayan kişinin adı gibi bilgileri telefonunuz ve seçili cihaz arasında senkronize edebilir"</string> <string name="consent_yes" msgid="8344487259618762872">"İzin ver"</string> diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml index f170d3cc15e0..1d248b6570fc 100644 --- a/packages/CompanionDeviceManager/res/values-uk/strings.xml +++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Дозволити додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> керувати пристроєм <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"пристрій"</string> <string name="summary_glasses" msgid="5469208629679579157">"Цей додаток матиме доступ до перелічених нижче дозволів на вашому <xliff:g id="DEVICE_TYPE">%1$s</xliff:g>"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Дозволити додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> транслювати додатки на вашому <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> на пристрій <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"Додаток <xliff:g id="APP_NAME_0">%1$s</xliff:g> матиме доступ до контенту, що відображається чи відтворюється на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, зокрема до аудіо, фото, паролів і повідомлень.<br/><br/>Додаток <xliff:g id="APP_NAME_1">%1$s</xliff:g> зможе транслювати додатки на пристрої \"<xliff:g id="DEVICE_NAME">%3$s</xliff:g>\", поки ви не скасуєте цей дозвіл."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені вашого пристрою \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" запитує дозвіл на відображення й транслювання додатків на ваших пристроях"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Дозвольте додатку <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> доступ до цієї інформації на вашому <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені вашого пристрою \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" запитує дозвіл на доступ до фотографій, медіафайлів і сповіщень на вашому <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Дозволити пристрою <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> транслювати додатки й системні функції на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> на пристрій <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"Додаток <xliff:g id="APP_NAME_0">%1$s</xliff:g>матиме доступ до контенту, що відображається чи відтворюється на вашому <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, зокрема до аудіо, фото, платіжної інформації, паролів і повідомлень.<br/><br/>Додаток <xliff:g id="APP_NAME_1">%1$s</xliff:g> зможе транслювати додатки й системні функції на <xliff:g id="DEVICE_NAME">%3$s</xliff:g>, поки ви не скасуєте цей дозвіл."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені вашого пристрою \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" запитує дозвіл на транслювання додатків й інших системних функцій на ваших пристроях"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"пристрій"</string> <string name="summary_generic" msgid="1761976003668044801">"Цей додаток зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає) між телефоном і вибраним пристроєм"</string> <string name="consent_yes" msgid="8344487259618762872">"Дозволити"</string> diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml index fd6537e98304..64732e814d00 100644 --- a/packages/CompanionDeviceManager/res/values-ur/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> کا نظم کرنے کی اجازت دیں؟"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"آلہ"</string> <string name="summary_glasses" msgid="5469208629679579157">"اس ایپ کو آپ کے <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> پر ان اجازتوں تک رسائی کی اجازت ہوگی"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی ایپس کو <xliff:g id="DEVICE_NAME">%3$s</xliff:g> پر سلسلہ بندی کرنے کی اجازت دیں؟"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> کو <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> پر دکھائی دینے والی یا چلائی جانے والی کسی بھی چیز تک رسائی حاصل ہوگی، بشمول آڈیو، تصاویر، پاس ورڈز اور پیغامات۔<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%3$s</xliff:g> پر اس وقت تک ایپس کی سلسلہ بندی کر سکے گی جب تک آپ اس اجازت تک رسائی کو ہٹا نہیں دیتے۔"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_NAME">%2$s</xliff:g> کی جانب سے آپ کے آلات کے درمیان ایپس کو ڈسپلے اور اسٹریم کرنے کے لیے اجازت کی درخواست کر رہی ہے"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> سے ان معلومات تک رسائی حاصل کرنے کی اجازت دیں"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_NAME">%2$s</xliff:g> کی جانب سے آپ کے <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> کی تصاویر، میڈیا اور اطلاعات تک رسائی کی اجازت کی درخواست کر رہی ہے"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> کو آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی ایپس اور سسٹم کی خصوصیات کو <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> پر سلسلہ بندی کرنے کی اجازت دیں؟"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> کو آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> پر دکھائی دینے والی یا چلائی جانے والی کسی بھی چیز تک رسائی حاصل ہوگی، بشمول آڈیو، تصاویر، ادائیگی کی معلومات، پاس ورڈز اور پیغامات۔;lt;br/><br/&gt&<xliff:g id="APP_NAME_1">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%3$s</xliff:g> پر اس وقت تک ایپس اور سسٹم کی خصوصیات کی سلسلہ بندی کر سکے گی جب تک آپ اس اجازت تک رسائی کو ہٹا نہیں دیتے۔"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_NAME">%2$s</xliff:g> کی جانب سے آپ کے آلات کے درمیان ایپس اور سسٹم کی دیگر خصوصیات کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"آلہ"</string> <string name="summary_generic" msgid="1761976003668044801">"یہ ایپ آپ کے فون اور منتخب کردہ آلے کے درمیان معلومات، جیسے کسی کال کرنے والے کے نام، کی مطابقت پذیری کر سکے گی"</string> <string name="consent_yes" msgid="8344487259618762872">"اجازت دیں"</string> diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml index f7a1ef7883d7..4b0c48a181b0 100644 --- a/packages/CompanionDeviceManager/res/values-uz/strings.xml +++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> qurilmasini boshqarish uchun ruxsat berilsinmi?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"qurilma"</string> <string name="summary_glasses" msgid="5469208629679579157">"Bu ilova <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> qurilmasida quyidagi ruxsatlarni oladi"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>dagi ilovalarni <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> qurilmasiga striming qilishiga ruxsat berasizmi?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>da koʻrinadigan yoki ijro etiladigan hamma narsaga, jumladan, audio, rasmlar, parollar va xabarlarga kirish huquqini oladi.<br/><br/>Bu ruxsatni olib tashlamaguningizcha, <xliff:g id="APP_NAME_1">%1$s</xliff:g> ilovalarni <xliff:g id="DEVICE_NAME">%3$s</xliff:g> qurilmasiga striming qila oladi."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nomidan ilovalarni koʻrsatish va striming qilishga ruxsat soʻramoqda"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>dagi ushbu maʼlumot uchun ruxsat bering"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nomidan <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>dagi suratlar, media va bildirishnomalarga kirish uchun ruxsat soʻramoqda"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>dagi ilovalar va tizim funksiyalarini <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> qurilmasiga striming qilishiga ruxsat berasizmi?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>da koʻrinadigan yoki ijro etiladigan hamma narsaga, jumladan, audio, rasmlar, toʻlov axboroti, parollar va xabarlarga kirish huquqini oladi.<br/><br/>Bu ruxsatni olib tashlamaguningizcha, <xliff:g id="APP_NAME_1">%1$s</xliff:g> ilovalarni va tizim funksiyalarini <xliff:g id="DEVICE_NAME">%3$s</xliff:g> qurilmasiga striming qila oladi."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> qurilmalaringiz orasida ilovalar va boshqa tizim funksiyalarini striming qilish uchun <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nomidan ruxsat soʻramoqda"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"qurilma"</string> <string name="summary_generic" msgid="1761976003668044801">"Bu ilova telefoningiz va tanlangan qurilmada chaqiruvchining ismi kabi maʼlumotlarni sinxronlay oladi"</string> <string name="consent_yes" msgid="8344487259618762872">"Ruxsat"</string> diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml index e668a6915b88..0b65172e9980 100644 --- a/packages/CompanionDeviceManager/res/values-vi/strings.xml +++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> quản lý <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"thiết bị"</string> <string name="summary_glasses" msgid="5469208629679579157">"Ứng dụng này sẽ được phép dùng những quyền sau trên <xliff:g id="DEVICE_TYPE">%1$s</xliff:g> của bạn"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truyền trực tuyến các ứng dụng trên <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> của bạn đến <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> sẽ có quyền truy cập vào mọi nội dung hiển thị hoặc phát trên <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, bao gồm cả âm thanh, ảnh, mật khẩu và tin nhắn.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> sẽ có thể truyền trực tuyến các ứng dụng đến <xliff:g id="DEVICE_NAME">%3$s</xliff:g> cho đến khi bạn thu hồi quyền này."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DEVICE_NAME">%2$s</xliff:g> để hiển thị và truyền trực tuyến các ứng dụng giữa các thiết bị của bạn"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập vào thông tin này trên <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> của bạn"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DEVICE_NAME">%2$s</xliff:g> để truy cập vào ảnh, nội dung nghe nhìn và thông báo trên <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> của bạn"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Cho phép <strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> truyền trực tuyến các ứng dụng và tính năng của hệ thống trên <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> của bạn đến <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> sẽ có quyền truy cập vào mọi nội dung hiển thị hoặc phát trên <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> của bạn, bao gồm cả âm thanh, ảnh, thông tin thanh toán, mật khẩu và tin nhắn.<br/><br/><xliff:g id="APP_NAME_1">%1$s</xliff:g> sẽ có thể truyền trực tuyến các ứng dụng và tính năng của hệ thống đến <xliff:g id="DEVICE_NAME">%3$s</xliff:g> cho đến khi bạn thu hồi quyền này."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DEVICE_NAME">%2$s</xliff:g> để truyền trực tuyến các ứng dụng và những tính năng khác của hệ thống giữa các thiết bị của bạn"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"thiết bị"</string> <string name="summary_generic" msgid="1761976003668044801">"Ứng dụng này sẽ đồng bộ hoá thông tin (ví dụ: tên người gọi) giữa điện thoại của bạn và thiết bị bạn chọn"</string> <string name="consent_yes" msgid="8344487259618762872">"Cho phép"</string> diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml index 8adb16009174..80e2d50b9735 100644 --- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml +++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"允许<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>管理<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"设备"</string> <string name="summary_glasses" msgid="5469208629679579157">"该应用将能获得您<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>上的以下权限"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"允许<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>将您<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>上的应用流式传输到<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>吗?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"“<xliff:g id="APP_NAME_0">%1$s</xliff:g>”将能访问<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>上可见或播放的任何内容,包括音频、照片、密码和消息。<br/><br/>“<xliff:g id="APP_NAME_1">%1$s</xliff:g>”能将应用流式传输到“<xliff:g id="DEVICE_NAME">%3$s</xliff:g>”,除非您撤消此访问权限。"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的“<xliff:g id="DEVICE_NAME">%2$s</xliff:g>”请求在设备之间显示和流式传输应用"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"允许<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>访问您<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>中的这项信息"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的“<xliff:g id="DEVICE_NAME">%2$s</xliff:g>”请求访问您<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>上的照片、媒体内容和通知"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"允许<strong><xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong>将您<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>上的应用和系统功能流式传输到<strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>吗?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"“<xliff:g id="APP_NAME_0">%1$s</xliff:g>”将能访问您<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>上可见或播放的任何内容,包括音频、照片、付款信息、密码和消息。<br/><br/>“<xliff:g id="APP_NAME_1">%1$s</xliff:g>”能将应用和系统功能流式传输到“<xliff:g id="DEVICE_NAME">%3$s</xliff:g>”,除非您撤消此访问权限。"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的“<xliff:g id="DEVICE_NAME">%2$s</xliff:g>”请求在设备之间流式传输应用和其他系统功能"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"设备"</string> <string name="summary_generic" msgid="1761976003668044801">"此应用将能在您的手机和所选设备之间同步信息,例如来电者的姓名"</string> <string name="consent_yes" msgid="8344487259618762872">"允许"</string> diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml index fee37dd834b9..cfb14220d07b 100644 --- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml +++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>管理「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」<strong></strong>嗎?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"裝置"</string> <string name="summary_glasses" msgid="5469208629679579157">"此應用程式將可在<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>上取得以下權限"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」串流<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>應用程式內容至「<xliff:g id="DEVICE_NAME">%3$s</xliff:g>」嗎?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」將能存取<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>上顯示或播放的任何內容,包括音訊、相片、密碼和訊息。<br/><br/>「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」將能串流應用程式內容至「<xliff:g id="DEVICE_NAME">%3$s</xliff:g>」,直至你移除此存取權限為止。"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」要求權限,以便在裝置間顯示和串流應用程式的內容"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」在<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>上存取這項資料"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」要求權限,以便存取<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>上的相片、媒體和通知"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"要允許「<xliff:g id="DEVICE_NAME_0">%1$s</xliff:g>」串流<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>應用程式內容和系統功能至「<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>」嗎?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」將能存取<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>上顯示或播放的任何內容,包括音訊、相片、付款資料、密碼和訊息。<br/><br/>「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」將能串流應用程式內容和系統功能至「<xliff:g id="DEVICE_NAME">%3$s</xliff:g>」,直至你移除此存取權限為止。"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」要求權限,以便在裝置間串流應用程式內容和其他系統功能"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string> <string name="summary_generic" msgid="1761976003668044801">"此應用程式將可同步手機和所選裝置的資訊,例如來電者的名稱"</string> <string name="consent_yes" msgid="8344487259618762872">"允許"</string> diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml index 28a3baf0c3bf..490d1bd7b556 100644 --- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml +++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>管理「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」<strong></strong>嗎?"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"裝置"</string> <string name="summary_glasses" msgid="5469208629679579157">"這個應用程式將可取得<xliff:g id="DEVICE_TYPE">%1$s</xliff:g>上的這些權限"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>將<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>的應用程式串流傳輸到 <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> 嗎?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」將可存取<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>顯示或播放的所有內容,包括音訊、相片、密碼和訊息。<br/><br/>「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」可將應用程式串流傳輸到 <xliff:g id="DEVICE_NAME">%3$s</xliff:g>,直到你移除這個權限為止。"</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表你的 <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 要求必要權限,以便在裝置間顯示及串流傳輸應用程式"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>中的這項資訊"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表你的 <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 要求必要權限,以便存取<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>上的相片、媒體和通知"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"要允許「<xliff:g id="DEVICE_NAME_0">%1$s</xliff:g>」<strong></strong>將<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>的應用程式和系統功能串流傳輸到 <strong><xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong> 嗎?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」將可存取<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>顯示或播放的所有內容,包括音訊、相片、付款資訊、密碼和訊息。<br/><br/>「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」可將應用程式和系統功能串流傳輸到 <xliff:g id="DEVICE_NAME">%3$s</xliff:g>,直到你移除這個權限為止。"</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表 <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 要求必要權限,以便在裝置間串流傳輸應用程式和其他系統功能"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string> <string name="summary_generic" msgid="1761976003668044801">"這個應用程式將可在手機和指定裝置間同步資訊,例如來電者名稱"</string> <string name="consent_yes" msgid="8344487259618762872">"允許"</string> diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml index 5966f8b1625a..3003fb84418c 100644 --- a/packages/CompanionDeviceManager/res/values-zu/strings.xml +++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml @@ -25,17 +25,23 @@ <string name="confirmation_title_glasses" msgid="8288346850537727333">"Vumela i-<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukuthi ifinyelele i-<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string> <string name="profile_name_glasses" msgid="3506504967216601277">"idivayisi"</string> <string name="summary_glasses" msgid="5469208629679579157">"Le-app izovunyelwa ukufinyelela lezi zimvume ku-<xliff:g id="DEVICE_TYPE">%1$s</xliff:g> yakho"</string> - <string name="title_app_streaming" msgid="6845373585257287200">"Vumela <strong>i-<xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukuze isakaze ama-app e-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho <strong>ku-<xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>?"</string> - <string name="summary_app_streaming" msgid="1274464413649731829">"I-<xliff:g id="APP_NAME_0">%1$s</xliff:g> izokwazi ukufinyelela kunoma yini ebonakalayo noma edlalwayo ku-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, okuhlanganisa umsindo, izithombe, amaphasiwedi, nemilayezo.<br/><br/>I-<xliff:g id="APP_NAME_1">%1$s</xliff:g> izokwazi ukusakaza ama-app ku-<xliff:g id="DEVICE_NAME">%3$s</xliff:g> uze ususe ukufinyelela kule mvume."</string> - <string name="helper_summary_app_streaming" msgid="1944832605534698562">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_NAME">%2$s</xliff:g> yakho yokubonisa nokusakaza ama-app phakathi kwamadivayisi wakho"</string> + <!-- no translation found for title_app_streaming (1047090167914857893) --> + <skip /> + <!-- no translation found for summary_app_streaming (7990244299655610920) --> + <skip /> + <!-- no translation found for helper_summary_app_streaming (1872657107404139828) --> + <skip /> <string name="title_automotive_projection" msgid="3296005598978412847"></string> <string name="summary_automotive_projection" msgid="8683801274662496164"></string> <string name="title_computer" msgid="4782923323932440751">"Vumela <strong>i-<xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukuze ifinyelele lolu lwazi ukusuka ku-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho"</string> <string name="summary_computer" msgid="3798467601598297062"></string> <string name="helper_summary_computer" msgid="2298803016482139668">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_NAME">%2$s</xliff:g> yakho ukuze ifinyelele izithombe ze-<xliff:g id="DEVICE_TYPE">%3$s</xliff:g> yakho, imidiya nezaziso"</string> - <string name="title_nearby_device_streaming" msgid="4295322493408411976">"Vumela <strong>i-<xliff:g id="DEVICE_NAME_0">%1$s</xliff:g></strong> ukuze isakaze ama-app e-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho nezakhi zesistimu <strong>ku-<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g></strong>?"</string> - <string name="summary_nearby_device_streaming" msgid="962267343109051648">"I-<xliff:g id="APP_NAME_0">%1$s</xliff:g> izokwazi ukufinyelela kunoma yini ebonakalayo noma edlalwayo ku-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho, okuhlanganisa umsindo, izithombe, ulwazi lokukhokha, amaphasiwedi, nemilayezo.<br/><br/>I-<xliff:g id="APP_NAME_1">%1$s</xliff:g> izokwazi ukusakaza ama-app nezakhi zesistimu ku-<xliff:g id="DEVICE_NAME">%3$s</xliff:g> uze ususe ukufinyelela kule mvume."</string> - <string name="helper_summary_nearby_device_streaming" msgid="8509848562931818793">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_NAME">%2$s</xliff:g> yakho ukuze isakaze ama-app nezinye zakhi zesistimu phakathi kwamadivayisi wakho"</string> + <!-- no translation found for title_nearby_device_streaming (2727103756701741359) --> + <skip /> + <!-- no translation found for summary_nearby_device_streaming (70434958004946884) --> + <skip /> + <!-- no translation found for helper_summary_nearby_device_streaming (4712712177819370967) --> + <skip /> <string name="profile_name_generic" msgid="6851028682723034988">"idivayisi"</string> <string name="summary_generic" msgid="1761976003668044801">"Le app izokwazi ukuvumelanisa ulwazi, njengegama lomuntu othile ofonayo, phakathi kwefoni yakho nedivayisi ekhethiwe"</string> <string name="consent_yes" msgid="8344487259618762872">"Vumela"</string> diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml index a57d6eb11927..b266912ca156 100644 --- a/packages/CompanionDeviceManager/res/values/strings.xml +++ b/packages/CompanionDeviceManager/res/values/strings.xml @@ -50,13 +50,13 @@ <!-- ================= DEVICE_PROFILE_APP_STREAMING ================= --> <!-- Confirmation for associating an application with a companion device of APP_STREAMING profile (type) [CHAR LIMIT=NONE] --> - <string name="title_app_streaming">Allow <strong><xliff:g id="app_name" example="Exo">%1$s</xliff:g></strong> to stream your <xliff:g id="device_type" example="phone">%2$s</xliff:g>\u2019s apps to <strong><xliff:g id="device_name" example="Chromebook">%3$s</xliff:g></strong>?</string> + <string name="title_app_streaming">Allow <strong><xliff:g id="app_name" example="Exo">%1$s</xliff:g></strong> to stream your <xliff:g id="device_type" example="phone">%2$s</xliff:g>\u2019s apps and system features to <strong><xliff:g id="device_name" example="Chromebook">%3$s</xliff:g></strong>?</string> <!-- Summary for associating an application with a companion device of APP_STREAMING profile [CHAR LIMIT=NONE] --> - <string name="summary_app_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will have access to anything that’s visible or played on the <xliff:g id="device_type" example="phone">%2$s</xliff:g>, including audio, photos, passwords, and messages.<br/><br/><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will be able to stream apps to <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g> until you remove access to this permission.</string> + <string name="summary_app_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will have access to anything that’s visible or played on your <xliff:g id="device_type" example="phone">%2$s</xliff:g>, including audio, photos, payment info, passwords, and messages.<br/><br/><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will be able to stream apps to <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g> until you remove access to this permission.</string> <!-- Description of the helper dialog for APP_STREAMING profile. [CHAR LIMIT=NONE] --> - <string name="helper_summary_app_streaming"><xliff:g id="app_name" example="GMS">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_name" example="Chromebook">%2$s</xliff:g> to display and stream apps between your devices</string> + <string name="helper_summary_app_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="device_name" example="Chromebook">%2$s</xliff:g> to stream apps and system features from your <xliff:g id="device_type" example="phone">%3$s</xliff:g></string> <!-- ================= DEVICE_PROFILE_AUTOMOTIVE_PROJECTION ================= --> @@ -80,13 +80,13 @@ <!-- ================= DEVICE_PROFILE_NEARBY_DEVICE_STREAMING ================= --> <!-- Confirmation for associating an application with a companion device of NEARBY_DEVICE_STREAMING profile (type) [CHAR LIMIT=NONE] --> - <string name="title_nearby_device_streaming">Allow <strong><xliff:g id="device_name" example="NearbyStreamer">%1$s</xliff:g></strong> to stream your <xliff:g id="device_type" example="phone">%2$s</xliff:g>\u2019s apps and system features to <strong><xliff:g id="device_name" example="Chromebook">%3$s</xliff:g></strong>?</string> + <string name="title_nearby_device_streaming">Allow <strong><xliff:g id="app_name" example="Exo">%1$s</xliff:g></strong> to stream your <xliff:g id="device_type" example="phone">%2$s</xliff:g>\u2019s apps to <strong><xliff:g id="device_name" example="Chromebook">%3$s</xliff:g></strong>?</string> <!-- Summary for associating an application with a companion device of NEARBY_DEVICE_STREAMING profile [CHAR LIMIT=NONE] --> - <string name="summary_nearby_device_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will have access to anything that’s visible or played on your <xliff:g id="device_type" example="phone">%2$s</xliff:g>, including audio, photos, payment info, passwords, and messages.<br/><br/><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will be able to stream apps and system features to <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g> until you remove access to this permission.</string> + <string name="summary_nearby_device_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will have access to anything that’s visible or played on <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g>, including audio, photos, payment info, passwords, and messages.<br/><br/><xliff:g id="app_name" example="Exo">%1$s</xliff:g> will be able to stream apps to <xliff:g id="device_name" example="Chromebook">%3$s</xliff:g> until you remove access to this permission.</string> <!-- Description of the helper dialog for NEARBY_DEVICE_STREAMING profile. [CHAR LIMIT=NONE] --> - <string name="helper_summary_nearby_device_streaming"><xliff:g id="app_name" example="NearbyStreamerApp">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_name" example="NearbyDevice">%2$s</xliff:g> to stream apps and other system features between your devices</string> + <string name="helper_summary_nearby_device_streaming"><xliff:g id="app_name" example="Exo">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="device_name" example="Chromebook">%2$s</xliff:g> to stream apps from your <xliff:g id="device_type" example="phone">%3$s</xliff:g></string> <!-- ================= null profile ================= --> diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java index 824dd4a5fdaf..d688a1a036d1 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java @@ -44,6 +44,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Process; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -100,7 +101,8 @@ public class PackageInstallerActivity extends Activity { private int mActivityResultCode = Activity.RESULT_CANCELED; private int mPendingUserActionReason = -1; - private final boolean mLocalLOGV = false; + private final boolean mLocalLOGV = + TextUtils.equals("userdebug", SystemProperties.get("ro.build.type", "")); PackageManager mPm; AppOpsManager mAppOpsManager; UserManager mUserManager; @@ -143,6 +145,11 @@ public class PackageInstallerActivity extends Activity { private AlertDialog mDialog; private void startInstallConfirm() { + if (mLocalLOGV) { + Log.d(TAG, "startInstallConfirm mAppInfo = " + mAppInfo + + ", existingUpdateOwner = " + getExistingUpdateOwner() + + ", mOriginatingPackage = " + mOriginatingPackage); + } TextView viewToEnable; if (mAppInfo != null) { @@ -183,6 +190,10 @@ public class PackageInstallerActivity extends Activity { try { final String packageName = mPkgInfo.packageName; final InstallSourceInfo sourceInfo = mPm.getInstallSourceInfo(packageName); + if (mLocalLOGV) { + Log.d(TAG, "getExistingUpdateOwner mAppInfo = " + mAppInfo + + ", packageName = " + packageName + ", sourceInfo = " + sourceInfo); + } return sourceInfo.getUpdateOwnerPackageName(); } catch (NameNotFoundException e) { return null; @@ -303,6 +314,12 @@ public class PackageInstallerActivity extends Activity { private void initiateInstall() { final String existingUpdateOwner = getExistingUpdateOwner(); + if (mLocalLOGV) { + Log.d(TAG, "initiateInstall mAppInfo = " + mAppInfo + + ", existingUpdateOwner = " + existingUpdateOwner + + ", mOriginatingPackage = " + mOriginatingPackage + + ", mSessionId = " + mSessionId); + } if (mSessionId == SessionInfo.INVALID_ID && !TextUtils.isEmpty(existingUpdateOwner) && !TextUtils.equals(existingUpdateOwner, mOriginatingPackage)) { @@ -814,15 +831,28 @@ public class PackageInstallerActivity extends Activity { @Override public void onOpChanged(String op, String packageName) { + if (mLocalLOGV) { + Log.d(TAG, "UnknownSourcesListener onOpChanged op = " + op + + ", packageName = " + packageName + + ", mOriginatingPackage = " + mOriginatingPackage); + } if (!mOriginatingPackage.equals(packageName)) { return; } unregister(this); mActiveUnknownSourcesListeners.remove(this); + if (mLocalLOGV) { + Log.d(TAG, "UnknownSourcesListener onOpChanged isDestroyed() = " + + isDestroyed()); + } if (isDestroyed()) { return; } new Handler(Looper.getMainLooper()).postDelayed(() -> { + if (mLocalLOGV) { + Log.d(TAG, "UnknownSourcesListener onOpChanged post isDestroyed()" + + "= " + isDestroyed() + ", getIntent() = " + getIntent()); + } if (!isDestroyed()) { startActivity(getIntent()); // The start flag (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP) doesn't @@ -840,6 +870,9 @@ public class PackageInstallerActivity extends Activity { } private void register(UnknownSourcesListener listener) { + if (mLocalLOGV) { + Log.d(TAG, "UnknownSourcesListener register"); + } mAppOpsManager.startWatchingMode( AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES, mOriginatingPackage, listener); @@ -847,6 +880,9 @@ public class PackageInstallerActivity extends Activity { } private void unregister(UnknownSourcesListener listener) { + if (mLocalLOGV) { + Log.d(TAG, "UnknownSourcesListener unregister"); + } mAppOpsManager.stopWatchingMode(listener); mActiveUnknownSourcesListeners.remove(listener); } diff --git a/packages/SettingsLib/ActionButtonsPreference/res/drawable/half_rounded_left_bk.xml b/packages/SettingsLib/ActionButtonsPreference/res/drawable/half_rounded_left_bk.xml index 0d4ef3c52e4c..8d6f0da4262f 100644 --- a/packages/SettingsLib/ActionButtonsPreference/res/drawable/half_rounded_left_bk.xml +++ b/packages/SettingsLib/ActionButtonsPreference/res/drawable/half_rounded_left_bk.xml @@ -1,18 +1,18 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - ~ Copyright (C) 2021 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. + Copyright (C) 2021 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. --> <shape xmlns:android="http://schemas.android.com/apk/res/android" diff --git a/packages/SettingsLib/ActionButtonsPreference/res/drawable/left_rounded_ripple.xml b/packages/SettingsLib/ActionButtonsPreference/res/drawable/left_rounded_ripple.xml index 1584b45aabf9..f82388c26b30 100644 --- a/packages/SettingsLib/ActionButtonsPreference/res/drawable/left_rounded_ripple.xml +++ b/packages/SettingsLib/ActionButtonsPreference/res/drawable/left_rounded_ripple.xml @@ -1,18 +1,18 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - ~ Copyright (C) 2021 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. + Copyright (C) 2021 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. --> <ripple xmlns:android="http://schemas.android.com/apk/res/android" diff --git a/packages/SettingsLib/ActionButtonsPreference/res/drawable/right_rounded_ripple.xml b/packages/SettingsLib/ActionButtonsPreference/res/drawable/right_rounded_ripple.xml index 15f2b5cd79d0..3b0cca030f0a 100644 --- a/packages/SettingsLib/ActionButtonsPreference/res/drawable/right_rounded_ripple.xml +++ b/packages/SettingsLib/ActionButtonsPreference/res/drawable/right_rounded_ripple.xml @@ -1,18 +1,18 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - ~ Copyright (C) 2021 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. + Copyright (C) 2021 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. --> <ripple xmlns:android="http://schemas.android.com/apk/res/android" diff --git a/packages/SettingsLib/ActionButtonsPreference/res/drawable/rounded_ripple.xml b/packages/SettingsLib/ActionButtonsPreference/res/drawable/rounded_ripple.xml index 90eefbe9a86e..bdf9114be20a 100644 --- a/packages/SettingsLib/ActionButtonsPreference/res/drawable/rounded_ripple.xml +++ b/packages/SettingsLib/ActionButtonsPreference/res/drawable/rounded_ripple.xml @@ -1,18 +1,18 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - ~ Copyright (C) 2021 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. + Copyright (C) 2021 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. --> <ripple xmlns:android="http://schemas.android.com/apk/res/android" diff --git a/packages/SettingsLib/ActionButtonsPreference/res/drawable/square_bk.xml b/packages/SettingsLib/ActionButtonsPreference/res/drawable/square_bk.xml index f0da7b4f457f..d56c8434824f 100644 --- a/packages/SettingsLib/ActionButtonsPreference/res/drawable/square_bk.xml +++ b/packages/SettingsLib/ActionButtonsPreference/res/drawable/square_bk.xml @@ -1,18 +1,18 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - ~ Copyright (C) 2021 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. + Copyright (C) 2021 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. --> <shape xmlns:android="http://schemas.android.com/apk/res/android" diff --git a/packages/SettingsLib/ActionButtonsPreference/res/drawable/square_ripple.xml b/packages/SettingsLib/ActionButtonsPreference/res/drawable/square_ripple.xml index 06be00dc2279..9270cbe7f4f5 100644 --- a/packages/SettingsLib/ActionButtonsPreference/res/drawable/square_ripple.xml +++ b/packages/SettingsLib/ActionButtonsPreference/res/drawable/square_ripple.xml @@ -1,18 +1,18 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - ~ Copyright (C) 2021 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. + Copyright (C) 2021 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. --> <ripple xmlns:android="http://schemas.android.com/apk/res/android" diff --git a/packages/SettingsLib/ActionButtonsPreference/res/values/arrays.xml b/packages/SettingsLib/ActionButtonsPreference/res/values/arrays.xml index fe88845daa64..180564d40782 100644 --- a/packages/SettingsLib/ActionButtonsPreference/res/values/arrays.xml +++ b/packages/SettingsLib/ActionButtonsPreference/res/values/arrays.xml @@ -1,18 +1,18 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - ~ Copyright (C) 2021 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. + Copyright (C) 2021 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"> diff --git a/packages/SettingsLib/IntroPreference/res/layout/settingslib_expressive_preference_intro.xml b/packages/SettingsLib/IntroPreference/res/layout/settingslib_expressive_preference_intro.xml index 203a395c3e98..2edc001ccc3f 100644 --- a/packages/SettingsLib/IntroPreference/res/layout/settingslib_expressive_preference_intro.xml +++ b/packages/SettingsLib/IntroPreference/res/layout/settingslib_expressive_preference_intro.xml @@ -31,7 +31,6 @@ <TextView android:id="@android:id/title" - android:text="Title" style="@style/SettingsLibEntityHeaderTitle"/> <com.android.settingslib.widget.CollapsableTextView diff --git a/packages/SettingsLib/Preference/Android.bp b/packages/SettingsLib/Preference/Android.bp index e83e17cc8375..bff95ceb137e 100644 --- a/packages/SettingsLib/Preference/Android.bp +++ b/packages/SettingsLib/Preference/Android.bp @@ -1,3 +1,19 @@ +// +// 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 { default_applicable_licenses: ["frameworks_base_license"], } @@ -22,16 +38,3 @@ android_library { ], kotlincflags: ["-Xjvm-default=all"], } - -android_library { - name: "SettingsLibPreference-testutils", - srcs: ["testutils/**/*.kt"], - static_libs: [ - "SettingsLibPreference", - "androidx.fragment_fragment-testing", - "androidx.test.core", - "androidx.test.ext.junit", - "flag-junit", - "truth", - ], -} diff --git a/packages/SettingsLib/Preference/testutils/Android.bp b/packages/SettingsLib/Preference/testutils/Android.bp new file mode 100644 index 000000000000..5287d6ce93f1 --- /dev/null +++ b/packages/SettingsLib/Preference/testutils/Android.bp @@ -0,0 +1,32 @@ +// +// 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 { + default_applicable_licenses: ["frameworks_base_license"], +} + +android_library { + name: "SettingsLibPreference-testutils", + srcs: ["**/*.kt"], + static_libs: [ + "SettingsLibPreference", + "androidx.fragment_fragment-testing", + "androidx.test.core", + "androidx.test.ext.junit", + "flag-junit", + "truth", + ], +} diff --git a/packages/SettingsLib/Preference/testutils/AndroidManifest.xml b/packages/SettingsLib/Preference/testutils/AndroidManifest.xml new file mode 100644 index 000000000000..4e807a6cd41d --- /dev/null +++ b/packages/SettingsLib/Preference/testutils/AndroidManifest.xml @@ -0,0 +1,21 @@ +<?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.settingslib.preference.testutils"> + + <uses-sdk android:minSdkVersion="21" /> +</manifest> diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values/attrs.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values/attrs.xml index 7ffde2578cc1..b90de6b59677 100644 --- a/packages/SettingsLib/SelectorWithWidgetPreference/res/values/attrs.xml +++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values/attrs.xml @@ -1,17 +1,18 @@ -<?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. +<?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> diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java b/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java index e6726dcbb17a..03a2101544be 100644 --- a/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java +++ b/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java @@ -255,4 +255,9 @@ public class SelectorWithWidgetPreference extends CheckBoxPreference { a.recycle(); } } + + @VisibleForTesting(otherwise = VisibleForTesting.NONE) + public View getExtraWidget() { + return mExtraWidget; + } } diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_list_divider.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_list_divider.xml new file mode 100644 index 000000000000..eb588d9fd585 --- /dev/null +++ b/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_list_divider.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="@color/settingslib_list_divider_color" /> + <size + android:height="1dp" + android:width="1dp" /> +</shape>
\ No newline at end of file diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_expressive_icon_chevron.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_expressive_icon_chevron.xml index 16ca18ae2200..94476538a6a5 100644 --- a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_expressive_icon_chevron.xml +++ b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_expressive_icon_chevron.xml @@ -1,18 +1,18 @@ <?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. + 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" diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_list_divider.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_list_divider.xml new file mode 100644 index 000000000000..c17f7ee8c61e --- /dev/null +++ b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_list_divider.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="@color/settingslib_materialColorOutline" /> + <size + android:height="1dp" + android:width="1dp" /> +</shape>
\ No newline at end of file diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v31/settingslib_preference_frame.xml b/packages/SettingsLib/SettingsTheme/res/layout-v31/settingslib_preference_frame.xml index 433d26445c4d..128f7a1bbb09 100644 --- a/packages/SettingsLib/SettingsTheme/res/layout-v31/settingslib_preference_frame.xml +++ b/packages/SettingsLib/SettingsTheme/res/layout-v31/settingslib_preference_frame.xml @@ -29,7 +29,6 @@ android:layout_height="wrap_content" android:layout_gravity="start" android:textAlignment="viewStart" - android:text="Title" android:maxLines="2" android:textAppearance="?android:attr/textAppearanceListItem" android:ellipsize="marquee"/> @@ -41,7 +40,6 @@ android:layout_below="@android:id/title" android:layout_alignLeft="@android:id/title" android:layout_alignStart="@android:id/title" - android:text="Summary summary summary" android:layout_gravity="start" android:textAlignment="viewStart" android:textColor="?android:attr/textColorSecondary" diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v33/settingslib_preference.xml b/packages/SettingsLib/SettingsTheme/res/layout-v33/settingslib_preference.xml deleted file mode 100644 index 4e23b6562e3e..000000000000 --- a/packages/SettingsLib/SettingsTheme/res/layout-v33/settingslib_preference.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - 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. - --> - -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:minHeight="?android:attr/listPreferredItemHeightSmall" - android:gravity="center_vertical" - android:paddingLeft="?android:attr/listPreferredItemPaddingLeft" - android:paddingStart="?android:attr/listPreferredItemPaddingStart" - android:paddingRight="?android:attr/listPreferredItemPaddingRight" - android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" - android:background="?android:attr/selectableItemBackground" - android:clipToPadding="false" - android:baselineAligned="false"> - - <include layout="@layout/settingslib_icon_frame"/> - - <include layout="@layout/settingslib_preference_frame"/> - - <!-- Preference should place its actual preference widget here. --> - <LinearLayout - android:id="@android:id/widget_frame" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:gravity="end|center_vertical" - android:paddingLeft="16dp" - android:paddingStart="16dp" - android:paddingRight="0dp" - android:paddingEnd="0dp" - android:orientation="vertical"/> - -</LinearLayout>
\ No newline at end of file diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v33/settingslib_preference_frame.xml b/packages/SettingsLib/SettingsTheme/res/layout-v33/settingslib_preference_frame.xml index f93e1b975eb2..599e8170d538 100644 --- a/packages/SettingsLib/SettingsTheme/res/layout-v33/settingslib_preference_frame.xml +++ b/packages/SettingsLib/SettingsTheme/res/layout-v33/settingslib_preference_frame.xml @@ -29,7 +29,6 @@ android:layout_height="wrap_content" android:layout_gravity="start" android:textAlignment="viewStart" - android:text="Title" android:maxLines="2" android:hyphenationFrequency="normalFast" android:lineBreakWordStyle="phrase" @@ -47,7 +46,6 @@ android:textAlignment="viewStart" android:textColor="?android:attr/textColorSecondary" android:maxLines="10" - android:text="Summary summary summary" android:hyphenationFrequency="normalFast" android:lineBreakWordStyle="phrase" style="@style/PreferenceSummaryTextStyle"/> diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml index 4cc3c89dadb5..ea7baa42a2c7 100644 --- a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml +++ b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml @@ -25,6 +25,7 @@ android:orientation="vertical" android:animateLayoutChanges="true" android:background="?android:attr/selectableItemBackground" + android:filterTouchesWhenObscured="false" android:clipToPadding="false"> <TextView diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference.xml b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference.xml index 2475dfd90e6e..511e2bb64f1e 100644 --- a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference.xml +++ b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference.xml @@ -25,7 +25,8 @@ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:background="?android:attr/selectableItemBackground" android:clipToPadding="false" - android:baselineAligned="false"> + android:baselineAligned="false" + android:filterTouchesWhenObscured="false"> <include layout="@layout/settingslib_expressive_preference_icon_frame"/> diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_icon_frame.xml b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_icon_frame.xml index f5017a5ae368..ccdf37d452b0 100644 --- a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_icon_frame.xml +++ b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_icon_frame.xml @@ -22,7 +22,8 @@ android:minWidth="@dimen/settingslib_expressive_space_medium3" android:minHeight="@dimen/settingslib_expressive_space_medium3" android:gravity="center" - android:layout_marginEnd="-8dp"> + android:layout_marginEnd="-8dp" + android:filterTouchesWhenObscured="false"> <androidx.preference.internal.PreferenceImageView android:id="@android:id/icon" diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_switch.xml b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_switch.xml index 4cbdfd5b7c36..4abcd22d67cc 100644 --- a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_switch.xml +++ b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_switch.xml @@ -19,4 +19,5 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:theme="@style/Theme.Material3.DynamicColors.DayNight" android:id="@+id/switchWidget" + android:filterTouchesWhenObscured="false" style="@style/SettingslibSwitchStyle.Expressive"/>
\ No newline at end of file diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_text_frame.xml b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_text_frame.xml index e3e689b4838c..cc42dab6737e 100644 --- a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_text_frame.xml +++ b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_preference_text_frame.xml @@ -20,7 +20,8 @@ android:layout_width="@dimen/settingslib_expressive_space_none" android:layout_height="wrap_content" android:layout_weight="1" - android:padding="@dimen/settingslib_expressive_space_small1"> + android:paddingVertical="@dimen/settingslib_expressive_space_small1" + android:filterTouchesWhenObscured="false"> <TextView android:id="@android:id/title" @@ -28,8 +29,10 @@ android:layout_height="wrap_content" android:layout_gravity="start" android:textAlignment="viewStart" - android:textAppearance="?android:attr/textAppearanceListItem" android:maxLines="2" + android:hyphenationFrequency="normalFast" + android:lineBreakWordStyle="phrase" + android:textAppearance="?android:attr/textAppearanceListItem" android:ellipsize="marquee"/> <TextView @@ -43,5 +46,7 @@ android:textAlignment="viewStart" android:textAppearance="?android:attr/textAppearanceListItemSecondary" android:textColor="?android:attr/textColorSecondary" - android:maxLines="10"/> -</RelativeLayout> + android:maxLines="10" + android:hyphenationFrequency="normalFast" + android:lineBreakWordStyle="phrase"/> +</RelativeLayout>
\ No newline at end of file diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_two_target_divider.xml b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_two_target_divider.xml index 3f751812ee40..9be9ec331984 100644 --- a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_two_target_divider.xml +++ b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_two_target_divider.xml @@ -1,18 +1,18 @@ <?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. + 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 @@ -24,7 +24,8 @@ android:orientation="horizontal" android:paddingStart="?android:attr/listPreferredItemPaddingEnd" android:paddingLeft="?android:attr/listPreferredItemPaddingEnd" - android:paddingVertical="@dimen/settingslib_expressive_space_extrasmall7"> + android:paddingVertical="@dimen/settingslib_expressive_space_extrasmall7" + android:filterTouchesWhenObscured="false"> <ImageView android:layout_width="wrap_content" diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_preference_category_no_title.xml b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_preference_category_no_title.xml index 7f466f60f517..f69fcd270919 100644 --- a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_preference_category_no_title.xml +++ b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_preference_category_no_title.xml @@ -18,5 +18,6 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" - android:baselineAligned="false"> + android:baselineAligned="false" + android:filterTouchesWhenObscured="false"> </LinearLayout> diff --git a/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml index 0a36a4fa035f..313748d8f091 100644 --- a/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml +++ b/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml @@ -56,4 +56,6 @@ <!--Deprecated. After sdk 35, don't use it--> <color name="settingslib_colorSurface">@color/settingslib_surface_dark</color> + + <color name="settingslib_list_divider_color">@android:color/system_neutral1_700</color> </resources>
\ No newline at end of file diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml index 7706e0e8a296..b99ee5123491 100644 --- a/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml +++ b/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml @@ -90,4 +90,6 @@ <color name="settingslib_spinner_title_color">@android:color/system_neutral1_900</color> <color name="settingslib_spinner_dropdown_color">@android:color/system_neutral2_700</color> + + <color name="settingslib_list_divider_color">@android:color/system_neutral1_200</color> </resources> diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml index 698f21d8d8a6..3ccbbc063064 100644 --- a/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml +++ b/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml @@ -27,6 +27,7 @@ <item name="android:switchStyle">@style/Switch.SettingsLib</item> <item name="switchStyle">@style/SwitchCompat.SettingsLib</item> <item name="android:progressBarStyleHorizontal">@style/HorizontalProgressBar.SettingsLib</item> + <item name="android:listDivider">@drawable/settingslib_list_divider</item> </style> <style name="Theme.SettingsBase" parent="Theme.SettingsBase_v31" /> diff --git a/packages/SettingsLib/SettingsTheme/res/values-v35/strings.xml b/packages/SettingsLib/SettingsTheme/res/values/strings.xml index 22734068733a..c36dcb88b9fe 100644 --- a/packages/SettingsLib/SettingsTheme/res/values-v35/strings.xml +++ b/packages/SettingsLib/SettingsTheme/res/values/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - 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. diff --git a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/CollapsableTextView.kt b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/CollapsableTextView.kt index f1cc4e952b99..7eb9840e3e98 100644 --- a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/CollapsableTextView.kt +++ b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/CollapsableTextView.kt @@ -248,8 +248,6 @@ internal class LearnMoreSpan( val url: String = "", val clickListener: View.OnClickListener) : URLSpan(url) { override fun onClick(widget: View) { - if (clickListener != null) { - clickListener.onClick(widget) - } + clickListener.onClick(widget) } } diff --git a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsThemeHelper.kt b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsThemeHelper.kt index 10e5267c02d3..74f5441f6760 100644 --- a/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsThemeHelper.kt +++ b/packages/SettingsLib/SettingsTheme/src/com/android/settingslib/widget/SettingsThemeHelper.kt @@ -18,7 +18,6 @@ package com.android.settingslib.widget import android.content.Context import android.os.Build -import android.os.SystemProperties object SettingsThemeHelper { private const val IS_EXPRESSIVE_DESIGN_ENABLED = "is_expressive_design_enabled" @@ -50,8 +49,7 @@ object SettingsThemeHelper { expressiveThemeState = if ( (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) && - (SystemProperties.getBoolean(IS_EXPRESSIVE_DESIGN_ENABLED, false) || - getPropBoolean(context, IS_EXPRESSIVE_DESIGN_ENABLED, false)) + getPropBoolean(context, IS_EXPRESSIVE_DESIGN_ENABLED, false) ) { ExpressiveThemeState.ENABLED } else { diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 0a507d12a5cb..0a8c6bfd7bdf 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Hierdie rekenaar (intern)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofoon (intern)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dokluidspreker"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Eksterne toestel"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Gekoppelde toestel"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Jou toestel moet herselflaai om hierdie verandering toe te pas. Herselflaai nou of kanselleer."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Bedrade oorfoon"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Oorfoon"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-luidspreker"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-oudio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofoonsok"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB-mikrofoon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-mikrofoon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aan"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Af"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Diensverskaffernetwerk verander tans"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 66644cb796c4..56420e296287 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"ይህ ኮምፒውተር (ውስጣዊ)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"ማይክሮፎን (ውስጣዊ)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"የመትከያ ድምፅ ማውጫ"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"የውጭ መሣሪያ"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"የተገናኘ መሣሪያ"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"የእርስዎን መሣሪያ ይህ ለው ለማመልከት እንደገና መነሣት አለበት። አሁን እንደገና ያስነሡ ወይም ይተዉት።"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"ባለገመድ የራስ ላይ ማዳመጫ"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"የጆሮ ማዳመጫ"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB ድምፅ ማውጫ"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB ኦዲዮ"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"የማይክሮፎን መሰኪያ"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB ማይክሮፎን"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB ማይክሮፎን"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"አብራ"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"አጥፋ"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"የአገልግሎት አቅራቢ አውታረ መረብን በመቀየር ላይ"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index e241c8a9a5a3..88fadbc6cb0a 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"هذا الكمبيوتر (داخلي)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"ميكروفون (داخلي)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"مكبّر صوت بقاعدة إرساء"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"جهاز خارجي"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"جهاز متّصل"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"يجب إعادة تشغيل جهازك ليتم تطبيق هذا التغيير. يمكنك إعادة التشغيل الآن أو إلغاء التغيير."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"سماعات رأس سلكية"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"سماعات رأس"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"مكبّر صوت USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"مكبر صوت USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"مقبس الميكروفون"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"ميكروفون بمنفذ USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"ميكروفون USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"مفعّلة"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"إيقاف"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"جارٍ تغيير شبكة مشغِّل شبكة الجوّال."</string> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index 4e734b9cf094..fca2953a788c 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"এই কম্পিউটাৰ (অভ্যন্তৰীণ)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"মাইক্ৰ’ফ’ন (অভ্যন্তৰীণ)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ড’ক স্পীকাৰ"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"বাহ্যিক ডিভাইচ"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"সংযোগ হৈ থকা ডিভাইচ"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"এই সলনিটো কার্যকৰী হ’বলৈ আপোনাৰ ডিভাইচটো ৰিবুট কৰিবই লাগিব। এতিয়াই ৰিবুট কৰক অথবা বাতিল কৰক।"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"তাঁৰযুক্ত হেডফ’ন"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"হেডফ’ন"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB স্পীকাৰ"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"ইউএছবি অডিঅ\'"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"মাইকৰ জেক"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"ইউএছবি মাইক"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"ইউএছবি মাইক্ৰ’ফ’ন"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"অন"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"অফ"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"বাহক নেটৱৰ্কৰ পৰিৱৰ্তন"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index 057d49249cc7..5ba618628df9 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Bu kompüter (daxili)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (daxili)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dok dinamiki"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Xarici cihaz"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Qoşulmuş cihaz"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Bu dəyişikliyin tətbiq edilməsi üçün cihaz yenidən başladılmalıdır. İndi yenidən başladın və ya ləğv edin."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Naqilli qulaqlıq"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Qulaqlıq"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB spikeri"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofon yuvası"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mikrofon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB mikrofon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktiv"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Deaktiv"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator şəbəkəsinin dəyişilməsi"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index fdd969d81a8f..28eaeba986c8 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Ovaj računar (interno)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (interni)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Zvučnik bazne stanice"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Spoljni uređaj"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Povezani uređaj"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Morate da restartujete uređaj da bi se ova promena primenila. Restartujte ga odmah ili otkažite."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Žičane slušalice"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Slušalice"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB zvučnik"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Utikač za mikrofon"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mikrofon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB mikrofon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Uključeno"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Isključeno"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Promena mreže mobilnog operatera"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index a262901b7992..e1da65e8d5c9 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Гэты камп’ютар (унутраны)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Мікрафон (унутраны)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Дынамік док-станцыі"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Знешняя прылада"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Падключаная прылада"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Перазагрузіце прыладу, каб прымяніць гэта змяненне. Перазагрузіце ці скасуйце."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Правадныя навушнікі"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Навушнікі"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-дынамік"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Аўдыяпрылада USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Раздым для мікрафона"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Мікрафон USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Мікрафон USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Уключана"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Выключана"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Змяненне аператара сеткі"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index 244a090aa594..b0c235483782 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -288,7 +288,7 @@ <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Да се разреши ли отключване от OEM?"</string> <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"ПРЕДУПРЕЖДЕНИЕ: Функциите за защита на устройството няма да работят, докато следната настройка е включена."</string> <string name="mock_location_app" msgid="6269380172542248304">"Избиране на приложение за мнимо местоположение"</string> - <string name="mock_location_app_not_set" msgid="6972032787262831155">"Няма зададено приложение за мнимо местоположение"</string> + <string name="mock_location_app_not_set" msgid="6972032787262831155">"Няма зададено приложение"</string> <string name="mock_location_app_set" msgid="4706722469342913843">"Приложение за мнимо местоположение: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="6829757985772659599">"Мрежи"</string> <string name="wifi_display_certification" msgid="1805579519992520381">"Безжичен дисплей"</string> @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Този компютър (вграден)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Микрофон (вътрешен)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Високоговорител докинг станция"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Външно устройство"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Свързано устройство"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"За да бъде приложена тази промяна, устройството ви трябва да бъде рестартирано. Рестартирайте сега или анулирайте."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Слушалки с кабел"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Слушалки"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Високоговорител с USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Аудиоустройство с USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Жак за микрофон"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Микрофон с USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Микрофон с USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Включване"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Изключване"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Промяна на мрежата на оператора"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 907cee10d23f..e861b579a04b 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"এই কম্পিউটার (ইন্টার্নাল)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"মাইক্রোফোন (ইন্টার্নাল)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ডক স্পিকার"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"এক্সটার্নাল ডিভাইস"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"কানেক্ট থাকা ডিভাইস"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"এই পরিবর্তনটি প্রয়োগ করার জন্য আপনার ডিভাইসটি অবশ্যই রিবুট করতে হবে। এখনই রিবুট করুন বা বাতিল করুন।"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"তারযুক্ত হেডফোন"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"হেডফোন"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB স্পিকার"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB অডিও"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"মাইকের জ্যাক"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB মাইক"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB মাইক্রোফোন"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"চালু আছে"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"বন্ধ আছে"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"পরিষেবা প্রদানকারীর নেটওয়ার্ক পরিবর্তন করা হচ্ছে"</string> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index 6b09b51a2f68..8844503d05a6 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Ovaj računar (interno)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (interni)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Zvučnik priključne stanice"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Vanjski uređaj"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Povezani uređaj"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Morate ponovo pokrenuti uređaj da se ova promjena primijeni. Ponovo pokrenite odmah ili otkažite."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Žičane slušalice"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Slušalice"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB zvučnik"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Priključak za mikrofon"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mikrofon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB mikrofon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Uključi"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Isključi"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Promjena mreže mobilnog operatera"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 305772989db9..b905ae2a1e81 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -288,7 +288,7 @@ <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Permetre el desbloqueig OEM?"</string> <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"ADVERTIMENT: les funcions de protecció del dispositiu no funcionaran mentre aquesta opció estigui activada."</string> <string name="mock_location_app" msgid="6269380172542248304">"Selecciona una aplicació d\'ubicació simulada"</string> - <string name="mock_location_app_not_set" msgid="6972032787262831155">"No s\'ha definit cap aplicació d\'ubicació simulada"</string> + <string name="mock_location_app_not_set" msgid="6972032787262831155">"Cap aplicació d\'ubicació simulada definida"</string> <string name="mock_location_app_set" msgid="4706722469342913843">"Aplicació d\'ubicació simulada: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="6829757985772659599">"Xarxes"</string> <string name="wifi_display_certification" msgid="1805579519992520381">"Certificació de pantalla sense fil"</string> @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Aquest ordinador (intern)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Micròfon (intern)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Base d\'altaveu"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositiu extern"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositiu connectat"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Has de reiniciar el teu dispositiu perquè s\'apliquin els canvis. Reinicia\'l ara o cancel·la."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Auriculars amb cable"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Auriculars"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Altaveu USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Àudio USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Connector per al micròfon"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Micròfon USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Micròfon USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activa"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactivat"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"S\'està canviant la xarxa de l\'operador de telefonia mòbil"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index d274e850c0f0..a69374f0a91c 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Tento počítač (interní)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (interní)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Reproduktor doku"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Externí zařízení"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Připojené zařízení"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Aby se tato změna projevila, je třeba zařízení restartovat. Restartujte zařízení nebo zrušte akci."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Kabelová sluchátka"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Sluchátka"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB reproduktor"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Zvuk USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Konektor mikrofonu"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mikrofon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Mikrofon USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Zapnout"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Vypnout"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Probíhá změna sítě operátora"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index ef37c658ffeb..f14c04b92992 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Denne computer (intern)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (indbygget)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dockhøjttaler"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ekstern enhed"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Forbundet enhed"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Din enhed skal genstartes for at anvende denne ændring. Genstart nu, eller annuller."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Høretelefoner med ledning"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Høretelefoner"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-højttaler"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-lydenhed"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Stik til mikrofon"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB-mikrofon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-mikrofon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Til"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Fra"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Skift af mobilnetværk"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 44f7329bc8db..972bb1fea866 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Dieser Computer (intern)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (intern)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock-Lautsprecher"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Externes Gerät"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Verbundenes Gerät"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Damit diese Änderung übernommen wird, musst du dein Gerät neu starten. Du kannst es jetzt neu starten oder den Vorgang abbrechen."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Kabelgebundene Kopfhörer"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Kopfhörer"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-Lautsprecher"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-Audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofonanschluss"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB‑Mikrofon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-Mikrofon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"An"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Aus"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mobilfunknetzwerk wird gewechselt"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 9cfceb56751c..86a4cb9addc3 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Αυτός ο υπολογιστής (εσωτερ.)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Μικρόφωνο (εσωτερικό)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Ηχείο βάσης σύνδεσης"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Εξωτερική συσκευή"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Συνδεδεμένη συσκευή"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Για να εφαρμοστεί αυτή η αλλαγή, θα πρέπει να επανεκκινήσετε τη συσκευή σας. Επανεκκίνηση τώρα ή ακύρωση."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Ενσύρματα ακουστικά"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Ακουστικά"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Ηχείο USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Ήχος USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Υποδοχή μικροφώνου"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Μικρόφωνο USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Μικρόφωνο USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ενεργό"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Ανενεργό"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Αλλαγή δικτύου εταιρείας κινητής τηλεφωνίας"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index d4e01ded8f59..7296c9696c8c 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"This computer (internal)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Microphone (internal)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock speaker"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External device"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Connected device"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Your device must be rebooted for this change to apply. Reboot now or cancel."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Wired headphones"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Headphone"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB speaker"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mic jack"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mic"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB microphone"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator network changing"</string> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index 602a0ed5c835..c07bd342e25b 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"This computer (internal)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Microphone (internal)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock speaker"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External Device"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Connected device"</string> @@ -688,9 +687,10 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Your device must be rebooted for this change to apply. Reboot now or cancel."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Wired headphone"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Headphone"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB speaker"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mic jack"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mic"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB microphone"</string> + <string name="media_transfer_bt_device_mic_name" msgid="1870669402238687618">"BT microphone"</string> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Carrier network changing"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index 2fd84f36c664..7296c9696c8c 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -687,10 +687,10 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Your device must be rebooted for this change to apply. Reboot now or cancel."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Wired headphones"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Headphone"</string> - <!-- no translation found for media_transfer_usb_audio_name (1789292056757821355) --> - <skip /> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mic jack"</string> - <!-- no translation found for media_transfer_usb_device_mic_name (7171789543226269822) --> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB microphone"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index d4e01ded8f59..7296c9696c8c 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"This computer (internal)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Microphone (internal)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock speaker"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External device"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Connected device"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Your device must be rebooted for this change to apply. Reboot now or cancel."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Wired headphones"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Headphone"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB speaker"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mic jack"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mic"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB microphone"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator network changing"</string> diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml index 0731b72b4b25..c85b12a129a0 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"This computer (internal)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Microphone (internal)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock speaker"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External Device"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Connected device"</string> @@ -688,9 +687,10 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Your device must be rebooted for this change to apply. Reboot now or cancel."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Wired headphone"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Headphone"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB speaker"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mic jack"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mic"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB microphone"</string> + <string name="media_transfer_bt_device_mic_name" msgid="1870669402238687618">"BT microphone"</string> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Carrier network changing"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index d6222ac07660..c933c7e77066 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Esta computadora (interna)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Micrófono (interno)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Bocina de la estación de carga"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Debes reiniciar el dispositivo para que se aplique el cambio. Reinícialo ahora o cancela la acción."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Auriculares con cable"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Auriculares"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Bocina USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Audio USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Conector para micrófono"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Micrófono USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Micrófono USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activar"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactivar"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Cambio de proveedor de red"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index d88634e2e72e..6215e7729f7a 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Este ordenador (interno)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Micrófono (interno)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Altavoz de la base"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Es necesario reiniciar tu dispositivo para que se apliquen los cambios. Reinicia ahora o cancela la acción."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Auriculares con cable"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Auriculares"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Altavoz USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Audio USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Conector jack para micrófono"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Micrófono USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Micrófono USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activado"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactivado"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Cambiando la red del operador"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index e3020be848ab..81926e5a5c03 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"See arvuti (sisemine)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (sisemine)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Doki kõlar"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Väline seade"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Ühendatud seade"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Selle muudatuse rakendamiseks tuleb seade taaskäivitada. Taaskäivitage kohe või tühistage."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Juhtmega kõrvaklapid"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Kõrvaklapid"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB kõlar"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-heli"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofoni pistikupesa"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB-mikrofon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-mikrofon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Sees"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Väljas"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operaatori võrku muudetakse"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index da47004793bc..45c2daa38f5c 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Ordenagailu hau (barnekoa)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofonoa (barnekoa)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Oinarri bozgorailuduna"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Kanpoko gailua"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Konektatutako gailua"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Aldaketa aplikatzeko, berrabiarazi egin behar da gailua. Berrabiaraz ezazu orain, edo utzi bertan behera."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Entzungailu kableduna"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Entzungailua"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB bidezko bozgorailua"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB bidezko audioa"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofonoaren konektorea"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB bidezko mikrofonoa"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB bidezko mikrofonoa"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktibatu"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desaktibatu"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operadorearen sarea aldatzen"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 5996efb9a9a7..af969248aec1 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -397,7 +397,7 @@ <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"غیرفعال کردن مسیریابی خودکار به وسایل جانبی صوتی USB"</string> <string name="debug_layout" msgid="1659216803043339741">"نمایش محدودههای طرحبندی"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"نمایش مرزها، حاشیهها و ویژگیهای دیگر کلیپ."</string> - <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"اجباری کردن چیدمان راستچین"</string> + <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"الزام جانمایی راست به چپ"</string> <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"اجباری کردن چیدمان راستچین صفحه برای همه زبانها"</string> <string name="transparent_navigation_bar" msgid="1933192171384678484">"نوار پیمایش شفاف"</string> <string name="transparent_navigation_bar_summary" msgid="5454359021817330722">"رنگ پسزمینه نوار پیمایش را بهطور پیشفرض شفاف میکند"</string> @@ -418,7 +418,7 @@ <string name="verbose_vendor_logging_preference_summary_on" msgid="9017757242481762036">"بهطور نامحدود فعال شد"</string> <string name="window_animation_scale_title" msgid="5236381298376812508">"مقیاس پویانمایی پنجره"</string> <string name="transition_animation_scale_title" msgid="1278477690695439337">"مقیاس پویانمایی انتقالی"</string> - <string name="animator_duration_scale_title" msgid="7082913931326085176">"مقیاس طول مدت انیماتور"</string> + <string name="animator_duration_scale_title" msgid="7082913931326085176">"مقیاس طول مدت مقیاس مدت پویانماساز"</string> <string name="overlay_display_devices_title" msgid="5411894622334469607">"شبیهسازی نمایشگر ثانویه"</string> <string name="debug_applications_category" msgid="5394089406638954196">"برنامهها"</string> <string name="immediately_destroy_activities" msgid="1826287490705167403">"فعالیتها نگه داشته نشوند"</string> @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"این رایانه (داخلی)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"میکروفون (داخلی)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"بلندگوی پایه اتصال"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"دستگاه خارجی"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"دستگاه متصل"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"برای اعمال این تغییر، دستگاه باید بازراهاندازی شود. یا اکنون بازراهاندازی کنید یا لغو کنید."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"هدفون سیمی"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"هدفون"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"بلندگوی USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"بلندگوی USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"فیش میکروفون"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"میکروفون USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"میکروفون USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"روشن"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"خاموش"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"تغییر شبکه شرکت مخابراتی"</string> @@ -734,7 +735,7 @@ <string name="back_navigation_animation" msgid="8105467568421689484">"پویانماییهای اشاره برگشت پیشگویانه"</string> <string name="back_navigation_animation_summary" msgid="741292224121599456">"پویانماییهای سیستم را برای اشاره برگشت پیشگویانه فعال کنید."</string> <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"این تنظیم پویانماییهای سیستم را برای پویانمایی اشاره برگشت پیشبینانه فعال میکند. این تنظیم مستلزم تنظیم شدن enableOnBackInvokedCallback مربوط به هر برنامه روی صحیح در فایل مانیفست است."</string> - <string name="font_scale_percentage" msgid="2624057443622817886">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>٪"</string> + <string name="font_scale_percentage" msgid="2624057443622817886">"%%<xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string> <string name="not_specified" msgid="5423502443185110328">"نامشخص"</string> <string name="neuter" msgid="2075249330106127310">"خنثی"</string> <string name="feminine" msgid="1529155595310784757">"مؤنث"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 6877d75de324..ab4ac1ea44c0 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Tämä tietokone (sisäinen)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofoni (sisäinen)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Telinekaiutin"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ulkoinen laite"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Yhdistetty laite"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Laitteesi on käynnistettävä uudelleen, jotta muutos tulee voimaan. Käynnistä uudelleen nyt tai peru."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Langalliset kuulokkeet"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Kuulokkeet"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-kaiutin"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofoniliitäntä"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB-mikrofoni"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-mikrofoni"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Päällä"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Ei käytössä"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operaattorin verkko muuttuu"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index b3946ce23688..05157b71d17a 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Cet ordinateur (interne)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Microphone (interne)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Haut-parleur du socle"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Appareil externe"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Appareil connecté"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Votre appareil doit être redémarré pour que ce changement prenne effet. Redémarrez-le maintenant ou annulez la modification."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Écouteurs filaires"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Écouteurs"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Haut-parleur à port USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Audio par USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Prise du microphone"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Microphone USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Microphone USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activé"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Désactivé"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Changer de réseau de fournisseur de services"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 13d57ed6ce2d..31616a79f79b 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Cet ordinateur (interne)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Micro (interne)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Haut-parleur station d\'accueil"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Appareil externe"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Appareil connecté"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Vous devez redémarrer l\'appareil pour que cette modification soit appliquée. Redémarrez maintenant ou annulez l\'opération."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Casque filaire"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Casque audio"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Haut-parleur USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Audio USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Connecteur micro"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Micro USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Micro USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Allumé"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Éteint"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Modification du réseau de l\'opérateur"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index d95e676961b0..2fccfba8ff04 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Este ordenador (interno)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Micrófono (interno)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Altofalante da base"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"É necesario reiniciar o teu dispositivo para aplicar este cambio. Reiníciao agora ou cancela o cambio."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Auriculares con cable"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Auriculares"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Altofalante USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Audio USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Conector do micrófono"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Micrófono USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Micrófono USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activada"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactivada"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Cambio de rede do operador"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index aa768f879928..3209b07a6faf 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"આ કમ્પ્યૂટર (આંતરિક)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"માઇક્રોફોન (આંતરિક)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ડૉક સ્પીકર"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"બહારનું ડિવાઇસ"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"કનેક્ટ કરેલું ડિવાઇસ"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"આ ફેરફારને લાગુ કરવા માટે તમારા ડિવાઇસને રીબૂટ કરવાની જરૂર છે. હમણાં જ રીબૂટ કરો કે રદ કરો."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"વાયરવાળો હૅડફોન"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"હૅડફોન"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB સ્પીકર"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB ઑડિયો"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"માઇક જૅક"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB માઇક"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB માઇક્રોફોન"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ચાલુ"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"બંધ"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"કૅરીઅર નેટવર્કમાં ફેરફાર થઈ રહ્યો છે"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index b8e55b50ff03..ef93e78e3090 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"इस कंप्यूटर पर (इंटरनल)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"माइक्रोफ़ोन (इंटरनल)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"डॉक स्पीकर"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"बाहरी डिवाइस"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"कनेक्ट किया गया डिवाइस"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"बदली गई सेटिंग को लागू करने के लिए, डिवाइस को रीस्टार्ट करना होगा. अपने डिवाइस को रीस्टार्ट करें या रद्द करें."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"तार वाला हेडफ़ोन"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"हेडफ़ोन"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"यूएसबी स्पीकर"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"यूएसबी ऑडियो"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"माइक्रोफ़ोन जैक"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"यूएसबी माइक्रोफ़ोन"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"यूएसबी माइक्रोफ़ोन"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"चालू है"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"बंद है"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"मोबाइल और इंटरनेट सेवा देने वाली कंपनी का नेटवर्क बदल रहा है"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index 45ac8c24bcaa..7fda17b0e91c 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Ovo računalo (interno)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (ugrađeni)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Zvučnik priključne stanice"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Vanjski uređaj"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Povezani uređaj"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Uređaj se mora ponovno pokrenuti da bi se ta promjena primijenila. Ponovo pokrenite uređaj odmah ili odustanite."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Žičane slušalice"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Slušalice"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB zvučnik"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB zvučnik"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Utičnica za mikrofon"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mikrofon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB mikrofon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Uključeno"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Isključeno"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Promjena mreže mobilnog operatera"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 6cb447ee192d..838965fdeccf 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Ez a számítógép (belső)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (belső)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dokkhangszóró"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Külső eszköz"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Csatlakoztatott eszköz"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Az eszközt újra kell indítani, hogy a módosítás megtörténjen. Indítsa újra most, vagy vesse el a módosítást."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Vezetékes fejhallgató"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Fejhallgató"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-hangszóró"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-hangeszköz"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofon jack csatlakozója"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB-mikrofon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-mikrofon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Be"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Ki"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Szolgáltatói hálózat váltása"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index 0e25b7904548..6ad700750228 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Այս համակարգիչը (ներքին)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Խոսափող (ներքին)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Դոկ-կայանով բարձրախոս"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Արտաքին սարք"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Միացված սարք"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Սարքն անհրաժեշտ է վերագործարկել, որպեսզի փոփոխությունը կիրառվի։ Վերագործարկեք հիմա կամ չեղարկեք փոփոխությունը։"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Լարով ականջակալ"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Ականջակալ"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB բարձրախոս"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB աուդիո"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Խոսափողի հարակցիչ"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB խոսափող"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB խոսափող"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Միացնել"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Անջատել"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Օպերատորի ցանցի փոփոխություն"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index ceb948daa72c..c6f0800ead9b 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -288,7 +288,7 @@ <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Izinkan buka kunci OEM?"</string> <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"PERINGATAN: Fitur perlindungan perangkat tidak akan berfungsi di perangkat ini saat setelan diaktifkan."</string> <string name="mock_location_app" msgid="6269380172542248304">"Pilih aplikasi lokasi palsu"</string> - <string name="mock_location_app_not_set" msgid="6972032787262831155">"Tidak ada aplikasi lokasi palsu yang disetel"</string> + <string name="mock_location_app_not_set" msgid="6972032787262831155">"Tidak ada aplikasi lokasi simulasi yang disetel"</string> <string name="mock_location_app_set" msgid="4706722469342913843">"Aplikasi lokasi palsu: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="6829757985772659599">"Jaringan"</string> <string name="wifi_display_certification" msgid="1805579519992520381">"Sertifikasi layar nirkabel"</string> @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Komputer ini (internal)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (internal)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Speaker dok"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Perangkat Eksternal"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Perangkat yang terhubung"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Perangkat Anda harus di-reboot agar perubahan ini diterapkan. Reboot sekarang atau batalkan."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Headphone berkabel"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Headphone"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Speaker USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Audio USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Colokan mikrofon"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Mikrofon USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Mikrofon USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktif"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Nonaktif"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Jaringan operator berubah"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index fd31a6f99c6e..2688e0ba92e8 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Þessi tölva (innbyggður)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Hljóðnemi (innbyggður)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Hátalaradokka"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ytra tæki"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Tengt tæki"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Endurræsa þarf tækið til að þessi breyting taki gildi. Endurræstu núna eða hættu við."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Heyrnartól með snúru"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Heyrnartól"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-hátalari"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-hljóð"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Hljóðnematengi"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB-hljóðnemi"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-hljóðnemi"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Kveikt"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Slökkt"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Skiptir um farsímakerfi"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index c2931fc2d257..c0f1557a3aff 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Questo computer (interno)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Microfono (interno)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Base con altoparlante"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo esterno"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo connesso"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Per applicare questa modifica, devi riavviare il dispositivo. Riavvia ora o annulla."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Cuffie con cavo"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Cuffie"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Altoparlante USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Audio USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Jack per microfono"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Microfono USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Microfono USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Cambio della rete dell\'operatore"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index bcf7e92ae375..f1020caa0db0 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"המחשב הזה (פנימי)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"מיקרופון (פנימי)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"רמקול של אביזר העגינה"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"מכשיר חיצוני"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"המכשיר המחובר"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"צריך להפעיל מחדש את המכשיר כדי להחיל את השינוי. יש להפעיל מחדש עכשיו או לבטל."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"אוזניות חוטיות"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"אוזניות"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"רמקול ב-USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"אודיו ב-USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"שקע למיקרופון"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"מיקרופון USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"מיקרופון ב-USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"פועלת"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"מצב כבוי"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"רשת ספק משתנה"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index 185c6c964a5b..ae68a03b7f40 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"このパソコン(内蔵)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"マイク(内蔵)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ホルダー スピーカー"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"外部デバイス"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"接続済みのデバイス"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"この変更を適用するには、デバイスの再起動が必要です。今すぐ再起動するか、キャンセルしてください。"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"有線ヘッドフォン"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"ヘッドフォン"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB スピーカー"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB オーディオ"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"マイク差込口"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB マイク"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB マイク"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ON"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"OFF"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"携帯通信会社のネットワークを変更します"</string> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index 9532c3a153a9..850ddf19bb42 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"ეს კომპიუტერი (შიდა)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"მიკროფონი (შიდა)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"სამაგრის დინამიკი"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"გარე მოწყობილობა"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"დაკავშირებული მოწყობილობა"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ამ ცვლილების ასამოქმედებლად თქვენი მოწყობილობა უნდა გადაიტვირთოს. გადატვირთეთ ახლავე ან გააუქმეთ."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"სადენიანი ყურსასმენი"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"ყურსასმენი"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB დინამიკი"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB აუდიო"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"მიკროფონის ჯეკი"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB მიკროფონი"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB მიკროფონი"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ჩართვა"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"გამორთვა"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"ოპერატორის ქსელის შეცვლა"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index 4f64bb9cf5d9..0cf0e04e97b6 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Осы компьютер (ішкі)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Микрофон (ішкі)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Динамигі бар қондыру станциясы"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Сыртқы құрылғы"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Жалғанған құрылғы"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Бұл өзгеріс күшіне енуі үшін, құрылғыны қайта жүктеу керек. Қазір қайта жүктеңіз не бас тартыңыз."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Сымды құлақаспап"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Құлақаспап"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB динамик"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB аудио"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Микрофон ұяшығы"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB микрофоны"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB микрофон"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Қосу"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Өшіру"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Оператор желісін өзгерту"</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index 43807a018083..0d22701f69ce 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -388,7 +388,7 @@ <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"ទិដ្ឋភាពបញ្ចេញពន្លឺភ្លឹបភ្លែតនៅក្នុងវិនដូនៅពេលគូរ"</string> <string name="show_hw_layers_updates" msgid="5268370750002509767">"បង្ហាញបច្ចុប្បន្នភាពស្រទាប់ហាតវែរ"</string> <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"ស្រទាប់ហាតវែរបញ្ចេញពន្លឺបៃតងនៅពេលធ្វើបច្ចុប្បន្នភាព"</string> - <string name="debug_hw_overdraw" msgid="8944851091008756796">"ជួសជុលការគូរលើស GPU"</string> + <string name="debug_hw_overdraw" msgid="8944851091008756796">"ជួសជុលការដាក់បង្ហាញពីលើច្រើនជ្រុលរបស់ GPU"</string> <string name="disable_overlays" msgid="4206590799671557143">"បិទការត្រួត HW"</string> <string name="disable_overlays_summary" msgid="1954852414363338166">"ប្រើ GPU ជានិច្ចសម្រាប់ផ្សំអេក្រង់"</string> <string name="simulate_color_space" msgid="1206503300335835151">"ត្រាប់តាមគំរូពណ៌"</string> @@ -417,8 +417,8 @@ <string name="verbose_vendor_logging_preference_summary_will_disable" msgid="6175431593394522553">"បិទក្រោយពេលមួយថ្ងៃ"</string> <string name="verbose_vendor_logging_preference_summary_on" msgid="9017757242481762036">"បានបើកដោយគ្មានពេលកំណត់"</string> <string name="window_animation_scale_title" msgid="5236381298376812508">"មាត្រដ្ឋានចលនាវិនដូ"</string> - <string name="transition_animation_scale_title" msgid="1278477690695439337">"មាត្រដ្ឋានដំណើរផ្លាស់ប្ដូរចលនា"</string> - <string name="animator_duration_scale_title" msgid="7082913931326085176">"មាត្រដ្ឋានរយៈពេលនៃកម្មវិធីចលនា"</string> + <string name="transition_animation_scale_title" msgid="1278477690695439337">"មាត្រដ្ឋានចលនាបែបផែនឆ្លង"</string> + <string name="animator_duration_scale_title" msgid="7082913931326085176">"មាត្រដ្ឋានរយៈពេលចលនា"</string> <string name="overlay_display_devices_title" msgid="5411894622334469607">"ត្រាប់ជាអេក្រង់ទីពីរ"</string> <string name="debug_applications_category" msgid="5394089406638954196">"កម្មវិធី"</string> <string name="immediately_destroy_activities" msgid="1826287490705167403">"កុំរក្សាទុកសកម្មភាព"</string> @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"កុំព្យូទ័រនេះ (ខាងក្នុង)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"មីក្រូហ្វូន (ខាងក្នុង)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ឧបាល័រជើងទម្រ"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ឧបករណ៍ខាងក្រៅ"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ឧបករណ៍ដែលបានភ្ជាប់"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ត្រូវតែចាប់ផ្ដើមឧបករណ៍របស់អ្នកឡើងវិញ ដើម្បីឱ្យការផ្លាស់ប្ដូរនេះមានប្រសិទ្ធភាព។ ចាប់ផ្ដើមឡើងវិញឥឡូវនេះ ឬបោះបង់។"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"កាសមានខ្សែ"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"កាស"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"ឧបករណ៍បំពងសំឡេង USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"ឧបករណ៍បំពងសំឡេង USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"ឌុយមីក្រូហ្វូន"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"មីក្រូហ្វូន USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"មីក្រូហ្វូន USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"បើក"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"បិទ"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"បណ្តាញក្រុមហ៊ុនសេវាទូរសព្ទកំពុងផ្លាស់ប្តូរ"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index 016f8b9d4003..3dc663a78366 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -241,7 +241,7 @@ <string name="category_clone" msgid="1554511758987195974">"ಕ್ಲೋನ್"</string> <string name="development_settings_title" msgid="140296922921597393">"ಡೆವಲಪರ್ ಆಯ್ಕೆಗಳು"</string> <string name="development_settings_enable" msgid="4285094651288242183">"ಡೆವಲಪರ್ ಆಯ್ಕೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> - <string name="development_settings_summary" msgid="8718917813868735095">"ಅಪ್ಲಿಕೇಶನ್ ಅಭಿವೃದ್ಧಿಗಾಗಿ ಆಯ್ಕೆಗಳನ್ನು ಹೊಂದಿಸಿ"</string> + <string name="development_settings_summary" msgid="8718917813868735095">"ಆ್ಯಪ್ ಅಭಿವೃದ್ಧಿಗಾಗಿ ಆಯ್ಕೆಗಳನ್ನು ಹೊಂದಿಸಿ"</string> <string name="development_settings_not_available" msgid="355070198089140951">"ಈ ಬಳಕೆದಾರರಿಗೆ ಡೆವಲಪರ್ ಆಯ್ಕೆಗಳು ಲಭ್ಯವಿಲ್ಲ"</string> <string name="vpn_settings_not_available" msgid="2894137119965668920">"VPN ಸೆಟ್ಟಿಂಗ್ಗಳು ಈ ಬಳಕೆದಾರರಿಗೆ ಲಭ್ಯವಿಲ್ಲ"</string> <string name="tethering_settings_not_available" msgid="266821736434699780">"ಟೆಥರಿಂಗ್ ಸೆಟ್ಟಿಂಗ್ಗಳು ಈ ಬಳಕೆದಾರರಿಗೆ ಲಭ್ಯವಿಲ್ಲ"</string> @@ -287,9 +287,9 @@ <string name="oem_unlock_enable_summary" msgid="5857388174390953829">"ಬೂಟ್ಲೋಡರ್ ಅನ್ಲಾಕ್ ಮಾಡಲು ಅನುಮತಿಸಿ"</string> <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM ಅನ್ಲಾಕ್ ಮಾಡುವಿಕೆಯನ್ನು ಅನುಮತಿಸುವುದೇ?"</string> <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"ಎಚ್ಚರಿಕೆ: ಈ ಸೆಟ್ಟಿಂಗ್ ಆನ್ ಇರುವಾಗ ಈ ಸಾಧನದಲ್ಲಿ ಸಾಧನ ಸಂರಕ್ಷಣಾ ವೈಶಿಷ್ಟ್ಯಗಳು ಕಾರ್ಯ ನಿರ್ವಹಿಸುವುದಿಲ್ಲ."</string> - <string name="mock_location_app" msgid="6269380172542248304">"ಅಣಕು ಸ್ಥಳ ಅಪ್ಲಿಕೇಶನ್ ಆಯ್ಕೆಮಾಡಿ"</string> - <string name="mock_location_app_not_set" msgid="6972032787262831155">"ಯಾವುದೇ ಅಣಕು ಸ್ಥಳ ಅಪ್ಲಿಕೇಶನ್ ಹೊಂದಿಕೆಯಾಗಿಲ್ಲ"</string> - <string name="mock_location_app_set" msgid="4706722469342913843">"ಅಣಕು ಸ್ಥಳ ಅಪ್ಲಿಕೇಶನ್: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="mock_location_app" msgid="6269380172542248304">"ಅಣಕು ಸ್ಥಳ ಆ್ಯಪ್ ಆಯ್ಕೆಮಾಡಿ"</string> + <string name="mock_location_app_not_set" msgid="6972032787262831155">"ಯಾವುದೇ ಅಣಕು ಸ್ಥಳ ಆ್ಯಪ್ ಹೊಂದಿಕೆಯಾಗಿಲ್ಲ"</string> + <string name="mock_location_app_set" msgid="4706722469342913843">"ಅಣಕು ಸ್ಥಳ ಆ್ಯಪ್: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="6829757985772659599">"ನೆಟ್ವರ್ಕಿಂಗ್"</string> <string name="wifi_display_certification" msgid="1805579519992520381">"ವೈರ್ಲೆಸ್ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣ"</string> <string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi‑Fi ವೆರ್ಬೋಸ್ ಲಾಗಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> @@ -356,17 +356,17 @@ <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ಬ್ಲೂಟೂತ್ Gabeldorsche ವೈಶಿಷ್ಟ್ಯದ ಸ್ಟ್ಯಾಕ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ."</string> <string name="enhanced_connectivity_summary" msgid="1576414159820676330">"ವರ್ಧಿತ ಸಂಪರ್ಕ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ"</string> <string name="enable_terminal_title" msgid="3834790541986303654">"ಸ್ಥಳೀಯ ಟರ್ಮಿನಲ್"</string> - <string name="enable_terminal_summary" msgid="2481074834856064500">"ಸ್ಥಳೀಯ ಶೆಲ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸುವ ಟರ್ಮಿನಲ್ ಅಪ್ಲಿಕೇಶನ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> + <string name="enable_terminal_summary" msgid="2481074834856064500">"ಸ್ಥಳೀಯ ಶೆಲ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸುವ ಟರ್ಮಿನಲ್ ಆ್ಯಪ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> <string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP ಪರೀಕ್ಷಿಸುವಿಕೆ"</string> <string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"HDCP ಪರಿಶೀಲನಾ ನಡವಳಿಕೆಯನ್ನು ಹೊಂದಿಸಿ"</string> <string name="debug_debugging_category" msgid="535341063709248842">"ಡೀಬಗ್ ಮಾಡುವಿಕೆ"</string> - <string name="debug_app" msgid="8903350241392391766">"ಡೀಬಗ್ ಅಪ್ಲಿಕೇಶನ್ ಆಯ್ಕೆಮಾಡಿ"</string> + <string name="debug_app" msgid="8903350241392391766">"ಡೀಬಗ್ ಆ್ಯಪ್ ಆಯ್ಕೆಮಾಡಿ"</string> <string name="debug_app_not_set" msgid="1934083001283807188">"ಯಾವುದೇ ಡೀಬಗ್ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಹೊಂದಿಸಿಲ್ಲ"</string> <string name="debug_app_set" msgid="6599535090477753651">"ಡೀಬಗ್ ಅಪ್ಲಿಕೇಶನ್: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="select_application" msgid="2543228890535466325">"ಅಪ್ಲಿಕೇಶನ್ ಆಯ್ಕೆಮಾಡಿ"</string> <string name="no_application" msgid="9038334538870247690">"ಏನೂ ಇಲ್ಲ"</string> <string name="wait_for_debugger" msgid="7461199843335409809">"ಡೀಬಗರ್ಗಾಗಿ ನಿರೀಕ್ಷಿಸಿ"</string> - <string name="wait_for_debugger_summary" msgid="6846330006113363286">"ಲಗತ್ತನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸುವ ಮೊದಲು ಡೀಬಗರ್ಗಾಗಿ ಡೀಬಗ್ ಮಾಡಿದ ಅಪ್ಲಿಕೇಶನ್ ಕಾಯುತ್ತದೆ"</string> + <string name="wait_for_debugger_summary" msgid="6846330006113363286">"ಲಗತ್ತನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸುವ ಮೊದಲು ಡೀಬಗರ್ಗಾಗಿ ಡೀಬಗ್ ಮಾಡಿದ ಆ್ಯಪ್ ಕಾಯುತ್ತದೆ"</string> <string name="debug_input_category" msgid="7349460906970849771">"ಇನ್ಪುಟ್"</string> <string name="debug_drawing_category" msgid="5066171112313666619">"ಚಿತ್ರಣ"</string> <string name="debug_hw_drawing_category" msgid="5830815169336975162">"ಹಾರ್ಡ್ವೇರ್ ವೇಗವರ್ಧಿತ ರೆಂಡರಿಂಗ್"</string> @@ -425,11 +425,11 @@ <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"ಬಳಕೆದಾರರು ಹೊರಹೋಗುತ್ತಿದ್ದಂತೆಯೇ ಚಟುವಟಿಕೆ ನಾಶಪಡಿಸು"</string> <string name="app_process_limit_title" msgid="8361367869453043007">"ಹಿನ್ನೆಲೆ ಪ್ರಕ್ರಿಯೆ ಮಿತಿ"</string> <string name="show_all_anrs" msgid="9160563836616468726">"ಹಿನ್ನೆಲೆ ANR ಗಳನ್ನು ತೋರಿಸಿ"</string> - <string name="show_all_anrs_summary" msgid="8562788834431971392">"ಹಿನ್ನೆಲೆ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ ಎಂಬ ಸಂಭಾಷಣೆ ತೋರಿಸಿ"</string> + <string name="show_all_anrs_summary" msgid="8562788834431971392">"ಹಿನ್ನೆಲೆ ಆ್ಯಪ್ಗಳಿಗಾಗಿ ಆ್ಯಪ್ ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ ಎಂಬ ಸಂಭಾಷಣೆ ತೋರಿಸಿ"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"ನೋಟಿಫಿಕೇಶನ್ ಎಚ್ಚರಿಕೆ ತೋರಿಸಿ"</string> <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"ಅಮಾನ್ಯ ಚಾನಲ್ ಅಧಿಸೂಚನೆಗಾಗಿ ಪರದೆಯಲ್ಲಿ ಎಚ್ಚರಿಕೆ"</string> <string name="force_allow_on_external" msgid="9187902444231637880">"ಬಾಹ್ಯವಾಗಿ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಒತ್ತಾಯವಾಗಿ ಅನುಮತಿಸಿ"</string> - <string name="force_allow_on_external_summary" msgid="8525425782530728238">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳು ಯಾವುದೇ ಆಗಿದ್ದರೂ, ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆಗೆ ಬರೆಯಲು ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅರ್ಹಗೊಳಿಸುತ್ತದೆ"</string> + <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="7599125687603914253">"ಮುಕ್ತಸ್ವರೂಪದ ವಿಂಡೊಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> @@ -453,7 +453,7 @@ <string name="inactive_apps_title" msgid="5372523625297212320">"ಸ್ಟ್ಯಾಂಡ್ಬೈ ಅಪ್ಲಿಕೇಶನ್ಗಳು"</string> <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"ನಿಷ್ಕ್ರಿಯ. ಟಾಗಲ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"ಸಕ್ರಿಯ. ಟಾಗಲ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> - <string name="standby_bucket_summary" msgid="5128193447550429600">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಟ್ಯಾಂಡ್ಬೈ ಸ್ಥಿತಿ:<xliff:g id="BUCKET"> %s</xliff:g>"</string> + <string name="standby_bucket_summary" msgid="5128193447550429600">"ಆ್ಯಪ್ ಸ್ಟ್ಯಾಂಡ್ಬೈ ಸ್ಥಿತಿ:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"ಮೀಡಿಯಾ ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> <string name="transcode_user_control" msgid="6176368544817731314">"ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಡೀಫಾಲ್ಟ್ಗಳನ್ನು ಅತಿಕ್ರಮಿಸಿ"</string> <string name="transcode_enable_all" msgid="2411165920039166710">"ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"ಈ ಕಂಪ್ಯೂಟರ್ (ಆಂತರಿಕ)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"ಮೈಕ್ರೊಫೋನ್ (ಆಂತರಿಕ)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ಡಾಕ್ ಸ್ಪೀಕರ್"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ಬಾಹ್ಯ ಸಾಧನ"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ಕನೆಕ್ಟ್ ಮಾಡಿರುವ ಸಾಧನ"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ಈ ಬದಲಾವಣೆ ಅನ್ವಯವಾಗಲು ನಿಮ್ಮ ಸಾಧನವನ್ನು ರೀಬೂಟ್ ಮಾಡಬೇಕು. ಇದೀಗ ರೀಬೂಟ್ ಮಾಡಿ ಅಥವಾ ರದ್ದುಗೊಳಿಸಿ."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"ವೈಯರ್ ಹೊಂದಿರುವ ಹೆಡ್ಫೋನ್"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"ಹೆಡ್ಫೋನ್"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB ಸ್ಪೀಕರ್"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB ಆಡಿಯೋ"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"ಮೈಕ್ ಜ್ಯಾಕ್"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB ಮೈಕ್"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB ಮೈಕ್ರೊಫೋನ್"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ಆನ್ ಆಗಿದೆ"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ಆಫ್"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"ವಾಹಕ ನೆಟ್ವರ್ಕ್ ಬದಲಾಯಿಸುವಿಕೆ"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 0af77dd660c0..9f714e18d8b2 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"이 컴퓨터(내부)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"마이크(내부)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"도크 스피커"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"외부 기기"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"연결된 기기"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"변경사항을 적용하려면 기기를 재부팅해야 합니다. 지금 재부팅하거나 취소하세요."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"유선 헤드폰"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"헤드폰"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB 스피커"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB 오디오"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"마이크 잭"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB 마이크"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB 마이크"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"사용"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"사용 안 함"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"이동통신사 네트워크 변경"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index a3ff033ac0f4..d7a39131edf0 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Бул компьютер (ички)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Микрофон (ички)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Док бекеттин динамиги"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Тышкы түзмөк"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Туташкан түзмөк"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Бул өзгөрүү күчүнө кириши үчүн, түзмөктү өчүрүп күйгүзүңүз. Азыр же кийинчерээк өчүрүп күйгүзсөңүз болот."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Зымдуу гарнитура"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Гарнитура"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB динамиги"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB аудио"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Микрофондун оюкчасы"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB микрофон"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB микрофон"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Күйгүзүү"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Өчүрүү"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Байланыш оператору өзгөртүлүүдө"</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index 1d89e3e5e68f..e57dae8d4ea4 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"ຄອມພິວເຕີນີ້ (ພາຍໃນ)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"ໄມໂຄຣໂຟນ (ພາຍໃນ)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ແທ່ນວາງລຳໂພງ"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ອຸປະກອນພາຍນອກ"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ອຸປະກອນທີ່ເຊື່ອມຕໍ່"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ທ່ານຕ້ອງປິດເປີດອຸປະກອນຄືນໃໝ່ເພື່ອນຳໃຊ້ການປ່ຽນແປງນີ້. ປິດເປີດໃໝ່ດຽວນີ້ ຫຼື ຍົກເລີກ."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"ຫູຟັງແບບມີສາຍ"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"ຫູຟັງ"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"ລຳໂພງ USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"ສຽງ USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"ຊ່ອງສຽງໄມ"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"ໄມ USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"ໄມໂຄຣໂຟນ USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ເປີດ"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ປິດ"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"ການປ່ຽນເຄືອຂ່າຍຜູ້ໃຫ້ບໍລິການ"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index 265eb9aa0618..a4d5b9bb1581 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Šis kompiuteris (vidinis)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofonas (vidinis)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Doko garsiakalbis"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Išorinis įrenginys"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Prijungtas įrenginys"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Kad pakeitimas būtų pritaikytas, įrenginį reikia paleisti iš naujo. Dabar paleiskite iš naujo arba atšaukite."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Laidinės ausinės"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Ausinės"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB garsiakalbis"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB garsas"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofono jungtis"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mikrofonas"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB mikrofonas"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Įjungta"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Išjungta"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Keičiamas operatoriaus tinklas"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index c24dafbaf278..bf6f80cab0db 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Šī datora iekšējais skaļrunis"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofons (iebūvētais)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Doka skaļrunis"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ārēja ierīce"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Pievienotā ierīce"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Lai šīs izmaiņas tiktu piemērotas, nepieciešama ierīces atkārtota palaišana. Atkārtoti palaidiet to tūlīt vai atceliet izmaiņas."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Vadu austiņas"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Austiņas"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB skaļrunis"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofona ligzda"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mikrofons"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB mikrofons"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ieslēgts"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Izslēgts"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mobilo sakaru operatora tīkla mainīšana"</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index ea9ff6c5b06b..f664f725b0ab 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Овој компјуер (внатрешен)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Микрофон (внатрешен)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Док со звучник"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Надворешен уред"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Поврзан уред"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"За да се примени променава, уредот мора да се рестартира. Рестартирајте сега или откажете."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Жичени слушалки"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Слушалка"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-звучник"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-аудио"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Приклучок за микрофон"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB-микрофон"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-микрофон"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Вклучено"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Исклучено"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Променување на мрежата на операторот"</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index 7af53aad667f..49af83d9851e 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"ഈ കമ്പ്യൂട്ടർ (ഇന്റേണൽ)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"മൈക്രോഫോൺ (ഇന്റേണൽ)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ഡോക്ക് സ്പീക്കർ"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ബാഹ്യ ഉപകരണം"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"കണക്റ്റ് ചെയ്ത ഉപകരണം"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ഈ മാറ്റം ബാധകമാകുന്നതിന് നിങ്ങളുടെ ഉപകരണം റീബൂട്ട് ചെയ്യേണ്ടതുണ്ട്. ഇപ്പോൾ റീബൂട്ട് ചെയ്യുകയോ റദ്ദാക്കുകയോ ചെയ്യുക."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"വയേർഡ് ഹെഡ്ഫോൺ"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"ഹെഡ്ഫോൺ"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB സ്പീക്കർ"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB ഓഡിയോ"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"മൈക്ക് ജാക്ക്"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB മൈക്ക്"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB മൈക്രോഫോൺ"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ഓണാണ്"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ഓഫാണ്"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"കാരിയർ നെറ്റ്വർക്ക് മാറ്റൽ"</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index 9fdbdc693dc8..2d010feba7ad 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Энэ компьютер (дотоод)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Микрофон (дотоод)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Суурилуулагчийн чанга яригч"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Гадаад төхөөрөмж"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Холбогдсон төхөөрөмж"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Энэ өөрчлөлтийг хэрэгжүүлэхийн тулд таны төхөөрөмжийг дахин асаах ёстой. Одоо дахин асаах эсвэл цуцлана уу."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Утастай чихэвч"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Чихэвч"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB чанга яригч"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB аудио"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Микрофоны чихэвчний оролт"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB микрофон"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB микрофон"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Асаах"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Унтраах"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Оператор компанийн сүлжээг өөрчилж байна"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 581545d609b9..bea1500a9874 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"हा काँप्युटर (अंतर्गत)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"मायक्रोफोन (अंतर्गत)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"डॉक स्पीकर"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"बाह्य डिव्हाइस"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"कनेक्ट केलेले डिव्हाइस"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"हा बदल लागू करण्यासाठी तुमचे डिव्हाइस रीबूट करणे आवश्यक आहे. आता रीबूट करा किंवा रद्द करा."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"वायर्ड हेडफोन"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"हेडफोन"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB स्पीकर"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB ऑडिओ"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"माइक जॅक"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB माइक"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB मायक्रोफोन"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"सुरू करा"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"बंद करा"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"वाहक नेटवर्क बदलत आहे"</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index 7990e0443acf..f04549027e0a 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Komputer ini (dalaman)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (dalaman)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Pembesar suara dok"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Peranti Luar"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Peranti yang disambungkan"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Peranti anda mesti dibut semula supaya perubahan ini berlaku. But semula sekarang atau batalkan."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Fon kepala berwayar"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Fon kepala"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Pembesar suara USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Audio USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Bicu mikrofon"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Mikrofon USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Mikrofon USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Hidup"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Mati"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Rangkaian pembawa berubah"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index 8fbc8bdc867e..4bdb50f50a78 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -376,7 +376,7 @@ <string name="strict_mode_summary" msgid="1838248687233554654">"အက်ပ်လုပ်ဆောင်မှု ရှည်ကြာလျှင် စကရင်ပြန်စသည်"</string> <string name="pointer_location" msgid="7516929526199520173">"မြား၏တည်နေရာ"</string> <string name="pointer_location_summary" msgid="957120116989798464">"လက်ရှိထိတွေ့မှုဒေတာကို ဖန်သားပေါ်တွင်ထပ်၍ ပြသသည်"</string> - <string name="show_touches" msgid="8437666942161289025">"တို့ခြင်းများကို ပြပါ"</string> + <string name="show_touches" msgid="8437666942161289025">"တို့ချက်များ ပြရန်"</string> <string name="show_touches_summary" msgid="3692861665994502193">"တို့ခြင်းများအတွက် အမြင်ဖြင့် တုံ့ပြန်မှုပြသည်"</string> <string name="show_key_presses" msgid="6360141722735900214">"ကီးနှိပ်မှုများ ပြပါ"</string> <string name="show_key_presses_summary" msgid="725387457373015024">"ပကတိကီးနှိပ်မှုများအတွက် ရုပ်မြင်အကြံပြုချက် ပြပါ"</string> @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"ဤကွန်ပျူတာ (စက်တွင်း)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"မိုက်ခရိုဖုန်း (စက်တွင်း)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"အထိုင် စပီကာ"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ပြင်ပစက်"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ချိတ်ဆက်ကိရိယာ"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ဤအပြောင်းအလဲ ထည့်သွင်းရန် သင့်စက်ကို ပြန်လည်စတင်ရမည်။ ယခု ပြန်လည်စတင်ပါ သို့မဟုတ် ပယ်ဖျက်ပါ။"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"ကြိုးတပ်နားကြပ်"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"နားကြပ်"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB စပီကာ"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB အသံ"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"မိုက်ဂျက်ပင်"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB မိုက်"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB မိုက်ခရိုဖုန်း"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ဖွင့်"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ပိတ်"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"ဝန်ဆောင်မှုပေးသူ ကွန်ရက် ပြောင်းလဲနေသည်။"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 569b900bd524..5de70698c370 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Denne datamaskinen (intern)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (intern)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dokkhøyttaler"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Ekstern enhet"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Tilkoblet enhet"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Enheten din må startes på nytt for at denne endringen skal tre i kraft. Start på nytt nå eller avbryt."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Hodetelefoner med kabel"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Hodetelefoner"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-høyttaler"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-lyd"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofonkontakt"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB-mikrofon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-mikrofon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"På"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Av"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Bytting av operatørnettverk"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index 916aba97cdf3..ec5da4572bed 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"यो कम्प्युटर (आन्तरिक)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"माइक्रोफोन (आन्तरिक)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"डक स्पिकर"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"बाह्य डिभाइस"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"कनेक्ट गरिएको डिभाइस"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"यो परिवर्तन लागू गर्न तपाईंको यन्त्र अनिवार्य रूपमा रिबुट गर्नु पर्छ। अहिले रिबुट गर्नुहोस् वा रद्द गर्नुहोस्।"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"तारयुक्त हेडफोन"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"हेडफोन"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB स्पिकर"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB अडियो"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"माइकको ज्याक"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB माइक"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB माइक्रोफोन"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"अन छ"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"अफ छ"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"सेवा प्रदायकको नेटवर्क परिवर्तन गर्ने आइकन"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 78dfd35ed855..f6c5c9ca764a 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Deze computer (intern)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Microfoon (intern)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dockspeaker"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Extern apparaat"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Verbonden apparaat"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Je apparaat moet opnieuw worden opgestart om deze wijziging toe te passen. Start nu opnieuw op of annuleer de wijziging."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Bedrade koptelefoon"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Koptelefoon"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-speaker"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Microfoonaansluiting"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB-microfoon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-microfoon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aan"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Uit"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Netwerk van provider wordt gewijzigd"</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index c2439f9c304a..2ab4d133f2bf 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"ଏହି କମ୍ପ୍ୟୁଟର (ଇଣ୍ଟର୍ନଲ)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"ମାଇକ୍ରୋଫୋନ (ଇଣ୍ଟର୍ନଲ)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ଡକ ସ୍ପିକର"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ଏକ୍ସଟର୍ନଲ ଡିଭାଇସ"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"କନେକ୍ଟ କରାଯାଇଥିବା ଡିଭାଇସ"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ଏହି ପରିବର୍ତ୍ତନ ଲାଗୁ କରିବା ପାଇଁ ଆପଣଙ୍କ ଡିଭାଇସକୁ ନିଶ୍ଚିତ ରୂପେ ରିବୁଟ୍ କରାଯିବା ଆବଶ୍ୟକ। ବର୍ତ୍ତମାନ ରିବୁଟ୍ କରନ୍ତୁ କିମ୍ବା ବାତିଲ କରନ୍ତୁ।"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"ତାରଯୁକ୍ତ ହେଡଫୋନ"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"ହେଡଫୋନ"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB ସ୍ପିକର"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB ଅଡିଓ"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"ମାଇକ ଜେକ"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB ମାଇକ"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB ମାଇକ୍ରୋଫୋନ"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ଚାଲୁ ଅଛି"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ବନ୍ଦ ଅଛି"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"କେରିଅର୍ ନେଟ୍ୱର୍କ ବଦଳୁଛି"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index 4a4f9248daba..f054ed538cee 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"ਇਸ ਕੰਪਿਊਟਰ \'ਤੇ (ਅੰਦਰੂਨੀ)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ (ਅੰਦਰੂਨੀ)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ਡੌਕ ਸਪੀਕਰ"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ਬਾਹਰੀ ਡੀਵਾਈਸ"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"ਕਨੈਕਟ ਕੀਤਾ ਡੀਵਾਈਸ"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ਇਸ ਤਬਦੀਲੀ ਨੂੰ ਲਾਗੂ ਕਰਨ ਲਈ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨੂੰ ਰੀਬੂਟ ਕਰਨਾ ਲਾਜ਼ਮੀ ਹੈ। ਹੁਣੇ ਰੀਬੂਟ ਕਰੋ ਜਾਂ ਰੱਦ ਕਰੋ।"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"ਤਾਰ ਵਾਲੇ ਹੈੱਡਫ਼ੋਨ"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"ਹੈੱਡਫ਼ੋਨ"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB ਸਪੀਕਰ"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB ਆਡੀਓ"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"ਮਾਈਕ ਜੈਕ"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB ਮਾਈਕ"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB ਮਾਈਕ੍ਰੋਫ਼ੋਨ"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ਚਾਲੂ"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ਬੰਦ"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"ਕੈਰੀਅਰ ਨੈੱਟਵਰਕ ਦੀ ਬਦਲੀ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index bb8fe2e40bfe..3786e02a109e 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Ten komputer (wewnętrzny)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (wewnętrzny)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Głośnik ze stacją dokującą"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Urządzenie zewnętrzne"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Połączone urządzenie"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Wprowadzenie zmiany wymaga ponownego uruchomienia urządzenia. Uruchom ponownie teraz lub anuluj."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Słuchawki przewodowe"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Słuchawki"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Głośnik USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Dźwięk przez USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Gniazdo mikrofonu"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Mikrofon USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Mikrofon USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Włączono"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Wyłączono"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Zmiana sieci operatora"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index e286643c5cf5..3a8b2b8ff1bc 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -687,10 +687,10 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"É necessário reinicializar o dispositivo para que a mudança seja aplicada. Faça isso agora ou cancele."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Fones de ouvido com fio"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Fone de ouvido"</string> - <!-- no translation found for media_transfer_usb_audio_name (1789292056757821355) --> - <skip /> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Áudio USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Entrada para microfone"</string> - <!-- no translation found for media_transfer_usb_device_mic_name (7171789543226269822) --> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Microfone USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ativado"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desativado"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index f489d916fbf0..7dbabb8032c3 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Este computador (interno)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Microfone (interno)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Altifalante estação carregamento"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo associado"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"É necessário reiniciar o dispositivo para aplicar esta alteração. Reinicie agora ou cancele."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Auscultadores com fios"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Auscultadores"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Altifalante USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Áudio USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Entrada para microfone"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Microfone USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Microfone USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ligado"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desligado"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Rede do operador em mudança."</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index 7f5bb0fa55dc..3a8b2b8ff1bc 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Este computador (interno)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Microfone (interno)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Alto-falante da base"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispositivo externo"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispositivo conectado"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"É necessário reinicializar o dispositivo para que a mudança seja aplicada. Faça isso agora ou cancele."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Fones de ouvido com fio"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Fone de ouvido"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Alto-falante USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Áudio USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Entrada para microfone"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Microfone USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Microfone USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ativado"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desativado"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Alteração de rede da operadora"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index f79c2e1e0634..9e0eb4fd7fde 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Acest computer (intern)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Microfon (intern)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Difuzorul dispozitivului de andocare"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Dispozitiv extern"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Dispozitiv conectat"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Pentru ca modificarea să se aplice, trebuie să repornești dispozitivul. Repornește-l acum sau anulează."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Căști cu fir"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Căști"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Difuzor USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Audio USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mufă pentru microfon"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Microfon USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Microfon USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activat"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Dezactivat"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Se schimbă rețeaua operatorului"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 1cdef05d8b18..dfde27267308 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Встроенный динамик компьютера"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Микрофон (встроенный)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Колонка с док-станцией"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Внешнее устройство"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Подключенное устройство"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Чтобы изменение вступило в силу, необходимо перезапустить устройство. Вы можете сделать это сейчас или позже."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Проводные наушники"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Наушники"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-колонка"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-аудиоустройство"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Микрофонный разъем"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB-микрофон"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-микрофон"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Вкл."</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Выкл."</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Сменить сеть"</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index 980f9c884358..fe011c773c2f 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"මෙම පරිගණකය (අභ්යන්තර)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"මයික්රෆෝනය (අභ්යන්තර)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ඩොක් ස්පීකරය"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"බාහිර උපාංගය"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"සම්බන්ධ කළ උපාංගය"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"මෙම වෙනස යෙදීමට ඔබේ උපාංගය නැවත පණ ගැන්විය යුතුය. දැන් නැවත පණ ගන්වන්න හෝ අවලංගු කරන්න."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"රැහැන්ගත හෙඩ්ෆෝන්"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"හෙඩ්ෆෝන්"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB ස්පීකරය"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB ශ්රව්ය"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"මයික් ජැක්කුව"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB මයික්"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB මයික්රෆෝනය"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ක්රියාත්මකයි"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ක්රියාවිරහිතයි"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"වාහක ජාලය වෙනස් වෙමින්"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index b1726498b8ce..46ab80aefb63 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Tento počítač (interný)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofón (vnútorný)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Reproduktor doku"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Externé zariadenie"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Pripojené zariadenie"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Zmena sa prejaví až po reštarte zariadenia. Môžete ho teraz reštartovať alebo akciu zrušiť."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Slúchadlá s káblom"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Slúchadlá"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Reproduktor s rozhraním USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Zvuk cez USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Konektor mikrofónu"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Mikrofón USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Mikrofón s rozhraním USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Zapnúť"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Vypnúť"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mení sa sieť operátora"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index 2ee12418c38a..0ea0d43eb4cd 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Ta računalnik (notranji)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (notranji)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Zvočnik nosilca"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Zunanja naprava"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Povezana naprava"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Napravo je treba znova zagnati, da bo ta sprememba uveljavljena. Znova zaženite zdaj ali prekličite."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Žične slušalke"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Slušalke"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Zvočnik USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Zvok USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Vtič za mikrofon"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Mikrofon USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Mikrofon USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Vklop"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Izklop"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Spreminjanje omrežja operaterja"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index 7c210637c360..54e75b2d6d61 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Ky kompjuter (i brendshëm)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofoni (i brendshëm)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Altoparlanti i stacionit"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Pajisja e jashtme"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Pajisja e lidhur"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Pajisja jote duhet të riniset që ky ndryshim të zbatohet. Rinise tani ose anuloje."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Kufje me tela"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Kufje"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Altoparlant me USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Pajisja audio me USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Fisha e mikrofonit"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Mikrofoni me USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Mikrofoni me USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktive"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Joaktive"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Rrjeti i operatorit celular po ndryshohet"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 34ccdaf0f19e..742e6ca29160 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Овај рачунар (интерно)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Микрофон (интерни)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Звучник базне станице"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Спољни уређај"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Повезани уређај"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Морате да рестартујете уређај да би се ова промена применила. Рестартујте га одмах или откажите."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Жичане слушалице"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Слушалице"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB звучник"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB аудио"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Утикач за микрофон"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB микрофон"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB микрофон"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Укључено"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Искључено"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Промена мреже мобилног оператера"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index c553c1d30125..b7269215e6e1 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Den här datorn (intern)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (inbyggd)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dockningsstationens högtalare"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Extern enhet"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Ansluten enhet"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Enheten måste startas om för att ändringen ska börja gälla. Starta om nu eller avbryt."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Hörlur med kabel"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Hörlur"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-högtalare"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-ljud"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofonuttag"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB-mikrofon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-mikrofon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"På"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Av"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Byter leverantörsnätverk"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index 6890d550f133..adc21db45db8 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Kompyuta hii (spika ya ndani)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Maikrofoni (ya ndani)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Spika ya kituo"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Kifaa cha Nje"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Kifaa kilichounganishwa"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Ni lazima uwashe tena kifaa chako ili mabadiliko haya yatekelezwe. Washa tena sasa au ughairi."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Kipokea sauti cha kichwani chenye waya"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Kipokea sauti cha kichwani"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Spika ya USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Sauti ya USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Pini ya maikrofoni"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Maikrofoni ya USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Maikrofoni ya USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Umewashwa"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Umezimwa"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mabadiliko katika mtandao wa mtoa huduma"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 5664290b0061..0e2698582b98 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"இந்தக் கம்ப்யூட்டர் (அகம்)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"மைக்ரோஃபோன் (அகம்)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"டாக் ஸ்பீக்கர்"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"வெளிப்புறச் சாதனம்"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"இணைக்கப்பட்டுள்ள சாதனம்"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"இந்த மாற்றங்கள் செயல்படுத்தப்பட உங்கள் சாதனத்தை மறுபடி தொடங்க வேண்டும். இப்போதே மறுபடி தொடங்கவும் அல்லது ரத்துசெய்யவும்."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"வயர்டு ஹெட்ஃபோன்"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"ஹெட்ஃபோன்"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB ஸ்பீக்கர்"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB ஆடியோ"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"மைக் ஜாக்"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB மைக்"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB மைக்ரோஃபோன்"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ஆன்"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ஆஃப்"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"மொபைல் நிறுவன நெட்வொர்க்கை மாற்றும்"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 56d0a7d5014b..0f835fa56d37 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"ఈ కంప్యూటర్ (ఇంటర్నల్)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"మైక్రోఫోన్ (అంతర్గతం)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"డాక్ స్పీకర్"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"ఎక్స్టర్నల్ పరికరం"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"కనెక్ట్ చేసిన పరికరం"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ఈ మార్పును వర్తింపజేయాలంటే మీరు మీ పరికరాన్ని తప్పనిసరిగా రీబూట్ చేయాలి. ఇప్పుడే రీబూట్ చేయండి లేదా రద్దు చేయండి."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"వైర్ ఉన్న హెడ్ఫోన్"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"హెడ్ఫోన్"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB స్పీకర్"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB ఆడియో"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"మైక్ జాక్"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB మైక్"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB మైక్రోఫోన్"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ఆన్లో ఉంది"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ఆఫ్లో ఉంది"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"క్యారియర్ నెట్వర్క్ మారుతోంది"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 28a0d64b5c75..b5deb55094a1 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"คอมพิวเตอร์เครื่องนี้ (ภายใน)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"ไมโครโฟน (ภายใน)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"แท่นชาร์จที่มีลำโพง"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"อุปกรณ์ภายนอก"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"อุปกรณ์ที่เชื่อมต่อ"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"คุณต้องรีบูตอุปกรณ์เพื่อให้การเปลี่ยนแปลงนี้มีผล รีบูตเลยหรือยกเลิก"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"หูฟังแบบใช้สาย"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"หูฟัง"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"ลำโพง USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"เสียง USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"ช่องเสียบไมค์"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"ไมค์ USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"ไมโครโฟน USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"เปิด"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ปิด"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"การเปลี่ยนเครือข่ายผู้ให้บริการ"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index 926ce8f65406..b664108ace23 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Sa computer na ito (internal)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikropono (internal)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Speaker ng dock"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"External na Device"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Nakakonektang device"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Dapat i-reboot ang iyong device para mailapat ang pagbabagong ito. Mag-reboot ngayon o kanselahin."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Wired na headphone"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Headphone"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB speaker"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Jack ng mikropono"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB na mikropono"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB na mikropono"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Naka-on"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Naka-off"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Nagpapalit ng carrier network"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 14c2108a134f..7cee87ecc6cb 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Bu bilgisayar (dahili)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (dahili)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Yuva hoparlörü"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Harici Cihaz"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Bağlı cihaz"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Bu değişikliğin geçerli olması için cihazınızın yeniden başlatılması gerekir. Şimdi yeniden başlatın veya iptal edin."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Kablolu kulaklık"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Kulaklık"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB hoparlör"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB ses cihazı"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofon jakı"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mikrofon"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB mikrofon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Açık"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Kapalı"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operatör ağı değiştiriliyor"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index 25475d573352..dd7f157f47b5 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Цей комп’ютер (внутрішній)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Мікрофон (внутрішній)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Динамік док-станції"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Зовнішній пристрій"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Підключений пристрій"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Щоб застосувати ці зміни, потрібний перезапуск. Перезапустіть пристрій або скасуйте зміни."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Дротові навушники"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Навушники"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB-динамік"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB-аудіо"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Гніздо для мікрофона"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB-мікрофон"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB-мікрофон"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Увімкнено"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Вимкнено"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Змінення мережі оператора"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index 2157f63325f1..23162cf5a929 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"یہ کمپیوٹر (داخلی)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"مائیکروفون (داخلی)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ڈاک اسپیکر"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"بیرونی آلہ"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"منسلک آلہ"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"اس تبدیلی کو لاگو کرنے کے ليے آپ کے آلہ کو ریبوٹ کرنا ضروری ہے۔ ابھی ریبوٹ کریں یا منسوخ کریں۔"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"تار والا ہیڈ فون"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"ہیڈ فون"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB اسپیکر"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB آڈیو"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"مائیک جیک"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB مائیک"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB مائیکروفون"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"آن"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"آف"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"کیریئر نیٹ ورک کی تبدیلی"</string> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 71fdae2a7714..8fa256fdedb0 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Bu kompyuter (ichki)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Mikrofon (ichki)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dok-stansiyali karnay"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Tashqi qurilma"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Ulangan qurilma"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Oʻzgarishlar kuchga kirishi uchun qurilmani oʻchirib yoqing. Buni hozir yoki keyinroq bajarishingiz mumkin."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Simli quloqlik"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Quloqlik"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB karnay"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB audio"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Mikrofon ulagichi"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB mik"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB mikrofon"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Yoniq"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Oʻchiq"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mobil tarmoqni o‘zgartirish"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index f53e8166c1e1..b4e09e0c36e3 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Máy tính này (nội bộ)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Micrô (bên trong)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Loa có gắn đế"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Thiết bị bên ngoài"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Thiết bị đã kết nối"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Bạn phải khởi động lại thiết bị để áp dụng sự thay đổi này. Hãy khởi động lại ngay hoặc hủy."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Tai nghe có dây"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Tai nghe"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Loa USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Âm thanh qua cổng USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Giắc cắm micrô"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"Micrô có cổng USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Micrô USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Đang bật"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Đang tắt"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Thay đổi mạng của nhà mạng"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 9275f1beed73..f9ce1c3df969 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"此计算机(内部)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"麦克风(内部)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"基座音箱"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"外部设备"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"连接的设备"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"设备必须重新启动才能应用此更改。您可以立即重新启动或取消。"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"有线耳机"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"头戴式耳机"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB 音箱"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB 音频"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"麦克风插孔"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB 麦克风"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB 麦克风"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"开启"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"关闭"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"运营商网络正在更改"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 4acc52ddc7b9..c50c7ba90165 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"此電腦 (內置)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"麥克風 (內置)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"插座喇叭"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"外部裝置"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"已連接的裝置"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"你的裝置必須重新開機,才能套用此變更。請立即重新開機或取消。"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"有線耳機"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"耳機"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB 喇叭"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB 音訊"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"麥克風插孔"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB 麥克風"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB 麥克風"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"開啟"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"關閉"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"流動網絡供應商網絡正在變更"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 8ded5d08edce..c5885dea3ae8 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"這部電腦 (內部)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"麥克風 (內部)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"座架喇叭"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"外部裝置"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"已連結的裝置"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"裝置必須重新啟動才能套用這項變更。請立即重新啟動或取消變更。"</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"有線耳機"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"耳機"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"USB 喇叭"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"USB 音訊"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"麥克風插孔"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"USB 麥克風"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"USB 麥克風"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"開啟"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"關閉"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"電信業者網路正在進行變更"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 972eed7be319..a39b436ff652 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -585,7 +585,6 @@ <string name="media_transfer_this_device_name_desktop" msgid="7912386128141470452">"Le khompyutha (ngaphakathi)"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> - <string name="media_transfer_internal_mic" msgid="797333824290228595">"Imakrofoni (okwangaphakathi)"</string> <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Isipikha sentuba"</string> <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Idivayisi Yangaphandle"</string> <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Idivayisi exhunyiwe"</string> @@ -688,9 +687,11 @@ <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Kufanele idivayisi yakho iqaliswe ukuze lolu shintsho lusebenze. Qalisa manje noma khansela."</string> <string name="media_transfer_wired_headphone_name" msgid="8698668536022665254">"Amahedifoni anentambo"</string> <string name="media_transfer_headphone_name" msgid="1131962659136578852">"Amahedifoni"</string> - <string name="media_transfer_usb_speaker_name" msgid="4736537022543593896">"Isipikha se-USB"</string> + <string name="media_transfer_usb_audio_name" msgid="1789292056757821355">"Umsindo we-USB"</string> <string name="media_transfer_wired_device_mic_name" msgid="7417067197803840965">"Umgodi we-earphone ye-mic"</string> - <string name="media_transfer_usb_device_mic_name" msgid="9189914846215516322">"I-mic ye-USB"</string> + <string name="media_transfer_usb_device_mic_name" msgid="7171789543226269822">"Imakrofoni ye-USB"</string> + <!-- no translation found for media_transfer_bt_device_mic_name (1870669402238687618) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Vuliwe"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Valiwe"</string> <string name="carrier_network_change_mode" msgid="4257621815706644026">"Inethiwekhi yenkampani yenethiwekhi iyashintsha"</string> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 8b9ec389e3fd..739c7d6bcfca 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1651,6 +1651,9 @@ <!-- Name of the usb audio device mic. [CHAR LIMIT=50] --> <string name="media_transfer_usb_device_mic_name">USB microphone</string> + <!-- Name of the bluetooth audio device mic. [CHAR LIMIT=50] --> + <string name="media_transfer_bt_device_mic_name">BT microphone</string> + <!-- Label for Wifi hotspot switch on. Toggles hotspot on [CHAR LIMIT=30] --> <string name="wifi_hotspot_switch_on_text">On</string> <!-- Label for Wifi hotspot switch off. Toggles hotspot off [CHAR LIMIT=30] --> diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index 9d56c77b097b..744e97e53fef 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -30,9 +30,10 @@ import android.hardware.usb.flags.Flags; import android.icu.text.NumberFormat; import android.location.LocationManager; import android.media.AudioManager; +import android.net.ConnectivityManager; import android.net.NetworkCapabilities; import android.net.TetheringManager; -import android.net.vcn.VcnTransportInfo; +import android.net.vcn.VcnUtils; import android.net.wifi.WifiInfo; import android.os.BatteryManager; import android.os.Build; @@ -737,14 +738,9 @@ public class Utils { * @param networkCapabilities NetworkCapabilities of the network. */ @Nullable - public static WifiInfo tryGetWifiInfoForVcn(NetworkCapabilities networkCapabilities) { - if (networkCapabilities.getTransportInfo() == null - || !(networkCapabilities.getTransportInfo() instanceof VcnTransportInfo)) { - return null; - } - VcnTransportInfo vcnTransportInfo = - (VcnTransportInfo) networkCapabilities.getTransportInfo(); - return vcnTransportInfo.getWifiInfo(); + public static WifiInfo tryGetWifiInfoForVcn( + ConnectivityManager connectivityMgr, NetworkCapabilities networkCapabilities) { + return VcnUtils.getWifiInfoFromVcnCaps(connectivityMgr, networkCapabilities); } /** Whether there is any incompatible chargers in the current UsbPort? */ diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java b/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java index c8bcabff1094..261c722e517c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java @@ -138,23 +138,37 @@ public class ServiceListing { } final PackageManager pmWrapper = mContext.getPackageManager(); + // Add requesting apps, with full validation List<ResolveInfo> installedServices = pmWrapper.queryIntentServicesAsUser( new Intent(mIntentAction), flags, user); for (ResolveInfo resolveInfo : installedServices) { ServiceInfo info = resolveInfo.serviceInfo; - if (!mPermission.equals(info.permission)) { - Slog.w(mTag, "Skipping " + mNoun + " service " - + info.packageName + "/" + info.name - + ": it does not require the permission " - + mPermission); - continue; + if (!mEnabledServices.contains(info.getComponentName())) { + if (!mPermission.equals(info.permission)) { + Slog.w(mTag, "Skipping " + mNoun + " service " + + info.packageName + "/" + info.name + + ": it does not require the permission " + + mPermission); + continue; + } + if (mValidator != null && !mValidator.test(info)) { + continue; + } + mServices.add(info); } - if (mValidator != null && !mValidator.test(info)) { - continue; + } + + // Add all apps with access, in case prior approval was granted without full validation + for (ComponentName cn : mEnabledServices) { + List<ResolveInfo> enabledServices = pmWrapper.queryIntentServicesAsUser( + new Intent().setComponent(cn), flags, user); + for (ResolveInfo resolveInfo : enabledServices) { + ServiceInfo info = resolveInfo.serviceInfo; + mServices.add(info); } - mServices.add(info); } + for (Callback callback : mCallbacks) { callback.onServicesReloaded(mServices); } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 92da2be60d1e..8845d2ee5369 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -38,7 +38,6 @@ import android.os.Looper; import android.os.Message; import android.os.ParcelUuid; import android.os.SystemClock; -import android.provider.Settings; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.style.ForegroundColorSpan; @@ -1291,12 +1290,10 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> if (BluetoothUtils.hasConnectedBroadcastSource(this, mBluetoothManager)) { // Gets summary for the buds which are in the audio sharing. int groupId = BluetoothUtils.getGroupId(this); - if (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID - && groupId - == Settings.Secure.getInt( - mContext.getContentResolver(), - "bluetooth_le_broadcast_fallback_active_group_id", - BluetoothCsipSetCoordinator.GROUP_ID_INVALID)) { + int primaryGroupId = BluetoothUtils.getPrimaryGroupIdForBroadcast( + mContext.getContentResolver()); + if ((primaryGroupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) + ? (groupId == primaryGroupId) : isActiveDevice(BluetoothProfile.LE_AUDIO)) { // The buds are primary buds return getSummaryWithBatteryInfo( R.string.bluetooth_active_battery_level_untethered, diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/ActionSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/ActionSwitchPreference.java index 1cbb8b4faaa8..2b9088f39b6a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/ActionSwitchPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/ActionSwitchPreference.java @@ -16,7 +16,6 @@ package com.android.settingslib.bluetooth.devicesettings; -import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Parcel; @@ -36,7 +35,7 @@ public class ActionSwitchPreference extends DeviceSettingPreference implements P private final String mTitle; private final String mSummary; private final Bitmap mIcon; - private final Intent mIntent; + private final DeviceSettingAction mAction; private final boolean mHasSwitch; private final boolean mChecked; private final boolean mIsAllowedChangingState; @@ -46,7 +45,7 @@ public class ActionSwitchPreference extends DeviceSettingPreference implements P String title, @Nullable String summary, @Nullable Bitmap icon, - @Nullable Intent intent, + @NonNull DeviceSettingAction action, boolean hasSwitch, boolean checked, boolean allowChangingState, @@ -56,7 +55,7 @@ public class ActionSwitchPreference extends DeviceSettingPreference implements P mTitle = title; mSummary = summary; mIcon = icon; - mIntent = intent; + mAction = action; mHasSwitch = hasSwitch; mChecked = checked; mIsAllowedChangingState = allowChangingState; @@ -79,13 +78,13 @@ public class ActionSwitchPreference extends DeviceSettingPreference implements P String title = in.readString(); String summary = in.readString(); Bitmap icon = in.readParcelable(Bitmap.class.getClassLoader()); - Intent intent = in.readParcelable(Intent.class.getClassLoader()); + DeviceSettingAction action = DeviceSettingAction.readFromParcel(in); boolean hasSwitch = in.readBoolean(); boolean checked = in.readBoolean(); boolean allowChangingState = in.readBoolean(); Bundle extras = in.readBundle(Bundle.class.getClassLoader()); return new ActionSwitchPreference( - title, summary, icon, intent, hasSwitch, checked, allowChangingState, extras); + title, summary, icon, action, hasSwitch, checked, allowChangingState, extras); } public static final Creator<ActionSwitchPreference> CREATOR = @@ -115,7 +114,7 @@ public class ActionSwitchPreference extends DeviceSettingPreference implements P dest.writeString(mTitle); dest.writeString(mSummary); dest.writeParcelable(mIcon, flags); - dest.writeParcelable(mIntent, flags); + mAction.writeToParcel(dest, flags); dest.writeBoolean(mHasSwitch); dest.writeBoolean(mChecked); dest.writeBoolean(mIsAllowedChangingState); @@ -127,7 +126,7 @@ public class ActionSwitchPreference extends DeviceSettingPreference implements P private String mTitle; private String mSummary; private Bitmap mIcon; - private Intent mIntent; + private DeviceSettingAction mAction = DeviceSettingAction.EMPTY_ACTION; private boolean mHasSwitch; private boolean mChecked; private boolean mIsAllowedChangingState; @@ -170,14 +169,14 @@ public class ActionSwitchPreference extends DeviceSettingPreference implements P } /** - * Sets the Intent to launch when the preference is clicked, optional. + * Sets the action to trigger when the preference is clicked, optional. * - * @param intent The Intent. + * @param action The action to trigger. * @return Returns the Builder object. */ @NonNull - public Builder setIntent(@Nullable Intent intent) { - mIntent = intent; + public Builder setAction(@Nullable DeviceSettingAction action) { + mAction = action == null ? DeviceSettingAction.EMPTY_ACTION : action; return this; } @@ -239,7 +238,7 @@ public class ActionSwitchPreference extends DeviceSettingPreference implements P mTitle, mSummary, mIcon, - mIntent, + mAction, mHasSwitch, mChecked, mIsAllowedChangingState, @@ -278,13 +277,13 @@ public class ActionSwitchPreference extends DeviceSettingPreference implements P } /** - * Gets the Intent to launch when the preference is clicked. + * Gets the action to trigger when the preference is clicked. * * @return Returns the intent to launch. */ - @Nullable - public Intent getIntent() { - return mIntent; + @NonNull + public DeviceSettingAction getAction() { + return mAction; } /** diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingAction.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingAction.java new file mode 100644 index 000000000000..01783e01e971 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingAction.java @@ -0,0 +1,61 @@ +/* + * 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; + +import android.os.Parcel; + +import androidx.annotation.NonNull; + +/** An abstract class representing a device setting action. */ +public abstract class DeviceSettingAction { + @DeviceSettingActionType private final int mActionType; + + public static final DeviceSettingAction EMPTY_ACTION = + new DeviceSettingAction(DeviceSettingActionType.DEVICE_SETTING_ACTION_TYPE_UNKNOWN) {}; + + protected DeviceSettingAction(@DeviceSettingActionType int actionType) { + mActionType = actionType; + } + + /** Read a {@link DeviceSettingPreference} instance from {@link Parcel} */ + @NonNull + public static DeviceSettingAction readFromParcel(@NonNull Parcel in) { + int type = in.readInt(); + return switch (type) { + case DeviceSettingActionType.DEVICE_SETTING_ACTION_TYPE_INTENT -> + DeviceSettingIntentAction.readFromParcel(in); + case DeviceSettingActionType.DEVICE_SETTING_ACTION_TYPE_PENDING_INTENT -> + DeviceSettingPendingIntentAction.readFromParcel(in); + default -> EMPTY_ACTION; + }; + } + + /** Writes the instance to {@link Parcel}. */ + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mActionType); + } + + /** + * Gets the setting action type, as defined by IntDef {@link DeviceSettingActionType}. + * + * @return the setting action type. + */ + @DeviceSettingType + public int getActionType() { + return mActionType; + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingActionType.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingActionType.java new file mode 100644 index 000000000000..13d3583f1928 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingActionType.java @@ -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. + */ + +package com.android.settingslib.bluetooth.devicesettings; + +import androidx.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.SOURCE) +@IntDef( + value = { + DeviceSettingActionType.DEVICE_SETTING_ACTION_TYPE_UNKNOWN, + DeviceSettingActionType.DEVICE_SETTING_ACTION_TYPE_INTENT, + DeviceSettingActionType.DEVICE_SETTING_ACTION_TYPE_PENDING_INTENT, + }, + open = true) +public @interface DeviceSettingActionType { + /** Device setting action type is unknown. */ + int DEVICE_SETTING_ACTION_TYPE_UNKNOWN = 0; + + /** Device setting action is an intent to start an activity. */ + int DEVICE_SETTING_ACTION_TYPE_INTENT = 1; + + /** Device setting action is a pending intent. */ + int DEVICE_SETTING_ACTION_TYPE_PENDING_INTENT = 2; +} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingIntentAction.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingIntentAction.java new file mode 100644 index 000000000000..a1136e65576d --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingIntentAction.java @@ -0,0 +1,132 @@ +/* + * 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; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +import java.util.Objects; + +/** An abstract class representing a device setting action. */ +public class DeviceSettingIntentAction extends DeviceSettingAction implements Parcelable { + private final Intent mIntent; + private final Bundle mExtras; + + DeviceSettingIntentAction(@NonNull Intent intent, @NonNull Bundle extras) { + super(DeviceSettingActionType.DEVICE_SETTING_ACTION_TYPE_INTENT); + validate(intent); + mIntent = intent; + mExtras = extras; + } + + private static void validate(Intent intent) { + if (Objects.isNull(intent)) { + throw new IllegalArgumentException("Intent must be set"); + } + } + + /** Read a {@link DeviceSettingIntentAction} instance from {@link Parcel} */ + @NonNull + public static DeviceSettingIntentAction readFromParcel(@NonNull Parcel in) { + Intent intent = in.readParcelable(Intent.class.getClassLoader()); + Bundle extras = in.readBundle(Bundle.class.getClassLoader()); + return new DeviceSettingIntentAction(intent, extras); + } + + public static final Creator<DeviceSettingIntentAction> CREATOR = + new Creator<>() { + @Override + @NonNull + public DeviceSettingIntentAction createFromParcel(@NonNull Parcel in) { + in.readInt(); + return readFromParcel(in); + } + + @Override + @NonNull + public DeviceSettingIntentAction[] newArray(int size) { + return new DeviceSettingIntentAction[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + /** Writes the instance to {@link Parcel}. */ + public void writeToParcel(@NonNull Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeParcelable(mIntent, flags); + dest.writeBundle(mExtras); + } + + /** Builder class for {@link DeviceSettingFooterPreference}. */ + public static final class Builder { + private Intent mIntent = null; + private Bundle mExtras = Bundle.EMPTY; + + /** + * Sets the intent for the action. + * + * @param intent The intent. + * @return Returns the Builder object. + */ + @NonNull + public Builder setIntent(@NonNull Intent intent) { + mIntent = intent; + return this; + } + + /** + * Sets the extras bundle. + * + * @return Returns the Builder object. + */ + @NonNull + public Builder setExtras(@NonNull Bundle extras) { + mExtras = extras; + return this; + } + + /** + * Builds the {@link DeviceSettingIntentAction} object. + * + * @return Returns the built {@link DeviceSettingIntentAction} object. + */ + @NonNull + public DeviceSettingIntentAction build() { + return new DeviceSettingIntentAction(mIntent, mExtras); + } + } + + /** Gets the intent. */ + @NonNull + public Intent getIntent() { + return mIntent; + } + + /** Gets the extra bundle. */ + @NonNull + public Bundle getExtras() { + return mExtras; + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingPendingIntentAction.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingPendingIntentAction.java new file mode 100644 index 000000000000..3d4282cfb6e4 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingPendingIntentAction.java @@ -0,0 +1,133 @@ +/* + * 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; + +import android.app.PendingIntent; +import android.content.Intent; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +import java.util.Objects; + +/** An abstract class representing a device setting action. */ +public class DeviceSettingPendingIntentAction extends DeviceSettingAction implements Parcelable { + private final PendingIntent mPendingIntent; + private final Bundle mExtras; + + DeviceSettingPendingIntentAction(@NonNull PendingIntent pendingIntent, @NonNull Bundle extras) { + super(DeviceSettingActionType.DEVICE_SETTING_ACTION_TYPE_PENDING_INTENT); + validate(pendingIntent); + mPendingIntent = pendingIntent; + mExtras = extras; + } + + private static void validate(PendingIntent pendingIntent) { + if (Objects.isNull(pendingIntent)) { + throw new IllegalArgumentException("PendingIntent must be set"); + } + } + + /** Read a {@link DeviceSettingPendingIntentAction} instance from {@link Parcel} */ + @NonNull + public static DeviceSettingPendingIntentAction readFromParcel(@NonNull Parcel in) { + PendingIntent pendingIntent = in.readParcelable(Intent.class.getClassLoader()); + Bundle extras = in.readBundle(Bundle.class.getClassLoader()); + return new DeviceSettingPendingIntentAction(pendingIntent, extras); + } + + public static final Creator<DeviceSettingPendingIntentAction> CREATOR = + new Creator<>() { + @Override + @NonNull + public DeviceSettingPendingIntentAction createFromParcel(@NonNull Parcel in) { + in.readInt(); + return readFromParcel(in); + } + + @Override + @NonNull + public DeviceSettingPendingIntentAction[] newArray(int size) { + return new DeviceSettingPendingIntentAction[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + /** Writes the instance to {@link Parcel}. */ + public void writeToParcel(@NonNull Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeParcelable(mPendingIntent, flags); + dest.writeBundle(mExtras); + } + + /** Builder class for {@link DeviceSettingFooterPreference}. */ + public static final class Builder { + private PendingIntent mPendingIntent = null; + private Bundle mExtras = Bundle.EMPTY; + + /** + * Sets the intent for the action. + * + * @param pendingIntent The pending intent. + * @return Returns the Builder object. + */ + @NonNull + public Builder setPendingIntent(@NonNull PendingIntent pendingIntent) { + mPendingIntent = pendingIntent; + return this; + } + + /** + * Sets the extras bundle. + * + * @return Returns the Builder object. + */ + @NonNull + public Builder setExtras(@NonNull Bundle extras) { + mExtras = extras; + return this; + } + + /** + * Builds the {@link DeviceSettingPendingIntentAction} object. + * + * @return Returns the built {@link DeviceSettingPendingIntentAction} object. + */ + @NonNull + public DeviceSettingPendingIntentAction build() { + return new DeviceSettingPendingIntentAction(mPendingIntent, mExtras); + } + } + + /** Gets the pending intent. */ + @NonNull + public PendingIntent getPendingIntent() { + return mPendingIntent; + } + + /** Gets the extra bundle. */ + @NonNull + public Bundle getExtras() { + return mExtras; + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingType.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingType.java index ae3bf5e3fc72..3cc13431fb69 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingType.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingType.java @@ -28,6 +28,7 @@ import java.lang.annotation.RetentionPolicy; DeviceSettingType.DEVICE_SETTING_TYPE_ACTION_SWITCH, DeviceSettingType.DEVICE_SETTING_TYPE_MULTI_TOGGLE, DeviceSettingType.DEVICE_SETTING_TYPE_FOOTER, + DeviceSettingType.DEVICE_SETTING_TYPE_HELP, }, open = true) public @interface DeviceSettingType { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt index 851b614f5279..8537897cb329 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt @@ -22,14 +22,18 @@ import android.text.TextUtils import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.settingslib.bluetooth.devicesettings.ActionSwitchPreference import com.android.settingslib.bluetooth.devicesettings.DeviceSetting +import com.android.settingslib.bluetooth.devicesettings.DeviceSettingAction import com.android.settingslib.bluetooth.devicesettings.DeviceSettingContract +import com.android.settingslib.bluetooth.devicesettings.DeviceSettingFooterPreference +import com.android.settingslib.bluetooth.devicesettings.DeviceSettingHelpPreference import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId +import com.android.settingslib.bluetooth.devicesettings.DeviceSettingIntentAction import com.android.settingslib.bluetooth.devicesettings.DeviceSettingItem +import com.android.settingslib.bluetooth.devicesettings.DeviceSettingPendingIntentAction import com.android.settingslib.bluetooth.devicesettings.DeviceSettingsConfig -import com.android.settingslib.bluetooth.devicesettings.DeviceSettingFooterPreference -import com.android.settingslib.bluetooth.devicesettings.DeviceSettingHelpPreference import com.android.settingslib.bluetooth.devicesettings.MultiTogglePreference import com.android.settingslib.bluetooth.devicesettings.ToggleInfo +import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingActionModel import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel.AppProvidedItem import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel.BuiltinItem.BluetoothProfilesItem @@ -58,7 +62,7 @@ interface DeviceSettingRepository { /** Gets device setting for the bluetooth device. */ fun getDeviceSetting( cachedDevice: CachedBluetoothDevice, - @DeviceSettingId settingId: Int + @DeviceSettingId settingId: Int, ): Flow<DeviceSettingModel?> } @@ -84,7 +88,8 @@ class DeviceSettingRepositoryImpl( coroutineScope, backgroundCoroutineContext, ) - }) + } + ) override suspend fun getDeviceSettingsConfig( cachedDevice: CachedBluetoothDevice @@ -93,7 +98,7 @@ class DeviceSettingRepositoryImpl( override fun getDeviceSetting( cachedDevice: CachedBluetoothDevice, - settingId: Int + settingId: Int, ): Flow<DeviceSettingModel?> = connectionCache.get(cachedDevice).let { connection -> connection.getDeviceSetting(settingId).map { it?.toModel(cachedDevice, connection) } @@ -103,7 +108,8 @@ class DeviceSettingRepositoryImpl( DeviceSettingConfigModel( mainItems = mainContentItems.map { it.toModel() }, moreSettingsItems = moreSettingsItems.map { it.toModel() }, - moreSettingsHelpItem = moreSettingsHelpItem?.toModel(), ) + moreSettingsHelpItem = moreSettingsHelpItem?.toModel(), + ) private fun DeviceSettingItem.toModel(): DeviceSettingConfigItemModel { return if (!TextUtils.isEmpty(preferenceKey)) { @@ -113,7 +119,7 @@ class DeviceSettingRepositoryImpl( highlighted, preferenceKey!!, extras.getStringArrayList(DeviceSettingContract.INVISIBLE_PROFILES) - ?: emptyList() + ?: emptyList(), ) } else { CommonBuiltinItem(settingId, highlighted, preferenceKey!!) @@ -123,9 +129,17 @@ class DeviceSettingRepositoryImpl( } } + private fun DeviceSettingAction.toModel(): DeviceSettingActionModel? = + when (this) { + is DeviceSettingIntentAction -> DeviceSettingActionModel.IntentAction(this.intent) + is DeviceSettingPendingIntentAction -> + DeviceSettingActionModel.PendingIntentAction(this.pendingIntent) + else -> null + } + private fun DeviceSetting.toModel( cachedDevice: CachedBluetoothDevice, - connection: DeviceSettingServiceConnection + connection: DeviceSettingServiceConnection, ): DeviceSettingModel = when (val pref = preference) { is ActionSwitchPreference -> @@ -136,7 +150,7 @@ class DeviceSettingRepositoryImpl( summary = pref.summary, icon = pref.icon?.let { DeviceSettingIcon.BitmapIcon(it) }, isAllowedChangingState = pref.isAllowedChangingState, - intent = pref.intent, + action = pref.action?.toModel(), switchState = if (pref.hasSwitch()) { DeviceSettingStateModel.ActionSwitchPreferenceState(pref.checked) @@ -145,10 +159,7 @@ class DeviceSettingRepositoryImpl( }, updateState = { newState -> coroutineScope.launch(backgroundCoroutineContext) { - connection.updateDeviceSettings( - settingId, - newState.toParcelable(), - ) + connection.updateDeviceSettings(settingId, newState.toParcelable()) } }, ) @@ -167,12 +178,18 @@ class DeviceSettingRepositoryImpl( } }, ) - is DeviceSettingFooterPreference -> DeviceSettingModel.FooterPreference( - cachedDevice = cachedDevice, - id = settingId, footerText = pref.footerText) - is DeviceSettingHelpPreference -> DeviceSettingModel.HelpPreference( - cachedDevice = cachedDevice, - id = settingId, intent = pref.intent) + is DeviceSettingFooterPreference -> + DeviceSettingModel.FooterPreference( + cachedDevice = cachedDevice, + id = settingId, + footerText = pref.footerText, + ) + is DeviceSettingHelpPreference -> + DeviceSettingModel.HelpPreference( + cachedDevice = cachedDevice, + id = settingId, + intent = pref.intent, + ) else -> DeviceSettingModel.Unknown(cachedDevice, settingId) } 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 index 73648acd801e..4d9f2d67dda9 100644 --- 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 @@ -16,6 +16,7 @@ package com.android.settingslib.bluetooth.devicesettings.shared.model +import android.app.PendingIntent import android.content.Intent import android.graphics.Bitmap import androidx.annotation.DrawableRes @@ -34,7 +35,7 @@ sealed interface DeviceSettingModel { val title: String, val summary: String? = null, val icon: DeviceSettingIcon? = null, - val intent: Intent? = null, + val action: DeviceSettingActionModel? = null, val switchState: DeviceSettingStateModel.ActionSwitchPreferenceState? = null, val isAllowedChangingState: Boolean = true, val updateState: ((DeviceSettingStateModel.ActionSwitchPreferenceState) -> Unit)? = null, @@ -83,3 +84,11 @@ sealed interface DeviceSettingIcon { data class ResourceIcon(@DrawableRes val resId: Int) : DeviceSettingIcon } + +/** Models an action in device settings. */ +sealed interface DeviceSettingActionModel { + + data class IntentAction(val intent: Intent) : DeviceSettingActionModel + + data class PendingIntentAction(val pendingIntent: PendingIntent) : DeviceSettingActionModel +} diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InputMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InputMediaDevice.java index e44a13491758..1d17b004fb6a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InputMediaDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InputMediaDevice.java @@ -15,6 +15,7 @@ */ package com.android.settingslib.media; +import static android.media.AudioDeviceInfo.TYPE_BLUETOOTH_SCO; import static android.media.AudioDeviceInfo.TYPE_BUILTIN_MIC; import static android.media.AudioDeviceInfo.TYPE_USB_ACCESSORY; import static android.media.AudioDeviceInfo.TYPE_USB_DEVICE; @@ -90,7 +91,8 @@ public class InputMediaDevice extends MediaDevice { TYPE_WIRED_HEADSET, TYPE_USB_DEVICE, TYPE_USB_HEADSET, - TYPE_USB_ACCESSORY -> + TYPE_USB_ACCESSORY, + TYPE_BLUETOOTH_SCO -> true; default -> false; }; @@ -103,6 +105,8 @@ public class InputMediaDevice extends MediaDevice { R.string.media_transfer_wired_device_mic_name); case TYPE_USB_DEVICE, TYPE_USB_HEADSET, TYPE_USB_ACCESSORY -> mContext.getString( R.string.media_transfer_usb_device_mic_name); + case TYPE_BLUETOOTH_SCO -> mContext.getString( + R.string.media_transfer_bt_device_mic_name); default -> mContext.getString(R.string.media_transfer_this_device_name_desktop); }; return name.toString(); diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java index 015356e013b7..cea3d17f116d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java @@ -30,6 +30,7 @@ import android.net.NetworkScoreManager; import android.net.ScoredNetwork; import android.net.TransportInfo; import android.net.vcn.VcnTransportInfo; +import android.net.vcn.VcnUtils; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiNetworkScoreCache; @@ -394,10 +395,7 @@ public class WifiStatusTracker { TransportInfo transportInfo = networkCapabilities.getTransportInfo(); if (transportInfo instanceof VcnTransportInfo) { - // This VcnTransportInfo logic is copied from - // [com.android.settingslib.Utils.tryGetWifiInfoForVcn]. It's copied instead of - // re-used because it makes the logic here clearer. - return ((VcnTransportInfo) transportInfo).getWifiInfo(); + return VcnUtils.getWifiInfoFromVcnCaps(mConnectivityManager, networkCapabilities); } else if (transportInfo instanceof WifiInfo) { return (WifiInfo) transportInfo; } else { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java index 7ff0988c494d..feef559dfe26 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; @@ -29,6 +30,7 @@ import static org.mockito.Mockito.when; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; @@ -42,6 +44,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatcher; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; @@ -72,19 +75,26 @@ public class ServiceListingTest { .build(); } + private ArgumentMatcher<Intent> filterEquals(Intent intent) { + return (test) -> { + return intent.filterEquals(test); + }; + } + @Test public void testValidator() { ServiceInfo s1 = new ServiceInfo(); s1.permission = "testPermission"; s1.packageName = "pkg"; + s1.name = "Service1"; ServiceInfo s2 = new ServiceInfo(); s2.permission = "testPermission"; s2.packageName = "pkg2"; + s2.name = "service2"; ResolveInfo r1 = new ResolveInfo(); r1.serviceInfo = s1; ResolveInfo r2 = new ResolveInfo(); r2.serviceInfo = s2; - when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn( ImmutableList.of(r1, r2)); @@ -118,9 +128,11 @@ public class ServiceListingTest { ServiceInfo s1 = new ServiceInfo(); s1.permission = "testPermission"; s1.packageName = "pkg"; + s1.name = "Service1"; ServiceInfo s2 = new ServiceInfo(); s2.permission = "testPermission"; s2.packageName = "pkg2"; + s2.name = "service2"; ResolveInfo r1 = new ResolveInfo(); r1.serviceInfo = s1; ResolveInfo r2 = new ResolveInfo(); @@ -193,4 +205,56 @@ public class ServiceListingTest { assertThat(Settings.Secure.getString(RuntimeEnvironment.application.getContentResolver(), TEST_SETTING)).contains(testComponent2.flattenToString()); } + + @Test + public void testHasPermissionWithoutMeetingCurrentRegs() { + ServiceInfo s1 = new ServiceInfo(); + s1.permission = "testPermission"; + s1.packageName = "pkg"; + s1.name = "Service1"; + ServiceInfo s2 = new ServiceInfo(); + s2.permission = "testPermission"; + s2.packageName = "pkg2"; + s2.name = "service2"; + ResolveInfo r1 = new ResolveInfo(); + r1.serviceInfo = s1; + ResolveInfo r2 = new ResolveInfo(); + r2.serviceInfo = s2; + + ComponentName approvedComponent = new ComponentName(s2.packageName, s2.name); + + Settings.Secure.putString( + mContext.getContentResolver(), TEST_SETTING, approvedComponent.flattenToString()); + + when(mPm.queryIntentServicesAsUser(argThat( + filterEquals(new Intent(TEST_INTENT))), anyInt(), anyInt())) + .thenReturn(ImmutableList.of(r1)); + when(mPm.queryIntentServicesAsUser(argThat( + filterEquals(new Intent().setComponent(approvedComponent))), + anyInt(), anyInt())) + .thenReturn(ImmutableList.of(r2)); + + mServiceListing = new ServiceListing.Builder(mContext) + .setTag("testTag") + .setSetting(TEST_SETTING) + .setNoun("testNoun") + .setIntentAction(TEST_INTENT) + .setValidator(info -> { + if (info.packageName.equals("pkg")) { + return true; + } + return false; + }) + .setPermission("testPermission") + .build(); + ServiceListing.Callback callback = mock(ServiceListing.Callback.class); + mServiceListing.addCallback(callback); + mServiceListing.reload(); + + verify(mPm, times(2)).queryIntentServicesAsUser(any(), anyInt(), anyInt()); + ArgumentCaptor<List<ServiceInfo>> captor = ArgumentCaptor.forClass(List.class); + verify(callback, times(1)).onServicesReloaded(captor.capture()); + + assertThat(captor.getValue()).containsExactlyElementsIn(ImmutableList.of(s2, s1)); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java index 0d814947527c..70cb2ef016ec 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java @@ -1977,12 +1977,12 @@ public class CachedBluetoothDeviceTest { } @Test - public void getConnectionSummary_isBroadcastPrimary_returnActive() { + public void getConnectionSummary_isBroadcastPrimary_fallbackDevice_returnActive() { when(mBroadcast.isEnabled(any())).thenReturn(true); when(mCachedDevice.getDevice()).thenReturn(mDevice); Settings.Secure.putInt( mContext.getContentResolver(), - "bluetooth_le_broadcast_fallback_active_group_id", + BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), 1); List<Long> bisSyncState = new ArrayList<>(); @@ -1992,12 +1992,30 @@ public class CachedBluetoothDeviceTest { sourceList.add(mLeBroadcastReceiveState); when(mAssistant.getAllSources(any())).thenReturn(sourceList); - when(mCachedDevice.getGroupId()) - .thenReturn( - Settings.Secure.getInt( - mContext.getContentResolver(), - "bluetooth_le_broadcast_fallback_active_group_id", - BluetoothCsipSetCoordinator.GROUP_ID_INVALID)); + when(mCachedDevice.getGroupId()).thenReturn(1); + + assertThat(mCachedDevice.getConnectionSummary(false)) + .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level)); + } + + @Test + public void getConnectionSummary_isBroadcastPrimary_activeDevice_returnActive() { + when(mBroadcast.isEnabled(any())).thenReturn(true); + when(mCachedDevice.getDevice()).thenReturn(mDevice); + Settings.Secure.putInt( + mContext.getContentResolver(), + BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + + List<Long> bisSyncState = new ArrayList<>(); + bisSyncState.add(1L); + when(mLeBroadcastReceiveState.getBisSyncState()).thenReturn(bisSyncState); + List<BluetoothLeBroadcastReceiveState> sourceList = new ArrayList<>(); + sourceList.add(mLeBroadcastReceiveState); + when(mAssistant.getAllSources(any())).thenReturn(sourceList); + + when(mCachedDevice.getGroupId()).thenReturn(1); + when(mCachedDevice.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true); assertThat(mCachedDevice.getConnectionSummary(false)) .isEqualTo(mContext.getString(R.string.bluetooth_active_no_battery_level)); @@ -2009,7 +2027,7 @@ public class CachedBluetoothDeviceTest { when(mCachedDevice.getDevice()).thenReturn(mDevice); Settings.Secure.putInt( mContext.getContentResolver(), - "bluetooth_le_broadcast_fallback_active_group_id", + BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), 1); List<Long> bisSyncState = new ArrayList<>(); diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/ActionSwitchPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/ActionSwitchPreferenceTest.java index 354d0f658544..7148618aaedb 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/ActionSwitchPreferenceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/ActionSwitchPreferenceTest.java @@ -50,11 +50,15 @@ public final class ActionSwitchPreferenceTest { @Test public void build_withAllFields_successfully() { + DeviceSettingIntentAction action = + new DeviceSettingIntentAction.Builder() + .setIntent(new Intent("intent_action")) + .build(); ActionSwitchPreference unused = new ActionSwitchPreference.Builder() .setTitle("title") .setSummary("summary") - .setIntent(new Intent("intent_action")) + .setAction(action) .setIcon(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)) .setHasSwitch(true) .setChecked(true) @@ -65,14 +69,17 @@ public final class ActionSwitchPreferenceTest { @Test public void getMethods() { - Intent intent = new Intent("intent_action"); + DeviceSettingIntentAction action = + new DeviceSettingIntentAction.Builder() + .setIntent(new Intent("intent_action")) + .build(); Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); - ActionSwitchPreference preference = builder().setIcon(icon).setIntent(intent).build(); + ActionSwitchPreference preference = builder().setIcon(icon).setAction(action).build(); assertThat(preference.getTitle()).isEqualTo("title"); assertThat(preference.getSummary()).isEqualTo("summary"); assertThat(preference.getIcon()).isSameInstanceAs(icon); - assertThat(preference.getIntent()).isSameInstanceAs(intent); + assertThat(preference.getAction()).isSameInstanceAs(action); assertThat(preference.hasSwitch()).isTrue(); assertThat(preference.getChecked()).isTrue(); assertThat(preference.isAllowedChangingState()).isTrue(); @@ -81,16 +88,20 @@ public final class ActionSwitchPreferenceTest { @Test public void parcelOperation() { - Intent intent = new Intent("intent_action"); + DeviceSettingIntentAction action = + new DeviceSettingIntentAction.Builder() + .setIntent(new Intent("intent_action")) + .build(); Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); - ActionSwitchPreference preference = builder().setIcon(icon).setIntent(intent).build(); + ActionSwitchPreference preference = builder().setIcon(icon).setAction(action).build(); ActionSwitchPreference fromParcel = writeAndRead(preference); assertThat(fromParcel.getTitle()).isEqualTo(preference.getTitle()); assertThat(fromParcel.getSummary()).isEqualTo(preference.getSummary()); assertThat(fromParcel.getIcon().sameAs(preference.getIcon())).isTrue(); - assertThat(fromParcel.getIntent().getAction()).isSameInstanceAs("intent_action"); + assertThat(((DeviceSettingIntentAction) fromParcel.getAction()).getIntent().getAction()) + .isEqualTo("intent_action"); assertThat(fromParcel.hasSwitch()).isEqualTo(preference.hasSwitch()); assertThat(fromParcel.getChecked()).isEqualTo(preference.getChecked()); assertThat(fromParcel.isAllowedChangingState()) @@ -102,14 +113,15 @@ public final class ActionSwitchPreferenceTest { @Test public void parcelOperation_noIntent() { Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); - ActionSwitchPreference preference = builder().setIcon(icon).setIntent(null).build(); + ActionSwitchPreference preference = builder().setIcon(icon).setAction(null).build(); ActionSwitchPreference fromParcel = writeAndRead(preference); assertThat(fromParcel.getTitle()).isEqualTo(preference.getTitle()); assertThat(fromParcel.getSummary()).isEqualTo(preference.getSummary()); assertThat(fromParcel.getIcon().sameAs(preference.getIcon())).isTrue(); - assertThat(preference.getIntent()).isNull(); + assertThat(preference.getAction().getActionType()) + .isEqualTo(DeviceSettingActionType.DEVICE_SETTING_ACTION_TYPE_UNKNOWN); assertThat(fromParcel.hasSwitch()).isEqualTo(preference.hasSwitch()); assertThat(fromParcel.getChecked()).isEqualTo(preference.getChecked()); assertThat(fromParcel.isAllowedChangingState()) @@ -120,15 +132,19 @@ public final class ActionSwitchPreferenceTest { @Test public void parcelOperation_noIcon() { - Intent intent = new Intent("intent_action"); - ActionSwitchPreference preference = builder().setIcon(null).setIntent(intent).build(); + DeviceSettingIntentAction action = + new DeviceSettingIntentAction.Builder() + .setIntent(new Intent("intent_action")) + .build(); + ActionSwitchPreference preference = builder().setIcon(null).setAction(action).build(); ActionSwitchPreference fromParcel = writeAndRead(preference); assertThat(fromParcel.getTitle()).isEqualTo(preference.getTitle()); assertThat(fromParcel.getSummary()).isEqualTo(preference.getSummary()); assertThat(fromParcel.getIcon()).isNull(); - assertThat(fromParcel.getIntent().getAction()).isSameInstanceAs("intent_action"); + assertThat(((DeviceSettingIntentAction) fromParcel.getAction()).getIntent().getAction()) + .isEqualTo("intent_action"); assertThat(fromParcel.hasSwitch()).isEqualTo(preference.hasSwitch()); assertThat(fromParcel.getChecked()).isEqualTo(preference.getChecked()); assertThat(fromParcel.isAllowedChangingState()) diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingIntentActionTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingIntentActionTest.java new file mode 100644 index 000000000000..d33db4f13fc4 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingIntentActionTest.java @@ -0,0 +1,73 @@ +/* + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Parcel; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public final class DeviceSettingIntentActionTest { + + @Test + public void getMethods() { + DeviceSettingIntentAction action = + new DeviceSettingIntentAction.Builder() + .setIntent(new Intent("intent_action")) + .setExtras(buildBundle("key1", "value1")) + .build(); + + assertThat(action.getIntent().getAction()).isEqualTo("intent_action"); + assertThat(action.getExtras().getString("key1")).isEqualTo("value1"); + } + + @Test + public void parcelOperation() { + DeviceSettingIntentAction action = + new DeviceSettingIntentAction.Builder() + .setIntent(new Intent("intent_action")) + .setExtras(buildBundle("key1", "value1")) + .build(); + + DeviceSettingIntentAction fromParcel = writeAndRead(action); + + assertThat(fromParcel.getIntent().getAction()).isEqualTo(action.getIntent().getAction()); + assertThat(fromParcel.getExtras().getString("key1")) + .isEqualTo(action.getExtras().getString("key1")); + } + + private Bundle buildBundle(String key, String value) { + Bundle bundle = new Bundle(); + bundle.putString(key, value); + return bundle; + } + + private DeviceSettingIntentAction writeAndRead(DeviceSettingIntentAction preference) { + Parcel parcel = Parcel.obtain(); + preference.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + DeviceSettingIntentAction fromParcel = + DeviceSettingIntentAction.CREATOR.createFromParcel(parcel); + return fromParcel; + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingPendingIntentActionTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingPendingIntentActionTest.java new file mode 100644 index 000000000000..3c35147c3a3f --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingPendingIntentActionTest.java @@ -0,0 +1,83 @@ +/* + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Parcel; + +import androidx.test.core.app.ApplicationProvider; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public final class DeviceSettingPendingIntentActionTest { + + private Context mContext = ApplicationProvider.getApplicationContext(); + + @Test + public void getMethods() { + DeviceSettingPendingIntentAction action = + new DeviceSettingPendingIntentAction.Builder() + .setPendingIntent( + PendingIntent.getBroadcast(mContext, 0, new Intent("action"), 0)) + .setExtras(buildBundle("key1", "value1")) + .build(); + + assertThat(action.getPendingIntent()).isSameInstanceAs(action.getPendingIntent()); + assertThat(action.getExtras().getString("key1")).isEqualTo("value1"); + } + + @Test + public void parcelOperation() { + DeviceSettingPendingIntentAction action = + new DeviceSettingPendingIntentAction.Builder() + .setPendingIntent( + PendingIntent.getBroadcast(mContext, 0, new Intent("action"), 0)) + .setExtras(buildBundle("key1", "value1")) + .build(); + + DeviceSettingPendingIntentAction fromParcel = writeAndRead(action); + + assertThat(action.getPendingIntent().getIntent()) + .isEqualTo(action.getPendingIntent().getIntent()); + assertThat(fromParcel.getExtras().getString("key1")) + .isEqualTo(action.getExtras().getString("key1")); + } + + private Bundle buildBundle(String key, String value) { + Bundle bundle = new Bundle(); + bundle.putString(key, value); + return bundle; + } + + private DeviceSettingPendingIntentAction writeAndRead( + DeviceSettingPendingIntentAction preference) { + Parcel parcel = Parcel.obtain(); + preference.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + DeviceSettingPendingIntentAction fromParcel = + DeviceSettingPendingIntentAction.CREATOR.createFromParcel(parcel); + return fromParcel; + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputMediaDeviceTest.java index 2f0aa1cf0cb9..30e4637f59ff 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputMediaDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputMediaDeviceTest.java @@ -37,6 +37,7 @@ public class InputMediaDeviceTest { private final int BUILTIN_MIC_ID = 1; private final int WIRED_HEADSET_ID = 2; private final int USB_HEADSET_ID = 3; + private final int BT_HEADSET_ID = 4; private final int MAX_VOLUME = 1; private final int CURRENT_VOLUME = 0; private final boolean IS_VOLUME_FIXED = true; @@ -108,4 +109,19 @@ public class InputMediaDeviceTest { assertThat(usbMediaDevice.getName()) .isEqualTo(mContext.getString(R.string.media_transfer_usb_device_mic_name)); } + + @Test + public void getName_returnCorrectName_btHeadset() { + InputMediaDevice btMediaDevice = + InputMediaDevice.create( + mContext, + String.valueOf(BT_HEADSET_ID), + AudioDeviceInfo.TYPE_BLUETOOTH_SCO, + MAX_VOLUME, + CURRENT_VOLUME, + IS_VOLUME_FIXED); + assertThat(btMediaDevice).isNotNull(); + assertThat(btMediaDevice.getName()) + .isEqualTo(mContext.getString(R.string.media_transfer_bt_device_mic_name)); + } } diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp index 1a99d25786ff..65b22758946d 100644 --- a/packages/SettingsProvider/Android.bp +++ b/packages/SettingsProvider/Android.bp @@ -39,6 +39,7 @@ android_library { "configinfra_framework_flags_java_lib", "device_config_service_flags_java", "libaconfig_java_proto_lite", + "notification_flags_lib", "SettingsLibDeviceStateRotationLock", "SettingsLibDisplayUtils", ], diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 5e31da411e49..4dc84246afc0 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -168,10 +168,6 @@ public class SecureSettings { Settings.Secure.SHOW_NOTIFICATION_SNOOZE, Settings.Secure.NOTIFICATION_HISTORY_ENABLED, Settings.Secure.ZEN_DURATION, - Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, - Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, - Settings.Secure.ZEN_SETTINGS_UPDATED, - Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, Settings.Secure.CHARGING_SOUNDS_ENABLED, Settings.Secure.CHARGING_VIBRATION_ENABLED, Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java index 0773bd701d5c..8f58e8cd1973 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java @@ -434,7 +434,7 @@ public class GlobalSettingsValidators { VALIDATORS.put(Global.Wearable.PHONE_SWITCHING_STATUS, new InclusiveIntegerRangeValidator( Global.Wearable.PHONE_SWITCHING_STATUS_NOT_STARTED, - Global.Wearable.PHONE_SWITCHING_STATUS_IN_PROGRESS_MIGRATION_SUCCESS)); + Global.Wearable.PHONE_SWITCHING_STATUS_ACCOUNTS_MATCHED)); VALIDATORS.put(Global.Wearable.REDUCE_MOTION, BOOLEAN_VALIDATOR); VALIDATORS.put(Global.Wearable.RTL_SWIPE_TO_DISMISS_ENABLED_DEV, BOOLEAN_VALIDATOR); VALIDATORS.put( diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index b3f73749f393..688676dc4072 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -247,10 +247,6 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.SHOW_NOTIFICATION_SNOOZE, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.NOTIFICATION_HISTORY_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.ZEN_DURATION, ANY_INTEGER_VALIDATOR); - VALIDATORS.put(Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, BOOLEAN_VALIDATOR); - VALIDATORS.put(Secure.SHOW_ZEN_SETTINGS_SUGGESTION, BOOLEAN_VALIDATOR); - VALIDATORS.put(Secure.ZEN_SETTINGS_UPDATED, BOOLEAN_VALIDATOR); - VALIDATORS.put(Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.CHARGING_VIBRATION_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put( diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java index 6c3183191163..ec3bd90b91ea 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java @@ -29,6 +29,7 @@ import android.hardware.display.ColorDisplayManager; import android.icu.util.ULocale; import android.media.AudioManager; import android.media.RingtoneManager; +import android.media.Utils; import android.net.Uri; import android.os.LocaleList; import android.os.RemoteException; @@ -309,6 +310,13 @@ public class SettingsHelper { return SILENT_RINGTONE; } } else { + // If the ringtone/notification support the vibration, use the original value. + final int ringtoneType = getRingtoneType(name); + if ((Settings.System.RINGTONE.equals(name) + || Settings.System.NOTIFICATION_SOUND.equals(name)) + && hasVibrationSettings(value, ringtoneType)) { + return value; + } return getCanonicalRingtoneValue(value); } } @@ -362,6 +370,15 @@ public class SettingsHelper { return; } + // If the ringtone/notification has vibration, we backup original value in onBackupValue. + // So use the value directly for restoring. + if ((ringtoneType == RingtoneManager.TYPE_RINGTONE + || ringtoneType == RingtoneManager.TYPE_NOTIFICATION) + && hasVibrationSettings(value, ringtoneType)) { + RingtoneManager.setActualDefaultRingtoneUri(mContext, ringtoneType, Uri.parse(value)); + return; + } + Uri ringtoneUri = null; try { ringtoneUri = @@ -617,6 +634,19 @@ public class SettingsHelper { return allLocales.remove(toFullLocale(filteredLocale)); } + private boolean hasVibrationSettings(String value, int type) { + if (Utils.hasVibration(Uri.parse(value)) && mContext.getResources().getBoolean( + com.android.internal.R.bool.config_ringtoneVibrationSettingsSupported)) { + if (type == RingtoneManager.TYPE_RINGTONE) { + return android.media.audio.Flags.enableRingtoneHapticsCustomization(); + } + if (type == RingtoneManager.TYPE_NOTIFICATION) { + return com.android.server.notification.Flags.notificationVibrationInSoundUri(); + } + } + return false; + } + /** * Sets the locale specified. Input data is the byte representation of comma separated * multiple BCP-47 language tags. For backwards compatibility, strings of the form diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 3c24f5c56603..2034f36c558b 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -2734,18 +2734,6 @@ class SettingsProtoDumpUtil { Settings.Secure.ZEN_DURATION, SecureSettingsProto.Zen.DURATION); dumpSetting(s, p, - Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, - SecureSettingsProto.Zen.SHOW_ZEN_UPGRADE_NOTIFICATION); - dumpSetting(s, p, - Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, - SecureSettingsProto.Zen.SHOW_ZEN_SETTINGS_SUGGESTION); - dumpSetting(s, p, - Settings.Secure.ZEN_SETTINGS_UPDATED, - SecureSettingsProto.Zen.SETTINGS_UPDATED); - dumpSetting(s, p, - Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, - SecureSettingsProto.Zen.SETTINGS_SUGGESTION_VIEWED); - dumpSetting(s, p, Settings.Secure.CHARGE_OPTIMIZATION_MODE, SecureSettingsProto.CHARGE_OPTIMIZATION_MODE); p.end(zenToken); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 749ad0a993b3..a8af43f5cb11 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -4771,9 +4771,9 @@ public class SettingsProvider extends ContentProvider { } if (currentVersion == 169) { - // Version 169: Set the default value for Secure Settings ZEN_DURATION, - // SHOW_ZEN_SETTINGS_SUGGESTION, ZEN_SETTINGS_UPDATE and - // ZEN_SETTINGS_SUGGESTION_VIEWED + // Version 169: Set the default value for Secure Settings ZEN_DURATION. + // Also used to update SHOW_ZEN_SETTINGS_SUGGESTION, ZEN_SETTINGS_UPDATE and + // ZEN_SETTINGS_SUGGESTION_VIEWED, but those properties are gone now. final SettingsState globalSettings = getGlobalSettingsLocked(); final Setting globalZenDuration = globalSettings.getSettingLocked( @@ -4801,33 +4801,6 @@ public class SettingsProvider extends ContentProvider { SettingsState.SYSTEM_PACKAGE_NAME); } - // SHOW_ZEN_SETTINGS_SUGGESTION - final Setting currentShowZenSettingSuggestion = secureSettings.getSettingLocked( - Secure.SHOW_ZEN_SETTINGS_SUGGESTION); - if (currentShowZenSettingSuggestion.isNull()) { - secureSettings.insertSettingOverrideableByRestoreLocked( - Secure.SHOW_ZEN_SETTINGS_SUGGESTION, "1", - null, true, SettingsState.SYSTEM_PACKAGE_NAME); - } - - // ZEN_SETTINGS_UPDATED - final Setting currentUpdatedSetting = secureSettings.getSettingLocked( - Secure.ZEN_SETTINGS_UPDATED); - if (currentUpdatedSetting.isNull()) { - secureSettings.insertSettingOverrideableByRestoreLocked( - Secure.ZEN_SETTINGS_UPDATED, "0", - null, true, SettingsState.SYSTEM_PACKAGE_NAME); - } - - // ZEN_SETTINGS_SUGGESTION_VIEWED - final Setting currentSettingSuggestionViewed = secureSettings.getSettingLocked( - Secure.ZEN_SETTINGS_SUGGESTION_VIEWED); - if (currentSettingSuggestionViewed.isNull()) { - secureSettings.insertSettingOverrideableByRestoreLocked( - Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, "0", - null, true, SettingsState.SYSTEM_PACKAGE_NAME); - } - currentVersion = 170; } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java index 3c634f067a0d..011ffbc97d19 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java @@ -610,7 +610,7 @@ final class SettingsState { flag.getPackageName(), flag.getFlagName(), flag.getServerFlagValue(), - false); + StorageRequestMessage.SERVER_ON_REBOOT); } if (flag.getHasLocalOverride()) { @@ -619,7 +619,7 @@ final class SettingsState { flag.getPackageName(), flag.getFlagName(), flag.getLocalFlagValue(), - true); + StorageRequestMessage.LOCAL_ON_REBOOT); } } diff --git a/packages/SettingsProvider/test/AndroidTest.xml b/packages/SettingsProvider/test/AndroidTest.xml index dccc2d398f12..541a29465b9a 100644 --- a/packages/SettingsProvider/test/AndroidTest.xml +++ b/packages/SettingsProvider/test/AndroidTest.xml @@ -32,7 +32,7 @@ <option name="package" value="com.android.providers.setting.test" /> <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> <option name="hidden-api-checks" value="false"/> - <option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile" /> - <option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser" /> + <option name="exclude-annotation" value="com.android.bedstead.enterprise.annotations.RequireRunOnWorkProfile" /> + <option name="exclude-annotation" value="com.android.bedstead.multiuser.annotations.RequireRunOnSecondaryUser" /> </test> </configuration> diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index b491b5a146e1..d39b5645109d 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -223,7 +223,6 @@ public class SettingsBackupTest { Settings.Global.ENABLE_DELETION_HELPER_NO_THRESHOLD_TOGGLE, Settings.Global.ENABLE_DISKSTATS_LOGGING, Settings.Global.ENABLE_EPHEMERAL_FEATURE, - Settings.Global.ENABLE_USE_APP_INFO_NOT_LAUNCHED, Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED, Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS, diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java index 4b10b56f49fb..babc1a37cc61 100644 --- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java +++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java @@ -37,9 +37,12 @@ import android.content.res.Resources; import android.database.Cursor; import android.database.MatrixCursor; import android.media.AudioManager; +import android.media.Utils; import android.net.Uri; import android.os.Bundle; import android.os.LocaleList; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.BaseColumns; import android.provider.MediaStore; import android.provider.Settings; @@ -54,6 +57,7 @@ import com.android.internal.R; 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; @@ -74,9 +78,13 @@ public class SettingsHelperTest { "content://media/internal/audio/media/20?title=DefaultNotification&canonical=1"; private static final String DEFAULT_ALARM_VALUE = "content://media/internal/audio/media/30?title=DefaultAlarm&canonical=1"; + private static final String VIBRATION_FILE_NAME = "haptics.xml"; private SettingsHelper mSettingsHelper; + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Mock private Context mContext; @Mock private Resources mResources; @Mock private AudioManager mAudioManager; @@ -120,6 +128,22 @@ public class SettingsHelperTest { } @Test + @EnableFlags({android.media.audio.Flags.FLAG_ENABLE_RINGTONE_HAPTICS_CUSTOMIZATION, + com.android.server.notification.Flags.FLAG_NOTIFICATION_VIBRATION_IN_SOUND_URI}) + public void testOnBackupValue_ringtoneVibrationSupport_returnsSameValue() { + when(mResources.getBoolean( + com.android.internal.R.bool.config_ringtoneVibrationSettingsSupported)).thenReturn( + true); + String testRingtoneVibrationValue = createUriWithVibration(DEFAULT_RINGTONE_VALUE); + String testNotificationVibrationValue = createUriWithVibration(DEFAULT_NOTIFICATION_VALUE); + + assertEquals(testRingtoneVibrationValue, mSettingsHelper.onBackupValue( + Settings.System.RINGTONE, testRingtoneVibrationValue)); + assertEquals(testNotificationVibrationValue, mSettingsHelper.onBackupValue( + Settings.System.NOTIFICATION_SOUND, testNotificationVibrationValue)); + } + + @Test public void testGetRealValue_settingNotReplaced_returnsSameValue() { when(mSettingsHelper.isReplacedSystemSetting(eq(SETTING_KEY))).thenReturn(false); @@ -675,6 +699,30 @@ public class SettingsHelperTest { .isEqualTo(null); } + @Test + @EnableFlags({android.media.audio.Flags.FLAG_ENABLE_RINGTONE_HAPTICS_CUSTOMIZATION, + com.android.server.notification.Flags.FLAG_NOTIFICATION_VIBRATION_IN_SOUND_URI}) + public void testRestoreValue_ringtoneVibrationSupport_restoreValue() { + when(mResources.getBoolean( + com.android.internal.R.bool.config_ringtoneVibrationSettingsSupported)).thenReturn( + true); + String testRingtoneVibrationValue = createUriWithVibration(DEFAULT_RINGTONE_VALUE); + String testNotificationVibrationValue = createUriWithVibration(DEFAULT_NOTIFICATION_VALUE); + ContentProvider mockMediaContentProvider = + new MockContentProvider(mContext) { + @Override + public String getType(Uri url) { + return "audio/ogg"; + } + }; + mContentResolver.addProvider(MediaStore.AUTHORITY, mockMediaContentProvider); + resetRingtoneSettingsToDefault(); + + assertRingtoneSettingsRestoring(Settings.System.RINGTONE, testRingtoneVibrationValue); + assertRingtoneSettingsRestoring( + Settings.System.NOTIFICATION_SOUND, testNotificationVibrationValue); + } + private static class MockSettingsProvider extends MockContentProvider { private final ArrayMap<String, String> mKeyValueStore = new ArrayMap<>(); MockSettingsProvider(Context context) { @@ -766,4 +814,25 @@ public class SettingsHelperTest { assertThat(Settings.System.getString(mContentResolver, Settings.System.ALARM_ALERT)) .isEqualTo(DEFAULT_ALARM_VALUE); } + + private String createUriWithVibration(String defaultUriString) { + return Uri.parse(defaultUriString).buildUpon() + .appendQueryParameter( + Utils.VIBRATION_URI_PARAM, VIBRATION_FILE_NAME).build().toString(); + } + + private void assertRingtoneSettingsRestoring( + String settings, String testRingtoneSettingsValue) { + mSettingsHelper.restoreValue( + mContext, + mContentResolver, + new ContentValues(), + Uri.EMPTY, + settings, + testRingtoneSettingsValue, + 0); + + assertThat(Settings.System.getString(mContentResolver, settings)) + .isEqualTo(testRingtoneSettingsValue); + } } diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java index e4898daf3cbf..e86e72712b48 100644 --- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java +++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java @@ -31,10 +31,10 @@ import com.android.bedstead.enterprise.annotations.EnsureHasNoWorkProfile; import com.android.bedstead.enterprise.annotations.EnsureHasWorkProfile; import com.android.bedstead.harrier.BedsteadJUnit4; import com.android.bedstead.harrier.DeviceState; -import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser; import com.android.bedstead.harrier.annotations.RequireFeature; import com.android.bedstead.harrier.annotations.RequireRunOnInitialUser; -import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser; +import com.android.bedstead.multiuser.annotations.EnsureHasSecondaryUser; +import com.android.bedstead.multiuser.annotations.RequireRunOnPrimaryUser; import com.android.bedstead.nene.TestApis; import com.android.bedstead.nene.users.UserReference; import com.android.bedstead.nene.users.UserType; diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index f3c5a186563d..456fedf912ff 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -948,6 +948,9 @@ <!-- Permission required for CTS test - CtsNfcTestCases --> <uses-permission android:name="android.permission.NFC_SET_CONTROLLER_ALWAYS_ON" /> + <!-- Permission required for CTS test - CtsAppTestCases --> + <uses-permission android:name="android.permission.KILL_UID" /> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" diff --git a/packages/Shell/res/values-kn/strings.xml b/packages/Shell/res/values-kn/strings.xml index 56448f73d9c2..18d0f341ad92 100644 --- a/packages/Shell/res/values-kn/strings.xml +++ b/packages/Shell/res/values-kn/strings.xml @@ -28,7 +28,7 @@ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಇಲ್ಲದೇ ಬಗ್ ವರದಿ ಹಂಚಿಕೊಳ್ಳಲು ಆಯ್ಕೆಮಾಡಿ, ಅಥವಾ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಪೂರ್ತಿಯಾಗುವ ತನಕ ಕಾಯಿರಿ"</string> <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಇಲ್ಲದೇ ನಿಮ್ಮ ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ ಅಥವಾ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಪೂರ್ತಿಯಾಗುವವರೆಗೂ ನಿರೀಕ್ಷಿಸಿ"</string> <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಇಲ್ಲದೇ ನಿಮ್ಮ ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ ಅಥವಾ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಪೂರ್ತಿಯಾಗುವವರೆಗೂ ನಿರೀಕ್ಷಿಸಿ"</string> - <string name="bugreport_confirm" msgid="5917407234515812495">"ನೀವು ಸೂಕ್ಷ್ಮ ಎಂದು ಪರಿಗಣಿಸಿರುವ ಯಾವುದೇ ಡೇಟಾ ಒಳಗೊಂಡಿರುವ ಸಿಸ್ಟಂನ ಹಲವಾರು ಲಾಗ್ ಫೈಲ್ಗಳಿಂದ ಡೇಟಾವನ್ನು ದೋಷದ ವರದಿಗಳು ಒಳಗೊಂಡಿವೆ (ಉದಾಹರಣೆಗೆ ಅಪ್ಲಿಕೇಶನ್-ಬಳಕೆ ಮತ್ತು ಸ್ಥಳ ಮಾಹಿತಿ). ನೀವು ನಂಬಿಕೆ ಇರಿಸಿರುವ ಜನರು ಮತ್ತು ಅಪ್ಲಿಕೇಶನ್ಗಳೊಂದಿಗೆ ಮಾತ್ರ ದೋಷದ ವರದಿಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳಿ."</string> + <string name="bugreport_confirm" msgid="5917407234515812495">"ನೀವು ಸೂಕ್ಷ್ಮ ಎಂದು ಪರಿಗಣಿಸಿರುವ ಯಾವುದೇ ಡೇಟಾ ಒಳಗೊಂಡಿರುವ ಸಿಸ್ಟಂನ ಹಲವಾರು ಲಾಗ್ ಫೈಲ್ಗಳಿಂದ ಡೇಟಾವನ್ನು ದೋಷದ ವರದಿಗಳು ಒಳಗೊಂಡಿವೆ (ಉದಾಹರಣೆಗೆ ಆ್ಯಪ್-ಬಳಕೆ ಮತ್ತು ಸ್ಥಳ ಮಾಹಿತಿ). ನೀವು ನಂಬಿಕೆ ಇರಿಸಿರುವ ಜನರು ಮತ್ತು ಆ್ಯಪ್ಗಳೊಂದಿಗೆ ಮಾತ್ರ ದೋಷದ ವರದಿಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳಿ."</string> <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"ಮತ್ತೊಮ್ಮೆ ತೋರಿಸಬೇಡ"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"ದೋಷ ವರದಿಗಳು"</string> <string name="bugreport_unreadable_text" msgid="586517851044535486">"ಬಗ್ ವರದಿ ಫೈಲ್ ಅನ್ನು ಓದಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string> diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-fa/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-fa/strings.xml index 49d8f6965540..cf6f0120bff0 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-fa/strings.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-fa/strings.xml @@ -26,6 +26,6 @@ <string name="accessibility_menu_large_buttons_title" msgid="8978499601044961736">"دکمههای بزرگ"</string> <string name="accessibility_menu_large_buttons_summary" msgid="236873938502785311">"افزایش اندازه «دکمههای منوی دسترسپذیری»"</string> <string name="pref_help_title" msgid="6871558837025010641">"راهنما"</string> - <string name="brightness_percentage_label" msgid="7391554573977867369">"روشنایی <xliff:g id="PERCENTAGE">%1$s</xliff:g> %%"</string> - <string name="music_volume_percentage_label" msgid="398635599662604706">"بلندی صدای موسیقی <xliff:g id="PERCENTAGE">%1$s</xliff:g> %%"</string> + <string name="brightness_percentage_label" msgid="7391554573977867369">"روشنایی %%<xliff:g id="PERCENTAGE">%1$s</xliff:g>"</string> + <string name="music_volume_percentage_label" msgid="398635599662604706">"بلندی صدای موسیقی %%<xliff:g id="PERCENTAGE">%1$s</xliff:g>"</string> </resources> diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index d98b2da5a811..26e6e71beae7 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -637,6 +637,13 @@ flag { } flag { + name: "screenshot_policy_split_and_desktop_mode" + namespace: "systemui" + description: "Improves screenshot policy handling for split screen and desktop mode." + bug: "365597999" +} + +flag { name: "run_fingerprint_detect_on_dismissible_keyguard" namespace: "systemui" description: "Run fingerprint detect instead of authenticate if the keyguard is dismissible." @@ -806,16 +813,6 @@ flag { } flag { - name: "register_zen_mode_content_observer_background" - namespace: "systemui" - description: "Decide whether to register zen mode content observers in the background thread." - bug: "324515627" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "clipboard_noninteractive_on_lockscreen" namespace: "systemui" description: "Prevents the interactive clipboard UI from appearing when device is locked" @@ -1074,6 +1071,16 @@ flag { } flag { + name: "dream_overlay_updated_font" + namespace: "systemui" + description: "Flag to enable updated font settings for dream overlay" + bug: "349656117" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "app_clips_backlinks" namespace: "systemui" description: "Enables Backlinks improvement feature in App Clips" @@ -1384,10 +1391,13 @@ flag { } flag { - name: "compose_haptic_sliders" + name: "haptics_for_compose_sliders" namespace: "systemui" description: "Adding haptic component infrastructure to sliders in Compose." bug: "341968766" + metadata { + purpose: PURPOSE_BUGFIX + } } flag { @@ -1453,3 +1463,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "check_lockscreen_gone_transition" + namespace: "systemui" + description: "Run notification pipeline when the lockscreen is not in gone transition for avoiding janky frames during unlocking animation" + bug: "358301118" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt index f5d01d70e077..907c39d842ce 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt @@ -944,9 +944,26 @@ private class AnimatedDialog( } override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) { - startController.onTransitionAnimationEnd(isExpandingFullyAbove) - endController.onTransitionAnimationEnd(isExpandingFullyAbove) - onLaunchAnimationEnd() + // onLaunchAnimationEnd is called by an Animator at the end of the animation, + // on a Choreographer animation tick. The following calls will move the animated + // content from the dialog overlay back to its original position, and this + // change must be reflected in the next frame given that we then sync the next + // frame of both the content and dialog ViewRoots. However, in case that content + // is rendered by Compose, whose compositions are also scheduled on a + // Choreographer frame, any state change made *right now* won't be reflected in + // the next frame given that a Choreographer frame can't schedule another and + // have it happen in the same frame. So we post the forwarded calls to + // [Controller.onLaunchAnimationEnd], leaving this Choreographer frame, ensuring + // that the move of the content back to its original window will be reflected in + // the next frame right after [onLaunchAnimationEnd] is called. + // + // TODO(b/330672236): Move this to TransitionAnimator. + dialog.context.mainExecutor.execute { + startController.onTransitionAnimationEnd(isExpandingFullyAbove) + endController.onTransitionAnimationEnd(isExpandingFullyAbove) + + onLaunchAnimationEnd() + } } override fun onTransitionAnimationProgress( diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt index 859fc4e09bb2..fc4cf1d1e21e 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt @@ -379,26 +379,13 @@ class TransitionAnimator( Log.d(TAG, "Animation ended") } - // onAnimationEnd is called at the end of the animation, on a Choreographer - // animation tick. During dialog launches, the following calls will move the - // animated content from the dialog overlay back to its original position, and - // this change must be reflected in the next frame given that we then sync the - // next frame of both the content and dialog ViewRoots. During SysUI activity - // launches, we will instantly collapse the shade at the end of the transition. - // However, if those are rendered by Compose, whose compositions are also - // scheduled on a Choreographer frame, any state change made *right now* won't - // be reflected in the next frame given that a Choreographer frame can't - // schedule another and have it happen in the same frame. So we post the - // forwarded calls to [Controller.onLaunchAnimationEnd] in the main executor, - // leaving this Choreographer frame, ensuring that any state change applied by - // onTransitionAnimationEnd() will be reflected in the same frame. - mainExecutor.execute { - controller.onTransitionAnimationEnd(isExpandingFullyAbove) - transitionContainerOverlay.remove(windowBackgroundLayer) - - if (moveBackgroundLayerWhenAppVisibilityChanges && controller.isLaunching) { - openingWindowSyncViewOverlay?.remove(windowBackgroundLayer) - } + // TODO(b/330672236): Post this to the main thread instead so that it does not + // flicker with Flexiglass enabled. + controller.onTransitionAnimationEnd(isExpandingFullyAbove) + transitionContainerOverlay.remove(windowBackgroundLayer) + + if (moveBackgroundLayerWhenAppVisibilityChanges && controller.isLaunching) { + openingWindowSyncViewOverlay?.remove(windowBackgroundLayer) } } } diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/Bounceable.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/Bounceable.kt new file mode 100644 index 000000000000..3f2f84b95977 --- /dev/null +++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/Bounceable.kt @@ -0,0 +1,123 @@ +/* + * 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 + +import androidx.compose.foundation.gestures.Orientation +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.layout +import androidx.compose.ui.unit.Constraints +import androidx.compose.ui.unit.Dp +import kotlin.math.roundToInt + +/** A component that can bounce in one dimension, for instance when it is tapped. */ +interface Bounceable { + val bounce: Dp +} + +/** + * Bounce a composable in the given [orientation] when this [bounceable], the [previousBounceable] + * or [nextBounceable] is bouncing. + * + * Important: This modifier should be used on composables that have a fixed size in [orientation], + * i.e. they should be placed *after* modifiers like Modifier.fillMaxWidth() or Modifier.height(). + * + * @param bounceable the [Bounceable] associated to the current composable that will make this + * composable size grow when bouncing. + * @param previousBounceable the [Bounceable] associated to the previous composable in [orientation] + * that will make this composable shrink when bouncing. + * @param nextBounceable the [Bounceable] associated to the next composable in [orientation] that + * will make this composable shrink when bouncing. + * @param orientation the orientation in which this bounceable should grow/shrink. + * @param bounceEnd whether this bounceable should bounce on the end (right in LTR layouts, left in + * RTL layouts) side. This can be used for grids for which the last item does not align perfectly + * with the end of the grid. + */ +fun Modifier.bounceable( + bounceable: Bounceable, + previousBounceable: Bounceable?, + nextBounceable: Bounceable?, + orientation: Orientation, + bounceEnd: Boolean = nextBounceable != null, +): Modifier { + return layout { measurable, constraints -> + // The constraints in the orientation should be fixed, otherwise there is no way to know + // what the size of our child node will be without this animation code. + checkFixedSize(constraints, orientation) + + var sizePrevious = 0f + var sizeNext = 0f + + if (previousBounceable != null) { + sizePrevious += bounceable.bounce.toPx() - previousBounceable.bounce.toPx() + } + + if (nextBounceable != null) { + sizeNext += bounceable.bounce.toPx() - nextBounceable.bounce.toPx() + } else if (bounceEnd) { + sizeNext += bounceable.bounce.toPx() + } + + when (orientation) { + Orientation.Horizontal -> { + val idleWidth = constraints.maxWidth + val animatedWidth = (idleWidth + sizePrevious + sizeNext).roundToInt() + val animatedConstraints = + constraints.copy(minWidth = animatedWidth, maxWidth = animatedWidth) + + val placeable = measurable.measure(animatedConstraints) + + // Important: we still place the element using the idle size coming from the + // constraints, otherwise the parent will automatically center this node given the + // size that it expects us to be. This allows us to then place the element where we + // want it to be. + layout(idleWidth, placeable.height) { + placeable.placeRelative(-sizePrevious.roundToInt(), 0) + } + } + Orientation.Vertical -> { + val idleHeight = constraints.maxHeight + val animatedHeight = (idleHeight + sizePrevious + sizeNext).roundToInt() + val animatedConstraints = + constraints.copy(minHeight = animatedHeight, maxHeight = animatedHeight) + + val placeable = measurable.measure(animatedConstraints) + layout(placeable.width, idleHeight) { + placeable.placeRelative(0, -sizePrevious.roundToInt()) + } + } + } + } +} + +private fun checkFixedSize(constraints: Constraints, orientation: Orientation) { + when (orientation) { + Orientation.Horizontal -> { + check(constraints.hasFixedWidth) { + "Modifier.bounceable() should receive a fixed width from its parent. Make sure " + + "that it is used *after* a fixed-width Modifier in the horizontal axis (like" + + " Modifier.fillMaxWidth() or Modifier.width())." + } + } + Orientation.Vertical -> { + check(constraints.hasFixedHeight) { + "Modifier.bounceable() should receive a fixed height from its parent. Make sure " + + "that it is used *after* a fixed-height Modifier in the vertical axis (like" + + " Modifier.fillMaxHeight() or Modifier.height())." + } + } + } +} diff --git a/packages/SystemUI/compose/core/tests/src/com/android/compose/animation/BounceableTest.kt b/packages/SystemUI/compose/core/tests/src/com/android/compose/animation/BounceableTest.kt new file mode 100644 index 000000000000..335e9f8872a6 --- /dev/null +++ b/packages/SystemUI/compose/core/tests/src/com/android/compose/animation/BounceableTest.kt @@ -0,0 +1,212 @@ +/* + * 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 + +import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.test.assertHeightIsEqualTo +import androidx.compose.ui.test.assertPositionInRootIsEqualTo +import androidx.compose.ui.test.assertWidthIsEqualTo +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.times +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class BounceableTest { + @get:Rule val rule = createComposeRule() + + @Test + fun bounceable_horizontal() { + var bounceables by mutableStateOf(List(4) { bounceable(0.dp) }) + + rule.setContent { + Row(Modifier.size(100.dp, 50.dp)) { + repeat(bounceables.size) { i -> + Box( + Modifier.weight(1f) + .fillMaxHeight() + .bounceable(bounceables, i, orientation = Orientation.Horizontal) + ) + } + } + } + + // All bounceables have a width of (100dp / bounceables.size) = 25dp and height of 50dp. + repeat(bounceables.size) { i -> + rule + .onNodeWithTag(bounceableTag(i)) + .assertWidthIsEqualTo(25.dp) + .assertHeightIsEqualTo(50.dp) + .assertPositionInRootIsEqualTo(i * 25.dp, 0.dp) + } + + // If all bounceables have the same bounce, it's the same as if they didn't have any. + bounceables = List(4) { bounceable(10.dp) } + repeat(bounceables.size) { i -> + rule + .onNodeWithTag(bounceableTag(i)) + .assertWidthIsEqualTo(25.dp) + .assertHeightIsEqualTo(50.dp) + .assertPositionInRootIsEqualTo(i * 25.dp, 0.dp) + } + + // Bounce the first and third one. + bounceables = + listOf( + bounceable(bounce = 5.dp), + bounceable(bounce = 0.dp), + bounceable(bounce = 10.dp), + bounceable(bounce = 0.dp), + ) + + // First one has a width of 25dp + 5dp, located in (0, 0). + rule + .onNodeWithTag(bounceableTag(0)) + .assertWidthIsEqualTo(30.dp) + .assertHeightIsEqualTo(50.dp) + .assertPositionInRootIsEqualTo(0.dp, 0.dp) + + // Second one has a width of 25dp - 5dp - 10dp, located in (30, 0). + rule + .onNodeWithTag(bounceableTag(1)) + .assertWidthIsEqualTo(10.dp) + .assertHeightIsEqualTo(50.dp) + .assertPositionInRootIsEqualTo(30.dp, 0.dp) + + // Third one has a width of 25 + 2 * 10dp, located in (40, 0). + rule + .onNodeWithTag(bounceableTag(2)) + .assertWidthIsEqualTo(45.dp) + .assertHeightIsEqualTo(50.dp) + .assertPositionInRootIsEqualTo(40.dp, 0.dp) + + // First one has a width of 25dp - 10dp, located in (85, 0). + rule + .onNodeWithTag(bounceableTag(3)) + .assertWidthIsEqualTo(15.dp) + .assertHeightIsEqualTo(50.dp) + .assertPositionInRootIsEqualTo(85.dp, 0.dp) + } + + @Test + fun bounceable_vertical() { + var bounceables by mutableStateOf(List(4) { bounceable(0.dp) }) + + rule.setContent { + Column(Modifier.size(50.dp, 100.dp)) { + repeat(bounceables.size) { i -> + Box( + Modifier.weight(1f) + .fillMaxWidth() + .bounceable(bounceables, i, Orientation.Vertical) + ) + } + } + } + + // All bounceables have a height of (100dp / bounceables.size) = 25dp and width of 50dp. + repeat(bounceables.size) { i -> + rule + .onNodeWithTag(bounceableTag(i)) + .assertWidthIsEqualTo(50.dp) + .assertHeightIsEqualTo(25.dp) + .assertPositionInRootIsEqualTo(0.dp, i * 25.dp) + } + + // If all bounceables have the same bounce, it's the same as if they didn't have any. + bounceables = List(4) { bounceable(10.dp) } + repeat(bounceables.size) { i -> + rule + .onNodeWithTag(bounceableTag(i)) + .assertWidthIsEqualTo(50.dp) + .assertHeightIsEqualTo(25.dp) + .assertPositionInRootIsEqualTo(0.dp, i * 25.dp) + } + + // Bounce the first and third one. + bounceables = + listOf( + bounceable(bounce = 5.dp), + bounceable(bounce = 0.dp), + bounceable(bounce = 10.dp), + bounceable(bounce = 0.dp), + ) + + // First one has a height of 25dp + 5dp, located in (0, 0). + rule + .onNodeWithTag(bounceableTag(0)) + .assertWidthIsEqualTo(50.dp) + .assertHeightIsEqualTo(30.dp) + .assertPositionInRootIsEqualTo(0.dp, 0.dp) + + // Second one has a height of 25dp - 5dp - 10dp, located in (0, 30). + rule + .onNodeWithTag(bounceableTag(1)) + .assertWidthIsEqualTo(50.dp) + .assertHeightIsEqualTo(10.dp) + .assertPositionInRootIsEqualTo(0.dp, 30.dp) + + // Third one has a height of 25 + 2 * 10dp, located in (0, 40). + rule + .onNodeWithTag(bounceableTag(2)) + .assertWidthIsEqualTo(50.dp) + .assertHeightIsEqualTo(45.dp) + .assertPositionInRootIsEqualTo(0.dp, 40.dp) + + // First one has a height of 25dp - 10dp, located in (0, 85). + rule + .onNodeWithTag(bounceableTag(3)) + .assertWidthIsEqualTo(50.dp) + .assertHeightIsEqualTo(15.dp) + .assertPositionInRootIsEqualTo(0.dp, 85.dp) + } + + private fun bounceable(bounce: Dp): Bounceable { + return object : Bounceable { + override val bounce: Dp = bounce + } + } + + private fun Modifier.bounceable( + bounceables: List<Bounceable>, + i: Int, + orientation: Orientation, + ): Modifier { + val previous = if (i > 0) bounceables[i - 1] else null + val next = if (i < bounceables.lastIndex) bounceables[i + 1] else null + return this.bounceable(bounceables[i], previous, next, orientation) + .testTag(bounceableTag(i)) + } + + private fun bounceableTag(i: Int) = "bounceable$i" +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/EnRouteContentModel.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/DreamSceneModule.kt index 7e78cca028ef..2f8236969185 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/EnRouteContentModel.kt +++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/DreamSceneModule.kt @@ -14,17 +14,15 @@ * limitations under the License. */ -package com.android.systemui.statusbar.notification.row.shared +package com.android.systemui.scene -/** - * Represents something en route. - * - * @param smallIcon the main small icon of the EnRoute notification. - * @param title the title of the EnRoute notification. - * @param text the text of the EnRoute notification. - */ -data class EnRouteContentModel( - val smallIcon: IconModel, - val title: CharSequence?, - val text: CharSequence?, -) : RichOngoingContentModel +import com.android.systemui.dream.ui.composable.DreamScene +import com.android.systemui.scene.ui.composable.Scene +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoSet + +@Module +interface DreamSceneModule { + @Binds @IntoSet fun dreamScene(scene: DreamScene): Scene +} 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 557257d6bdc0..571b36639c9e 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 @@ -162,7 +162,6 @@ fun CommunalContainer( initialScene = currentSceneKey, canChangeScene = { _ -> viewModel.canChangeScene() }, transitions = sceneTransitions, - enableInterruptions = false, ) } 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 bcd333710497..7fb4c537641b 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 @@ -148,6 +148,7 @@ import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp @@ -165,6 +166,7 @@ import com.android.compose.ui.graphics.painter.rememberDrawablePainter import com.android.internal.R.dimen.system_app_widget_background_radius import com.android.systemui.Flags import com.android.systemui.Flags.communalTimerFlickerFix +import com.android.systemui.Flags.communalWidgetResizing import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.shared.model.CommunalContentSize import com.android.systemui.communal.shared.model.CommunalScenes @@ -176,6 +178,7 @@ import com.android.systemui.communal.ui.view.layout.sections.CommunalAppWidgetSe import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel import com.android.systemui.communal.ui.viewmodel.CommunalViewModel +import com.android.systemui.communal.ui.viewmodel.ResizeInfo import com.android.systemui.communal.util.DensityUtils.Companion.adjustedDp import com.android.systemui.communal.widgets.SmartspaceAppWidgetHostView import com.android.systemui.communal.widgets.WidgetConfigurator @@ -639,6 +642,38 @@ private fun ObserveNewWidgetAddedEffect( } } +@Composable +private fun ResizableItemFrameWrapper( + key: String, + gridState: LazyGridState, + minItemSpan: Int, + gridContentPadding: PaddingValues, + verticalArrangement: Arrangement.Vertical, + enabled: Boolean, + modifier: Modifier = Modifier, + alpha: () -> Float = { 1f }, + onResize: (info: ResizeInfo) -> Unit = {}, + content: @Composable (modifier: Modifier) -> Unit, +) { + if (!communalWidgetResizing()) { + content(modifier) + } else { + ResizableItemFrame( + key = key, + gridState = gridState, + minItemSpan = minItemSpan, + gridContentPadding = gridContentPadding, + verticalArrangement = verticalArrangement, + enabled = enabled, + alpha = alpha, + modifier = modifier, + onResize = onResize, + ) { + content(Modifier) + } + } +} + @OptIn(ExperimentalFoundationApi::class) @Composable private fun BoxScope.CommunalHubLazyGrid( @@ -695,13 +730,14 @@ private fun BoxScope.CommunalHubLazyGrid( gridModifier = gridModifier.height(hubDimensions.GridHeight) } + val itemArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing) LazyHorizontalGrid( modifier = gridModifier, state = gridState, rows = GridCells.Fixed(CommunalContentSize.FULL.span), contentPadding = contentPadding, - horizontalArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing), - verticalArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing), + horizontalArrangement = itemArrangement, + verticalArrangement = itemArrangement, ) { itemsIndexed( items = list, @@ -710,35 +746,54 @@ private fun BoxScope.CommunalHubLazyGrid( span = { _, item -> GridItemSpan(item.size.span) }, ) { index, item -> val size = SizeF(Dimensions.CardWidth.value, item.size.dp().value) - val cardModifier = Modifier.requiredSize(width = size.width.dp, height = size.height.dp) + val selected = item.key == selectedKey.value + val dpSize = DpSize(size.width.dp, size.height.dp) + if (viewModel.isEditMode && dragDropState != null) { - val selected = item.key == selectedKey.value - DraggableItem( + val outlineAlpha by + animateFloatAsState( + targetValue = if (selected) 1f else 0f, + animationSpec = spring(stiffness = Spring.StiffnessMediumLow), + label = "Widget resizing outline alpha", + ) + ResizableItemFrameWrapper( + key = item.key, + gridState = gridState, + minItemSpan = CommunalContentSize.HALF.span, + gridContentPadding = contentPadding, + verticalArrangement = itemArrangement, + enabled = selected, + alpha = { outlineAlpha }, modifier = - if (dragDropState.draggingItemIndex == index) { - Modifier - } else { + Modifier.requiredSize(dpSize).thenIf( + dragDropState.draggingItemIndex != index + ) { Modifier.animateItem( placementSpec = spring(stiffness = Spring.StiffnessMediumLow) ) }, - dragDropState = dragDropState, - selected = selected, - enabled = item.isWidgetContent(), - index = index, - ) { isDragging -> - CommunalContent( - modifier = cardModifier, - model = item, - viewModel = viewModel, - size = size, - selected = selected && !isDragging, - widgetConfigurator = widgetConfigurator, + onResize = { resizeInfo -> contentListState.resize(index, resizeInfo) }, + ) { modifier -> + DraggableItem( + modifier = modifier, + dragDropState = dragDropState, + selected = selected, + enabled = item.isWidgetContent(), index = index, - contentListState = contentListState, - interactionHandler = interactionHandler, - widgetSection = widgetSection, - ) + ) { isDragging -> + CommunalContent( + modifier = Modifier.fillMaxSize(), + model = item, + viewModel = viewModel, + size = size, + selected = selected && !isDragging, + widgetConfigurator = widgetConfigurator, + index = index, + contentListState = contentListState, + interactionHandler = interactionHandler, + widgetSection = widgetSection, + ) + } } } else { CommunalContent( @@ -746,7 +801,7 @@ private fun BoxScope.CommunalHubLazyGrid( viewModel = viewModel, size = size, selected = false, - modifier = cardModifier.animateItem(), + modifier = Modifier.requiredSize(dpSize).animateItem(), index = index, contentListState = contentListState, interactionHandler = interactionHandler, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ContentListState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ContentListState.kt index 11373577eedb..6e30575a684d 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ContentListState.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ContentListState.kt @@ -21,8 +21,12 @@ import android.os.UserHandle import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.runtime.toMutableStateList +import com.android.systemui.Flags.communalWidgetResizing import com.android.systemui.communal.domain.model.CommunalContentModel +import com.android.systemui.communal.shared.model.CommunalContentSize import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel +import com.android.systemui.communal.ui.viewmodel.DragHandle +import com.android.systemui.communal.ui.viewmodel.ResizeInfo import com.android.systemui.communal.widgets.WidgetConfigurator @Composable @@ -35,15 +39,11 @@ fun rememberContentListState( ContentListState( communalContent, { componentName, user, rank -> - viewModel.onAddWidget( - componentName, - user, - rank, - widgetConfigurator, - ) + viewModel.onAddWidget(componentName, user, rank, widgetConfigurator) }, viewModel::onDeleteWidget, viewModel::onReorderWidgets, + viewModel::onResizeWidget, ) } } @@ -59,6 +59,7 @@ internal constructor( private val onAddWidget: (componentName: ComponentName, user: UserHandle, rank: Int) -> Unit, private val onDeleteWidget: (id: Int, componentName: ComponentName, rank: Int) -> Unit, private val onReorderWidgets: (widgetIdToRankMap: Map<Int, Int>) -> Unit, + private val onResizeWidget: (id: Int, spanY: Int, widgetIdToRankMap: Map<Int, Int>) -> Unit, ) { var list = communalContent.toMutableStateList() private set @@ -77,6 +78,36 @@ internal constructor( } } + /** Resize a widget, possibly re-ordering widgets if needed. */ + fun resize(index: Int, resizeInfo: ResizeInfo) { + val item = list[index] + val currentSpan = item.size.span + val newSpan = currentSpan + resizeInfo.spans + // Only widgets can be resized + if ( + !communalWidgetResizing() || + currentSpan == newSpan || + item !is CommunalContentModel.WidgetContent.Widget + ) { + return + } + list[index] = item.copy(size = CommunalContentSize.toSize(newSpan)) + val prevItem = list.getOrNull(index - 1) + // Check if we have to update indices of items to accommodate the resize. + val widgetIdToRankMap: Map<Int, Int> = + if ( + resizeInfo.isExpanding && + resizeInfo.fromHandle == DragHandle.TOP && + prevItem is CommunalContentModel.WidgetContent.Widget + ) { + onMove(index - 1, index) + mapOf(prevItem.appWidgetId to index, item.appWidgetId to index - 1) + } else { + emptyMap() + } + onResizeWidget(item.appWidgetId, newSpan, widgetIdToRankMap) + } + /** * Persists the new order with all the movements happened during drag operations & the new * widget drop (if applicable). @@ -91,7 +122,7 @@ internal constructor( fun onSaveList( newItemComponentName: ComponentName? = null, newItemUser: UserHandle? = null, - newItemIndex: Int? = null + newItemIndex: Int? = null, ) { // New widget added to the grid. Other widgets are shifted as needed at the database level. if (newItemComponentName != null && newItemUser != null && newItemIndex != null) { diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt index 20ee13166c08..101385f88825 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt @@ -42,6 +42,7 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.toOffset import androidx.compose.ui.unit.toSize +import com.android.systemui.Flags.communalWidgetResizing import com.android.systemui.communal.ui.compose.extensions.firstItemAtOffset import com.android.systemui.communal.ui.compose.extensions.plus import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel @@ -65,7 +66,7 @@ fun rememberGridDragDropState( state = gridState, contentListState = contentListState, scope = scope, - updateDragPositionForRemove = updateDragPositionForRemove + updateDragPositionForRemove = updateDragPositionForRemove, ) } LaunchedEffect(state) { @@ -90,7 +91,7 @@ internal constructor( private val state: LazyGridState, private val contentListState: ContentListState, private val scope: CoroutineScope, - private val updateDragPositionForRemove: (offset: Offset) -> Boolean + private val updateDragPositionForRemove: (offset: Offset) -> Boolean, ) { var draggingItemIndex by mutableStateOf<Int?>(null) private set @@ -122,12 +123,12 @@ internal constructor( offset: Offset, screenWidth: Int, layoutDirection: LayoutDirection, - contentOffset: Offset + contentOffset: Offset, ): Boolean { val normalizedOffset = Offset( if (layoutDirection == LayoutDirection.Ltr) offset.x else screenWidth - offset.x, - offset.y + offset.y, ) state.layoutInfo.visibleItemsInfo .filter { item -> contentListState.isItemEditable(item.index) } @@ -248,7 +249,7 @@ fun Modifier.dragContainer( offset, screenWidth, layoutDirection, - contentOffset + contentOffset, ) ) { viewModel.onReorderWidgetStart() @@ -261,7 +262,7 @@ fun Modifier.dragContainer( onDragCancel = { dragDropState.onDragInterrupted() viewModel.onReorderWidgetCancel() - } + }, ) } ) @@ -276,7 +277,7 @@ fun LazyGridItemScope.DraggableItem( enabled: Boolean, selected: Boolean, modifier: Modifier = Modifier, - content: @Composable (isDragging: Boolean) -> Unit + content: @Composable (isDragging: Boolean) -> Unit, ) { if (!enabled) { return content(false) @@ -286,7 +287,7 @@ fun LazyGridItemScope.DraggableItem( val itemAlpha: Float by animateFloatAsState( targetValue = if (dragDropState.isDraggingToRemove) 0.5f else 1f, - label = "DraggableItemAlpha" + label = "DraggableItemAlpha", ) val direction = LocalLayoutDirection.current val draggingModifier = @@ -303,12 +304,17 @@ fun LazyGridItemScope.DraggableItem( // Animate the highlight alpha manually as alpha modifier (and AnimatedVisibility) clips the // widget to bounds, which cuts off the highlight as we are drawing outside the widget bounds. + val highlightSelected = !communalWidgetResizing() && selected val alpha by animateFloatAsState( targetValue = - if ((dragging || selected) && !dragDropState.isDraggingToRemove) 1f else 0f, + if ((dragging || highlightSelected) && !dragDropState.isDraggingToRemove) { + 1f + } else { + 0f + }, animationSpec = spring(stiffness = Spring.StiffnessMediumLow), - label = "Widget outline alpha" + label = "Widget outline alpha", ) Box(modifier) { diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ResizeableItemFrame.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ResizeableItemFrame.kt new file mode 100644 index 000000000000..ef62eb726e2b --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ResizeableItemFrame.kt @@ -0,0 +1,245 @@ +/* + * 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.communal.ui.compose + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.gestures.AnchoredDraggableState +import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.gestures.anchoredDraggable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.lazy.grid.LazyGridState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.CornerRadius +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.drawscope.Stroke +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.fastIsFinite +import com.android.compose.theme.LocalAndroidColorScheme +import com.android.systemui.communal.ui.viewmodel.DragHandle +import com.android.systemui.communal.ui.viewmodel.ResizeInfo +import com.android.systemui.communal.ui.viewmodel.ResizeableItemFrameViewModel +import com.android.systemui.lifecycle.rememberViewModel +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.combine + +@Composable +private fun UpdateGridLayoutInfo( + viewModel: ResizeableItemFrameViewModel, + key: String, + gridState: LazyGridState, + minItemSpan: Int, + gridContentPadding: PaddingValues, + verticalArrangement: Arrangement.Vertical, +) { + val density = LocalDensity.current + LaunchedEffect( + density, + viewModel, + key, + gridState, + minItemSpan, + gridContentPadding, + verticalArrangement, + ) { + val verticalItemSpacingPx = with(density) { verticalArrangement.spacing.toPx() } + val verticalContentPaddingPx = + with(density) { + (gridContentPadding.calculateTopPadding() + + gridContentPadding.calculateBottomPadding()) + .toPx() + } + + combine( + snapshotFlow { gridState.layoutInfo.maxSpan }, + snapshotFlow { gridState.layoutInfo.viewportSize.height }, + snapshotFlow { + gridState.layoutInfo.visibleItemsInfo.firstOrNull { it.key == key } + }, + ::Triple, + ) + .collectLatest { (maxItemSpan, viewportHeightPx, itemInfo) -> + viewModel.setGridLayoutInfo( + verticalItemSpacingPx, + verticalContentPaddingPx, + viewportHeightPx, + maxItemSpan, + minItemSpan, + itemInfo?.row, + itemInfo?.span, + ) + } + } +} + +@Composable +private fun BoxScope.DragHandle( + handle: DragHandle, + dragState: AnchoredDraggableState<Int>, + outlinePadding: Dp, + brush: Brush, + alpha: () -> Float, + modifier: Modifier = Modifier, +) { + val directionalModifier = if (handle == DragHandle.TOP) -1 else 1 + val alignment = if (handle == DragHandle.TOP) Alignment.TopCenter else Alignment.BottomCenter + Box( + modifier + .align(alignment) + .graphicsLayer { + translationY = + directionalModifier * (size.height / 2 + outlinePadding.toPx()) + + (dragState.offset.takeIf { it.fastIsFinite() } ?: 0f) + } + .anchoredDraggable(dragState, Orientation.Vertical) + ) { + Canvas(modifier = Modifier.fillMaxSize()) { + if (dragState.anchors.size > 1) { + drawCircle( + brush = brush, + radius = outlinePadding.toPx(), + center = Offset(size.width / 2, size.height / 2), + alpha = alpha(), + ) + } + } + } +} + +/** + * Draws a frame around the content with drag handles on the top and bottom of the content. + * + * @param index The index of this item in the [LazyGridState]. + * @param gridState The [LazyGridState] for the grid containing this item. + * @param minItemSpan The minimum span that an item may occupy. Items are resized in multiples of + * this span. + * @param gridContentPadding The content padding used for the grid, needed for determining offsets. + * @param verticalArrangement The vertical arrangement of the grid items. + * @param modifier Optional modifier to apply to the frame. + * @param enabled Whether resizing is enabled. + * @param outlinePadding The padding to apply around the entire frame, in [Dp] + * @param outlineColor Optional color to make the outline around the content. + * @param cornerRadius Optional radius to give to the outline around the content. + * @param strokeWidth Optional stroke width to draw the outline with. + * @param alpha Optional function to provide an alpha value for the outline. Can be used to fade the + * outline in and out. This is wrapped in a function for performance, as the value is only + * accessed during the draw phase. + * @param onResize Optional callback which gets executed when the item is resized to a new span. + * @param content The content to draw inside the frame. + */ +@Composable +fun ResizableItemFrame( + key: String, + gridState: LazyGridState, + minItemSpan: Int, + gridContentPadding: PaddingValues, + verticalArrangement: Arrangement.Vertical, + modifier: Modifier = Modifier, + enabled: Boolean = true, + outlinePadding: Dp = 8.dp, + outlineColor: Color = LocalAndroidColorScheme.current.primary, + cornerRadius: Dp = 37.dp, + strokeWidth: Dp = 3.dp, + alpha: () -> Float = { 1f }, + onResize: (info: ResizeInfo) -> Unit = {}, + content: @Composable () -> Unit, +) { + val brush = SolidColor(outlineColor) + val onResizeUpdated by rememberUpdatedState(onResize) + val viewModel = + rememberViewModel(traceName = "ResizeableItemFrame.viewModel") { + ResizeableItemFrameViewModel() + } + + val dragHandleHeight = verticalArrangement.spacing - outlinePadding * 2 + + // Draw content surrounded by drag handles at top and bottom. Allow drag handles + // to overlap content. + Box(modifier) { + content() + + if (enabled) { + DragHandle( + handle = DragHandle.TOP, + dragState = viewModel.topDragState, + outlinePadding = outlinePadding, + brush = brush, + alpha = alpha, + modifier = Modifier.fillMaxWidth().height(dragHandleHeight), + ) + + DragHandle( + handle = DragHandle.BOTTOM, + dragState = viewModel.bottomDragState, + outlinePadding = outlinePadding, + brush = brush, + alpha = alpha, + modifier = Modifier.fillMaxWidth().height(dragHandleHeight), + ) + + // Draw outline around the element. + Canvas(modifier = Modifier.matchParentSize()) { + val paddingPx = outlinePadding.toPx() + val topOffset = viewModel.topDragState.offset.takeIf { it.fastIsFinite() } ?: 0f + val bottomOffset = + viewModel.bottomDragState.offset.takeIf { it.fastIsFinite() } ?: 0f + drawRoundRect( + brush, + alpha = alpha(), + topLeft = Offset(-paddingPx, topOffset + -paddingPx), + size = + Size( + width = size.width + paddingPx * 2, + height = -topOffset + bottomOffset + size.height + paddingPx * 2, + ), + cornerRadius = CornerRadius(cornerRadius.toPx()), + style = Stroke(width = strokeWidth.toPx()), + ) + } + + UpdateGridLayoutInfo( + viewModel, + key, + gridState, + minItemSpan, + gridContentPadding, + verticalArrangement, + ) + LaunchedEffect(viewModel) { + viewModel.resizeInfo.collectLatest { info -> onResizeUpdated(info) } + } + } + } +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/dream/ui/composable/DreamScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/dream/ui/composable/DreamScene.kt new file mode 100644 index 000000000000..f4374c6c9487 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/dream/ui/composable/DreamScene.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.dream.ui.composable + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.android.compose.animation.scene.SceneScope +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dreams.ui.viewmodel.DreamUserActionsViewModel +import com.android.systemui.lifecycle.ExclusiveActivatable +import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.scene.ui.composable.Scene +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow + +/** The dream scene shows when a dream activity is showing. */ +@SysUISingleton +class DreamScene +@Inject +constructor(private val actionsViewModelFactory: DreamUserActionsViewModel.Factory) : + ExclusiveActivatable(), Scene { + override val key = Scenes.Dream + + private val actionsViewModel: DreamUserActionsViewModel by lazy { + actionsViewModelFactory.create() + } + + override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions + + override suspend fun onActivated(): Nothing { + actionsViewModel.activate() + } + + @Composable + override fun SceneScope.Content(modifier: Modifier) { + Box(modifier = modifier.fillMaxSize()) { + // Render a sleep emoji to make the scene appear visible. + Text( + modifier = Modifier.padding(16.dp).align(Alignment.BottomStart), + text = "\uD83D\uDCA4", + ) + } + } +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt index 97d89a2631bf..afa92f2533ce 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt @@ -83,11 +83,7 @@ constructor( } val state = remember { - MutableSceneTransitionLayoutState( - currentScene, - ClockTransition.defaultClockTransitions, - enableInterruptions = false, - ) + MutableSceneTransitionLayoutState(currentScene, ClockTransition.defaultClockTransitions) } // Update state whenever currentSceneKey has changed. @@ -102,7 +98,7 @@ constructor( scene(splitShadeLargeClockScene) { LargeClockWithSmartSpace( smartSpacePaddingTop = smartSpacePaddingTop, - shouldOffSetClockToOneHalf = !hasCustomPositionUpdatedAnimation + shouldOffSetClockToOneHalf = !hasCustomPositionUpdatedAnimation, ) } @@ -114,21 +110,15 @@ constructor( } scene(smallClockScene) { - SmallClockWithSmartSpace( - smartSpacePaddingTop = smartSpacePaddingTop, - ) + SmallClockWithSmartSpace(smartSpacePaddingTop = smartSpacePaddingTop) } scene(largeClockScene) { - LargeClockWithSmartSpace( - smartSpacePaddingTop = smartSpacePaddingTop, - ) + LargeClockWithSmartSpace(smartSpacePaddingTop = smartSpacePaddingTop) } scene(WeatherClockScenes.largeClockScene) { - WeatherLargeClockWithSmartSpace( - smartSpacePaddingTop = smartSpacePaddingTop, - ) + WeatherLargeClockWithSmartSpace(smartSpacePaddingTop = smartSpacePaddingTop) } scene(WeatherClockScenes.splitShadeLargeClockScene) { @@ -154,7 +144,7 @@ constructor( SmallClock( burnInParams = burnIn.parameters, onTopChanged = burnIn.onSmallClockTopChanged, - modifier = Modifier.wrapContentSize() + modifier = Modifier.wrapContentSize(), ) } with(smartSpaceSection) { @@ -202,7 +192,7 @@ constructor( y = 0, ) } - } + }, ) } } @@ -226,10 +216,7 @@ constructor( Column(modifier = modifier) { val currentClock = currentClockState.value ?: return@Column with(weatherClockSection) { - Time( - clock = currentClock, - burnInParams = burnIn.parameters, - ) + Time(clock = currentClock, burnInParams = burnIn.parameters) } val density = LocalDensity.current val context = LocalContext.current @@ -242,7 +229,7 @@ constructor( modifier = Modifier.heightIn( min = getDimen(context, "enhanced_smartspace_height", density) - ) + ), ) } with(weatherClockSection) { 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 2745f6ea6bb4..4c6834cf6bea 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 @@ -47,7 +47,6 @@ import androidx.compose.foundation.layout.windowInsetsBottomHeight import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect @@ -60,7 +59,6 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.graphics.BlendMode import androidx.compose.ui.graphics.Color @@ -70,7 +68,6 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.LayoutCoordinates import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.layout.onPlaced import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.positionInWindow import androidx.compose.ui.platform.LocalConfiguration @@ -82,6 +79,7 @@ import androidx.compose.ui.unit.Velocity import androidx.compose.ui.unit.dp import androidx.compose.ui.util.lerp import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.android.compose.animation.scene.ContentKey import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.LowestZIndexContentPicker import com.android.compose.animation.scene.NestedScrollBehavior @@ -93,8 +91,9 @@ import com.android.systemui.common.ui.compose.windowinsets.LocalScreenCornerRadi import com.android.systemui.res.R import com.android.systemui.scene.session.ui.composable.SaveableSession import com.android.systemui.scene.session.ui.composable.rememberSession +import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.Scenes -import com.android.systemui.shade.shared.model.ShadeMode +import com.android.systemui.shade.shared.flag.DualShade import com.android.systemui.shade.ui.composable.ShadeHeader import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimRounding @@ -112,18 +111,16 @@ object Notifications { val NotificationStackPlaceholder = ElementKey("NotificationStackPlaceholder") val HeadsUpNotificationPlaceholder = ElementKey("HeadsUpNotificationPlaceholder", contentPicker = LowestZIndexContentPicker) - val ShelfSpace = ElementKey("ShelfSpace") val NotificationStackCutoffGuideline = ElementKey("NotificationStackCutoffGuideline") } - - // Expansion fraction thresholds (between 0-1f) at which the corresponding value should be - // at its maximum, given they are at their minimum value at expansion = 0f. - object TransitionThresholds { - const val EXPANSION_FOR_MAX_CORNER_RADIUS = 0.1f - const val EXPANSION_FOR_MAX_SCRIM_ALPHA = 0.3f - } } +private val notificationsShadeContentKey: ContentKey + get() = if (DualShade.isEnabled) Overlays.NotificationsShade else Scenes.Shade + +private val quickSettingsShadeContentKey: ContentKey + get() = if (DualShade.isEnabled) Overlays.QuickSettingsShade else Scenes.QuickSettings + /** * Adds the space where heads up notifications can appear in the scene. This should generally be the * entire size of the scene. @@ -146,7 +143,7 @@ fun SceneScope.HeadsUpNotificationSpace( // This element is sometimes opted out of the shared element system, so there // can be multiple instances of it during a transition. Thus we need to // determine which instance should feed its bounds to NSSL to avoid providing - // conflicting values + // conflicting values. val useBounds = useHunBounds() if (useBounds) { val positionInWindow = coordinates.positionInWindow() @@ -157,8 +154,8 @@ fun SceneScope.HeadsUpNotificationSpace( " bounds=$boundsInWindow" } // Note: boundsInWindow doesn't scroll off the screen, so use - // positionInWindow - // for top bound, which can scroll off screen while snoozing + // positionInWindow for top bound, which can scroll off screen while + // snoozing. stackScrollView.setHeadsUpTop(positionInWindow.y) stackScrollView.setHeadsUpBottom(boundsInWindow.bottom) } @@ -285,7 +282,8 @@ fun SceneScope.NotificationScrollingStack( shouldFillMaxSize: Boolean = true, shouldReserveSpaceForNavBar: Boolean = true, shouldIncludeHeadsUpSpace: Boolean = true, - shadeMode: ShadeMode, + shouldShowScrim: Boolean = true, + supportNestedScrolling: Boolean, onEmptySpaceClick: (() -> Unit)? = null, modifier: Modifier = Modifier, ) { @@ -293,6 +291,7 @@ fun SceneScope.NotificationScrollingStack( val density = LocalDensity.current val screenCornerRadius = LocalScreenCornerRadius.current val scrimCornerRadius = dimensionResource(R.dimen.notification_scrim_corner_radius) + val scrimBackgroundColor = MaterialTheme.colorScheme.surface val scrollState = shadeSession.rememberSaveableSession(saver = ScrollState.Saver, key = null) { ScrollState(initial = 0) @@ -427,8 +426,14 @@ fun SceneScope.NotificationScrollingStack( // completes. if ( scrimOffset.value < 0 && - layoutState.isTransitioning(from = Scenes.Shade, to = Scenes.Gone) || - layoutState.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen) + (layoutState.isTransitioning( + from = notificationsShadeContentKey, + to = Scenes.Gone, + ) || + layoutState.isTransitioning( + from = notificationsShadeContentKey, + to = Scenes.Lockscreen, + )) ) { IntOffset(x = 0, y = (scrimOffset.value * expansionFraction).roundToInt()) } else if ( @@ -498,7 +503,7 @@ fun SceneScope.NotificationScrollingStack( (expansionFraction / EXPANSION_FOR_MAX_SCRIM_ALPHA).coerceAtMost(1f) } else 1f } - .background(MaterialTheme.colorScheme.surface) + .thenIf(shouldShowScrim) { Modifier.background(scrimBackgroundColor) } .thenIf(shouldFillMaxSize) { Modifier.fillMaxSize() } .debugBackground(viewModel, DEBUG_BOX_COLOR) ) { @@ -508,7 +513,7 @@ fun SceneScope.NotificationScrollingStack( topBehavior = NestedScrollBehavior.EdgeWithPreview, isExternalOverscrollGesture = { isCurrentGestureOverscroll.value }, ) - .thenIf(shadeMode == ShadeMode.Single) { + .thenIf(supportNestedScrolling) { Modifier.nestedScroll(scrimNestedScrollConnection) } .stackVerticalOverscroll(coroutineScope) { scrollState.canScrollForward } @@ -550,38 +555,6 @@ fun SceneScope.NotificationScrollingStack( } /** - * This may be added to the lockscreen to provide a space to the start of the lock icon where the - * short shelf has room to flow vertically below the lock icon, but to its start, allowing more - * notifications to fit in the stack itself. (see: b/213934746) - * - * NOTE: this is totally unused for now; it is here to clarify the future plan - */ -@Composable -fun SceneScope.NotificationShelfSpace( - viewModel: NotificationsPlaceholderViewModel, - modifier: Modifier = Modifier, -) { - Text( - text = "Shelf Space", - modifier - .element(key = Notifications.Elements.ShelfSpace) - .fillMaxWidth() - .onPlaced { coordinates: LayoutCoordinates -> - debugLog(viewModel) { - ("SHELF onPlaced:" + - " size=${coordinates.size}" + - " bounds=${coordinates.boundsInWindow()}") - } - } - .clip(RoundedCornerShape(24.dp)) - .background(MaterialTheme.colorScheme.primaryContainer) - .padding(16.dp), - style = MaterialTheme.typography.titleLarge, - color = MaterialTheme.colorScheme.onPrimaryContainer, - ) -} - -/** * A 0 height horizontal spacer to be placed at the bottom-most position in the current scene, where * the notification contents (stack, footer, shelf) should be drawn. */ @@ -673,15 +646,19 @@ private suspend fun scrollNotificationStack( } } +private fun TransitionState.isOnLockscreen(): Boolean { + return currentScene == Scenes.Lockscreen && currentOverlays.isEmpty() +} + private fun shouldUseLockscreenStackBounds(state: TransitionState): Boolean { - return state is TransitionState.Idle && state.currentScene == Scenes.Lockscreen + return state is TransitionState.Idle && state.isOnLockscreen() } private fun shouldUseLockscreenHunBounds(state: TransitionState): Boolean { return when (state) { - is TransitionState.Idle -> state.currentScene == Scenes.Lockscreen + is TransitionState.Idle -> state.isOnLockscreen() is TransitionState.Transition -> - state.isTransitioning(from = Scenes.QuickSettings, to = Scenes.Lockscreen) + state.isTransitioning(from = quickSettingsShadeContentKey, to = Scenes.Lockscreen) } } @@ -690,7 +667,7 @@ private fun shouldAnimateScrimCornerRadius( shouldPunchHoleBehindScrim: Boolean, ): Boolean { return shouldPunchHoleBehindScrim || - state.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen) + state.isTransitioning(from = notificationsShadeContentKey, to = Scenes.Lockscreen) } private fun calculateCornerRadius( diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt index a22beccf3448..5b996704eb12 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt @@ -33,7 +33,6 @@ import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeOverlay import com.android.systemui.scene.session.ui.composable.SaveableSession import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.ui.composable.Overlay -import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.shade.ui.composable.ExpandedShadeHeader import com.android.systemui.shade.ui.composable.OverlayShade import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView @@ -69,9 +68,7 @@ constructor( } @Composable - override fun ContentScope.Content( - modifier: Modifier, - ) { + override fun ContentScope.Content(modifier: Modifier) { val viewModel = rememberViewModel("NotificationsShadeOverlay-viewModel") { contentViewModelFactory.create() @@ -81,10 +78,7 @@ constructor( viewModel.notificationsPlaceholderViewModelFactory.create() } - OverlayShade( - modifier = modifier, - onScrimClicked = viewModel::onScrimClicked, - ) { + OverlayShade(modifier = modifier, onScrimClicked = viewModel::onScrimClicked) { Column { ExpandedShadeHeader( viewModelFactory = viewModel.shadeHeaderViewModelFactory, @@ -102,7 +96,8 @@ constructor( shouldPunchHoleBehindScrim = false, shouldFillMaxSize = false, shouldReserveSpaceForNavBar = false, - shadeMode = ShadeMode.Dual, + shouldShowScrim = false, + supportNestedScrolling = false, modifier = Modifier.fillMaxWidth(), ) diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt index 630497998c3e..d75a776a2515 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt @@ -100,7 +100,6 @@ import com.android.systemui.res.R import com.android.systemui.scene.session.ui.composable.SaveableSession import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.Scene -import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.shade.ui.composable.CollapsedShadeHeader import com.android.systemui.shade.ui.composable.ExpandedShadeHeader import com.android.systemui.shade.ui.composable.Shade @@ -114,11 +113,9 @@ import dagger.Lazy import javax.inject.Inject import javax.inject.Named import kotlin.math.roundToInt -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow /** The Quick Settings (AKA "QS") scene shows the quick setting tiles. */ -@OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class QuickSettingsScene @Inject @@ -420,17 +417,26 @@ private fun SceneScope.QuickSettingsScene( .navigationBarsPadding() .padding(horizontal = shadeHorizontalPadding), ) + + // The minimum possible value for the top of the notification stack. In other words: how + // high is the notification stack allowed to get when the scene is at rest. It may still be + // translated farther upwards by a transition animation but, at rest, the top edge of its + // bounds must be limited to be at or below this value. + // + // A 1 pixel is added to compensate for any kind of rounding errors to make sure 100% that + // the notification stack is entirely "below" the entire screen. + val minNotificationStackTop = screenHeight.roundToInt() + 1 NotificationScrollingStack( shadeSession = shadeSession, stackScrollView = notificationStackScrollView, viewModel = notificationsPlaceholderViewModel, - maxScrimTop = { screenHeight }, + maxScrimTop = { minNotificationStackTop.toFloat() }, shouldPunchHoleBehindScrim = shouldPunchHoleBehindScrim, shouldIncludeHeadsUpSpace = false, - shadeMode = ShadeMode.Single, + supportNestedScrolling = true, modifier = Modifier.fillMaxWidth() - .offset { IntOffset(x = 0, y = screenHeight.roundToInt()) } + .offset { IntOffset(x = 0, y = minNotificationStackTop) } .padding(horizontal = shadeHorizontalPadding), ) NotificationStackCutoffGuideline( @@ -439,7 +445,7 @@ private fun SceneScope.QuickSettingsScene( modifier = Modifier.align(Alignment.BottomCenter) .navigationBarsPadding() - .offset { IntOffset(x = 0, y = screenHeight.roundToInt()) } + .offset { IntOffset(x = 0, y = minNotificationStackTop) } .padding(horizontal = shadeHorizontalPadding), ) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt index 56de096effce..417f2b8922e4 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt @@ -81,7 +81,6 @@ fun SceneContainer( initialScene = initialSceneKey, canChangeScene = { toScene -> viewModel.canChangeScene(toScene) }, transitions = SceneContainerTransitions, - enableInterruptions = false, ) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerInterruptionHandler.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerInterruptionHandler.kt new file mode 100644 index 000000000000..7e99847a7200 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerInterruptionHandler.kt @@ -0,0 +1,72 @@ +/* + * 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.scene.ui.composable + +import com.android.compose.animation.scene.InterruptionHandler +import com.android.compose.animation.scene.InterruptionResult +import com.android.compose.animation.scene.SceneKey +import com.android.compose.animation.scene.content.state.TransitionState +import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.scene.ui.composable.transitions.TO_BOUNCER_FADE_FRACTION + +object SceneContainerInterruptionHandler : InterruptionHandler { + override fun onInterruption( + interrupted: TransitionState.Transition.ChangeScene, + newTargetScene: SceneKey, + ): InterruptionResult? { + return handleTransitionToGoneDuringTransitionToBouncer(interrupted, newTargetScene) + } + + /** + * Handle the case where we start transitioning to Bouncer but then we are interrupted to + * transition to Gone, for instance because face auth kicked in. + */ + private fun handleTransitionToGoneDuringTransitionToBouncer( + transition: TransitionState.Transition.ChangeScene, + targetScene: SceneKey, + ): InterruptionResult? { + if (targetScene != Scenes.Gone || !transition.isTransitioningFromOrTo(Scenes.Bouncer)) { + return null + } + + // Animate Bouncer => Gone only when the bouncer is fully opaque, otherwise animate + // OtherScene => Gone and reverse the OtherScene => Bouncer transition (note: OtherScene is + // usually the Lockscreen scene). + val otherScene: SceneKey + val animatesFromBouncer = + if (transition.isTransitioning(to = Scenes.Bouncer)) { + otherScene = transition.fromScene + transition.progress >= TO_BOUNCER_FADE_FRACTION + } else { + otherScene = transition.toScene + transition.progress <= 1f - TO_BOUNCER_FADE_FRACTION + } + + return if (animatesFromBouncer) { + InterruptionResult( + animateFrom = Scenes.Bouncer, + + // We don't want the content of the lockscreen to be shown during the Bouncer => + // Launcher transition. We disable chaining of the transitions so that only the + // Bouncer and Launcher scenes are composed. + chain = false, + ) + } else { + InterruptionResult(animateFrom = otherScene) + } + } +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt index ac58ab5296f6..dc545b8bf7c2 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt @@ -1,5 +1,6 @@ package com.android.systemui.scene.ui.composable +import androidx.compose.animation.core.spring import androidx.compose.foundation.gestures.Orientation import com.android.compose.animation.scene.ProgressConverter import com.android.compose.animation.scene.TransitionKey @@ -12,11 +13,15 @@ import com.android.systemui.scene.shared.model.TransitionKeys.SlightlyFasterShad import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade import com.android.systemui.scene.ui.composable.transitions.bouncerToGoneTransition import com.android.systemui.scene.ui.composable.transitions.bouncerToLockscreenPreview +import com.android.systemui.scene.ui.composable.transitions.communalToBouncerTransition +import com.android.systemui.scene.ui.composable.transitions.communalToShadeTransition +import com.android.systemui.scene.ui.composable.transitions.dreamToGoneTransition import com.android.systemui.scene.ui.composable.transitions.goneToQuickSettingsTransition import com.android.systemui.scene.ui.composable.transitions.goneToShadeTransition import com.android.systemui.scene.ui.composable.transitions.goneToSplitShadeTransition import com.android.systemui.scene.ui.composable.transitions.lockscreenToBouncerTransition import com.android.systemui.scene.ui.composable.transitions.lockscreenToCommunalTransition +import com.android.systemui.scene.ui.composable.transitions.lockscreenToDreamTransition import com.android.systemui.scene.ui.composable.transitions.lockscreenToGoneTransition import com.android.systemui.scene.ui.composable.transitions.lockscreenToQuickSettingsTransition import com.android.systemui.scene.ui.composable.transitions.lockscreenToShadeTransition @@ -41,13 +46,16 @@ import com.android.systemui.shade.ui.composable.Shade * Please keep the list sorted alphabetically. */ val SceneContainerTransitions = transitions { + interruptionHandler = SceneContainerInterruptionHandler // Overscroll progress starts linearly with some resistance (3f) and slowly approaches 0.2f defaultOverscrollProgressConverter = ProgressConverter.tanh(maxProgress = 0.2f, tilt = 3f) + defaultSwipeSpec = spring(stiffness = 300f, dampingRatio = 0.8f, visibilityThreshold = 0.5f) // Scene transitions from(Scenes.Bouncer, to = Scenes.Gone) { bouncerToGoneTransition() } + from(Scenes.Dream, to = Scenes.Gone) { dreamToGoneTransition() } from(Scenes.Gone, to = Scenes.Shade) { goneToShadeTransition() } from(Scenes.Gone, to = Scenes.Shade, key = ToSplitShade) { goneToSplitShadeTransition() } from(Scenes.Gone, to = Scenes.Shade, key = SlightlyFasterShadeCollapse) { @@ -68,6 +76,7 @@ val SceneContainerTransitions = transitions { lockscreenToBouncerTransition() } from(Scenes.Lockscreen, to = Scenes.Communal) { lockscreenToCommunalTransition() } + from(Scenes.Lockscreen, to = Scenes.Dream) { lockscreenToDreamTransition() } from(Scenes.Lockscreen, to = Scenes.Shade) { lockscreenToShadeTransition() } from(Scenes.Lockscreen, to = Scenes.Shade, key = ToSplitShade) { lockscreenToSplitShadeTransition() @@ -87,6 +96,8 @@ val SceneContainerTransitions = transitions { sharedElement(Notifications.Elements.NotificationStackPlaceholder, enabled = false) sharedElement(Notifications.Elements.HeadsUpNotificationPlaceholder, enabled = false) } + from(Scenes.Communal, to = Scenes.Shade) { communalToShadeTransition() } + from(Scenes.Communal, to = Scenes.Bouncer) { communalToBouncerTransition() } // Overlay transitions diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToBouncerTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToBouncerTransition.kt new file mode 100644 index 000000000000..d7173fd3cffb --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToBouncerTransition.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.scene.ui.composable.transitions + +import com.android.compose.animation.scene.TransitionBuilder + +fun TransitionBuilder.communalToBouncerTransition() { + toBouncerTransition() +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToShadeTransition.kt new file mode 100644 index 000000000000..ba920acec0a5 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromCommunalToShadeTransition.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.scene.ui.composable.transitions + +import com.android.compose.animation.scene.TransitionBuilder + +fun TransitionBuilder.communalToShadeTransition() { + toShadeTransition() +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromDreamToGoneTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromDreamToGoneTransition.kt new file mode 100644 index 000000000000..60dc4c05e99d --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromDreamToGoneTransition.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.scene.ui.composable.transitions + +import androidx.compose.animation.core.tween +import com.android.compose.animation.scene.TransitionBuilder +import com.android.systemui.scene.shared.model.Scenes + +fun TransitionBuilder.dreamToGoneTransition() { + spec = tween(durationMillis = 1000) + + fade(Scenes.Dream.rootElementKey) +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt index 4c0efd2047ff..dd37b533ae4c 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt @@ -1,29 +1,11 @@ package com.android.systemui.scene.ui.composable.transitions import androidx.compose.animation.core.CubicBezierEasing -import androidx.compose.animation.core.tween -import androidx.compose.ui.unit.dp import com.android.compose.animation.scene.TransitionBuilder -import com.android.compose.animation.scene.UserActionDistance import com.android.systemui.bouncer.ui.composable.Bouncer -const val FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION = 0.5f -const val FROM_LOCK_SCREEN_TO_BOUNCER_SWIPE_DISTANCE_FRACTION = 0.5f - fun TransitionBuilder.lockscreenToBouncerTransition() { - spec = tween(durationMillis = 500) - - distance = UserActionDistance { fromSceneSize, _ -> - fromSceneSize.height * FROM_LOCK_SCREEN_TO_BOUNCER_SWIPE_DISTANCE_FRACTION - } - - translate(Bouncer.Elements.Content, y = 300.dp) - fractionRange(end = FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION) { - fade(Bouncer.Elements.Background) - } - fractionRange(start = FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION) { - fade(Bouncer.Elements.Content) - } + toBouncerTransition() } fun TransitionBuilder.bouncerToLockscreenPreview() { diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToDreamTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToDreamTransition.kt new file mode 100644 index 000000000000..7092e3f68f93 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToDreamTransition.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.scene.ui.composable.transitions + +import androidx.compose.animation.core.tween +import com.android.compose.animation.scene.TransitionBuilder +import com.android.systemui.scene.shared.model.Scenes + +fun TransitionBuilder.lockscreenToDreamTransition() { + spec = tween(durationMillis = 1000) + + fade(Scenes.Lockscreen.rootElementKey) +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.kt new file mode 100644 index 000000000000..de76f708c1c7 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToBouncerTransition.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.scene.ui.composable.transitions + +import androidx.compose.animation.core.tween +import androidx.compose.ui.unit.dp +import com.android.compose.animation.scene.TransitionBuilder +import com.android.compose.animation.scene.UserActionDistance +import com.android.systemui.bouncer.ui.composable.Bouncer + +const val TO_BOUNCER_FADE_FRACTION = 0.5f +private const val TO_BOUNCER_SWIPE_DISTANCE_FRACTION = 0.5f + +fun TransitionBuilder.toBouncerTransition() { + spec = tween(durationMillis = 500) + + distance = UserActionDistance { fromSceneSize, _ -> + fromSceneSize.height * TO_BOUNCER_SWIPE_DISTANCE_FRACTION + } + + translate(Bouncer.Elements.Content, y = 300.dp) + fractionRange(end = TO_BOUNCER_FADE_FRACTION) { fade(Bouncer.Elements.Background) } + fractionRange(start = TO_BOUNCER_FADE_FRACTION) { fade(Bouncer.Elements.Content) } +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToNotificationsShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToNotificationsShadeTransition.kt index 337f53a58844..23c4f12cb0ae 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToNotificationsShadeTransition.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToNotificationsShadeTransition.kt @@ -21,26 +21,20 @@ import androidx.compose.animation.core.spring import androidx.compose.animation.core.tween import com.android.compose.animation.scene.Edge import com.android.compose.animation.scene.TransitionBuilder -import com.android.compose.animation.scene.UserActionDistance import com.android.systemui.notifications.ui.composable.Notifications import com.android.systemui.shade.ui.composable.OverlayShade import com.android.systemui.shade.ui.composable.Shade import com.android.systemui.shade.ui.composable.ShadeHeader import kotlin.time.Duration.Companion.milliseconds -fun TransitionBuilder.toNotificationsShadeTransition( - durationScale: Double = 1.0, -) { +fun TransitionBuilder.toNotificationsShadeTransition(durationScale: Double = 1.0) { spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt()) swipeSpec = spring( stiffness = Spring.StiffnessMediumLow, visibilityThreshold = Shade.Dimensions.ScrimVisibilityThreshold, ) - distance = UserActionDistance { fromSceneSize, orientation -> - fromSceneSize.height.toFloat() * 2 / 3f - } - + scaleSize(OverlayShade.Elements.Panel, height = 0f) translate(OverlayShade.Elements.Panel, Edge.Top) fractionRange(end = .5f) { fade(OverlayShade.Elements.Scrim) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt index c6c42fce7553..3ec057becc18 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt @@ -40,7 +40,6 @@ import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.systemBars import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect @@ -89,7 +88,6 @@ import com.android.systemui.media.controls.ui.composable.shouldElevateMedia import com.android.systemui.media.controls.ui.controller.MediaCarouselController import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager import com.android.systemui.media.controls.ui.view.MediaHost -import com.android.systemui.media.controls.ui.view.MediaHostState import com.android.systemui.media.controls.ui.view.MediaHostState.Companion.COLLAPSED import com.android.systemui.media.controls.ui.view.MediaHostState.Companion.EXPANDED import com.android.systemui.media.dagger.MediaModule.QS_PANEL @@ -117,7 +115,6 @@ import dagger.Lazy import javax.inject.Inject import javax.inject.Named import kotlin.math.roundToInt -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow object Shade { @@ -128,23 +125,13 @@ object Shade { } object Dimensions { - val ScrimCornerSize = 32.dp val HorizontalPadding = 16.dp val ScrimOverscrollLimit = 32.dp const val ScrimVisibilityThreshold = 5f } - - object Shapes { - val Scrim = - RoundedCornerShape( - topStart = Dimensions.ScrimCornerSize, - topEnd = Dimensions.ScrimCornerSize, - ) - } } /** The shade scene shows scrolling list of notifications and some of the quick setting tiles. */ -@OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class ShadeScene @Inject @@ -197,11 +184,11 @@ constructor( ) init { - qqsMediaHost.expansion = MediaHostState.EXPANDED + qqsMediaHost.expansion = EXPANDED qqsMediaHost.showsOnlyActiveMedia = true qqsMediaHost.init(MediaHierarchyManager.LOCATION_QQS) - qsMediaHost.expansion = MediaHostState.EXPANDED + qsMediaHost.expansion = EXPANDED qsMediaHost.showsOnlyActiveMedia = false qsMediaHost.init(MediaHierarchyManager.LOCATION_QS) } @@ -329,8 +316,7 @@ private fun SceneScope.SingleShade( modifier = modifier.thenIf(shouldPunchHoleBehindScrim) { // Render the scene to an offscreen buffer so that BlendMode.DstOut only clears this - // scene - // (and not the one under it) during a scene transition. + // scene (and not the one under it) during a scene transition. Modifier.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen) } ) { @@ -382,8 +368,8 @@ private fun SceneScope.SingleShade( stackScrollView = notificationStackScrollView, viewModel = notificationsPlaceholderViewModel, maxScrimTop = { maxNotifScrimTop.toFloat() }, - shadeMode = ShadeMode.Single, shouldPunchHoleBehindScrim = shouldPunchHoleBehindScrim, + supportNestedScrolling = true, onEmptySpaceClick = viewModel::onEmptySpaceClicked.takeIf { isEmptySpaceClickable }, modifier = @@ -601,7 +587,7 @@ private fun SceneScope.SplitShade( maxScrimTop = { 0f }, shouldPunchHoleBehindScrim = false, shouldReserveSpaceForNavBar = false, - shadeMode = ShadeMode.Split, + supportNestedScrolling = false, onEmptySpaceClick = viewModel::onEmptySpaceClicked.takeIf { isEmptySpaceClickable }, modifier = 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 5fa5db880cce..085157ac72b9 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 @@ -226,7 +226,6 @@ internal class DraggableHandlerImpl( val fromSource = resolveSwipeSource(startedPosition) val upOrLeft = resolveSwipe(pointersDown, fromSource, isUpOrLeft = true) val downOrRight = resolveSwipe(pointersDown, fromSource, isUpOrLeft = false) - return if (fromSource == null) { Swipes( upOrLeft = null, @@ -366,10 +365,18 @@ private class DragControllerImpl( return 0f } + val currentTransitionIrreversible = + if (swipeAnimation.isUpOrLeft) { + swipes.upOrLeftResult?.isIrreversible ?: false + } else { + swipes.downOrRightResult?.isIrreversible ?: false + } + val needNewTransition = - hasReachedToContent || - result.toContent(layoutState.currentScene) != swipeAnimation.toContent || - result.transitionKey != swipeAnimation.contentTransition.key + !currentTransitionIrreversible && + (hasReachedToContent || + result.toContent(layoutState.currentScene) != swipeAnimation.toContent || + result.transitionKey != swipeAnimation.contentTransition.key) if (needNewTransition) { // Make sure the current transition will finish to the right current scene. diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt index 5ddc28485ac6..aa70a0ce156b 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt @@ -128,7 +128,7 @@ internal class MultiPointerDraggableNode( var onDragStarted: (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> DragController, var onFirstPointerDown: () -> Unit, - var swipeDetector: SwipeDetector = DefaultSwipeDetector, + swipeDetector: SwipeDetector = DefaultSwipeDetector, private val dispatcher: NestedScrollDispatcher, ) : DelegatingNode(), @@ -139,6 +139,14 @@ internal class MultiPointerDraggableNode( private val pointerInput = delegate(SuspendingPointerInputModifierNode { pointerInput() }) private val velocityTracker = VelocityTracker() + var swipeDetector: SwipeDetector = swipeDetector + set(value) { + if (value != field) { + field = value + pointerInput.resetPointerInputHandler() + } + } + private var converter = SpaceVectorConverter(orientation) override fun Offset.toFloat(): Float = with(converter) { this@toFloat.toFloat() } 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 cec888380513..c9a4d5808cac 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 @@ -498,6 +498,12 @@ sealed class UserActionResult( * bigger than 100% when the user released their finger. ` */ open val requiresFullDistanceSwipe: Boolean, + + /** + * Whether swiping back in the opposite direction past the origin point of the swipe can replace + * the action with the action for the opposite direction. + */ + open val isIrreversible: Boolean = false, ) { internal abstract fun toContent(currentScene: SceneKey): ContentKey @@ -507,6 +513,7 @@ sealed class UserActionResult( val toScene: SceneKey, override val transitionKey: TransitionKey? = null, override val requiresFullDistanceSwipe: Boolean = false, + override val isIrreversible: Boolean = false, ) : UserActionResult(transitionKey, requiresFullDistanceSwipe) { override fun toContent(currentScene: SceneKey): ContentKey = toScene } @@ -516,6 +523,7 @@ sealed class UserActionResult( val overlay: OverlayKey, override val transitionKey: TransitionKey? = null, override val requiresFullDistanceSwipe: Boolean = false, + override val isIrreversible: Boolean = false, ) : UserActionResult(transitionKey, requiresFullDistanceSwipe) { override fun toContent(currentScene: SceneKey): ContentKey = overlay } @@ -558,7 +566,14 @@ sealed class UserActionResult( * the user released their finger. */ requiresFullDistanceSwipe: Boolean = false, - ): UserActionResult = ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe) + + /** + * Whether swiping back in the opposite direction past the origin point of the swipe can + * replace the action with the action for the opposite direction. + */ + isIrreversible: Boolean = false, + ): UserActionResult = + ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe, isIrreversible) /** A [UserActionResult] that shows [toOverlay]. */ operator fun invoke( 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 b358faf2c418..879dc542552c 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 @@ -152,6 +152,7 @@ internal constructor( internal val DefaultSwipeSpec = spring( stiffness = Spring.StiffnessMediumLow, + dampingRatio = Spring.DampingRatioLowBouncy, visibilityThreshold = OffsetVisibilityThreshold, ) 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 d201be9acc12..061583a64702 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 @@ -68,17 +68,36 @@ private fun Content.shouldEnableSwipes(orientation: Orientation): Boolean { private data class SwipeToSceneElement( val draggableHandler: DraggableHandlerImpl, val swipeDetector: SwipeDetector, -) : ModifierNodeElement<SwipeToSceneNode>() { - override fun create(): SwipeToSceneNode = SwipeToSceneNode(draggableHandler, swipeDetector) +) : ModifierNodeElement<SwipeToSceneRootNode>() { + override fun create(): SwipeToSceneRootNode = + SwipeToSceneRootNode(draggableHandler, swipeDetector) - override fun update(node: SwipeToSceneNode) { - node.draggableHandler = draggableHandler + override fun update(node: SwipeToSceneRootNode) { + node.update(draggableHandler, swipeDetector) } } -private class SwipeToSceneNode( +private class SwipeToSceneRootNode( draggableHandler: DraggableHandlerImpl, swipeDetector: SwipeDetector, +) : DelegatingNode() { + private var delegate = delegate(SwipeToSceneNode(draggableHandler, swipeDetector)) + + fun update(draggableHandler: DraggableHandlerImpl, swipeDetector: SwipeDetector) { + if (draggableHandler == delegate.draggableHandler) { + // Simple update, just update the swipe detector directly and keep the node. + delegate.swipeDetector = swipeDetector + } else { + // The draggableHandler changed, force recreate the underlying SwipeToSceneNode. + undelegate(delegate) + delegate = delegate(SwipeToSceneNode(draggableHandler, swipeDetector)) + } + } +} + +private class SwipeToSceneNode( + val draggableHandler: DraggableHandlerImpl, + swipeDetector: SwipeDetector, ) : DelegatingNode(), PointerInputModifierNode { private val dispatcher = NestedScrollDispatcher() private val multiPointerDraggableNode = @@ -93,18 +112,10 @@ private class SwipeToSceneNode( ) ) - private var _draggableHandler = draggableHandler - var draggableHandler: DraggableHandlerImpl - get() = _draggableHandler + var swipeDetector: SwipeDetector + get() = multiPointerDraggableNode.swipeDetector set(value) { - if (_draggableHandler != value) { - _draggableHandler = value - - // Make sure to update the delegate orientation. Note that this will automatically - // reset the underlying pointer input handler, so previous gestures will be - // cancelled. - multiPointerDraggableNode.orientation = value.orientation - } + multiPointerDraggableNode.swipeDetector = value } private val nestedScrollHandlerImpl = 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 a6ebb0e3ba56..a3641e6635e7 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 @@ -34,71 +34,76 @@ internal typealias SuspendedValue<T> = suspend () -> T * Note: Call [reset] before destroying this object to make sure you always get a call to [onStop] * after [onStart]. * - * @sample com.android.compose.animation.scene.rememberSwipeToSceneNestedScrollConnection + * @sample LargeTopAppBarNestedScrollConnection + * @sample com.android.compose.animation.scene.NestedScrollHandlerImpl.nestedScrollConnection */ class PriorityNestedScrollConnection( - private val canStartPreScroll: (offsetAvailable: Offset, offsetBeforeStart: Offset) -> Boolean, - private val canStartPostScroll: (offsetAvailable: Offset, offsetBeforeStart: Offset) -> Boolean, - private val canStartPostFling: (velocityAvailable: Velocity) -> Boolean, + orientation: Orientation, + private val canStartPreScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean, + private val canStartPostScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean, + private val canStartPostFling: (velocityAvailable: Float) -> Boolean, private val canContinueScroll: (source: NestedScrollSource) -> Boolean, private val canScrollOnFling: Boolean, - private val onStart: (offsetAvailable: Offset) -> Unit, - private val onScroll: (offsetAvailable: Offset) -> Offset, - private val onStop: (velocityAvailable: Velocity) -> SuspendedValue<Velocity>, -) : NestedScrollConnection { + private val onStart: (offsetAvailable: Float) -> Unit, + private val onScroll: (offsetAvailable: Float) -> Float, + private val onStop: (velocityAvailable: Float) -> SuspendedValue<Float>, +) : NestedScrollConnection, SpaceVectorConverter by SpaceVectorConverter(orientation) { /** In priority mode [onPreScroll] events are first consumed by the parent, via [onScroll]. */ private var isPriorityMode = false - private var offsetScrolledBeforePriorityMode = Offset.Zero + private var offsetScrolledBeforePriorityMode = 0f override fun onPostScroll( consumed: Offset, available: Offset, source: NestedScrollSource, ): Offset { + val availableFloat = available.toFloat() // The offset before the start takes into account the up and down movements, starting from // the beginning or from the last fling gesture. - val offsetBeforeStart = offsetScrolledBeforePriorityMode - available + val offsetBeforeStart = offsetScrolledBeforePriorityMode - availableFloat if ( isPriorityMode || (source == NestedScrollSource.SideEffect && !canScrollOnFling) || - !canStartPostScroll(available, offsetBeforeStart) + !canStartPostScroll(availableFloat, offsetBeforeStart) ) { // The priority mode cannot start so we won't consume the available offset. return Offset.Zero } - return onPriorityStart(available) + return onPriorityStart(availableFloat).toOffset() } override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { if (!isPriorityMode) { if (source == NestedScrollSource.UserInput || canScrollOnFling) { - if (canStartPreScroll(available, offsetScrolledBeforePriorityMode)) { - return onPriorityStart(available) + val availableFloat = available.toFloat() + if (canStartPreScroll(availableFloat, offsetScrolledBeforePriorityMode)) { + return onPriorityStart(availableFloat).toOffset() } // We want to track the amount of offset consumed before entering priority mode - offsetScrolledBeforePriorityMode += available + offsetScrolledBeforePriorityMode += availableFloat } return Offset.Zero } + val availableFloat = available.toFloat() if (!canContinueScroll(source)) { // Step 3a: We have lost priority and we no longer need to intercept scroll events. - onPriorityStop(velocity = Velocity.Zero) + onPriorityStop(velocity = 0f) - // We've just reset offsetScrolledBeforePriorityMode to Offset.Zero + // We've just reset offsetScrolledBeforePriorityMode to 0f // We want to track the amount of offset consumed before entering priority mode - offsetScrolledBeforePriorityMode += available + offsetScrolledBeforePriorityMode += availableFloat return Offset.Zero } // Step 2: We have the priority and can consume the scroll events. - return onScroll(available) + return onScroll(availableFloat).toOffset() } override suspend fun onPreFling(available: Velocity): Velocity { @@ -108,15 +113,16 @@ class PriorityNestedScrollConnection( } // Step 3b: The finger is lifted, we can stop intercepting scroll events and use the speed // of the fling gesture. - return onPriorityStop(velocity = available).invoke() + return onPriorityStop(velocity = available.toFloat()).invoke().toVelocity() } override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity { + val availableFloat = available.toFloat() if (isPriorityMode) { - return onPriorityStop(velocity = available).invoke() + return onPriorityStop(velocity = availableFloat).invoke().toVelocity() } - if (!canStartPostFling(available)) { + if (!canStartPostFling(availableFloat)) { return Velocity.Zero } @@ -124,11 +130,11 @@ class PriorityNestedScrollConnection( // given the available velocity. // TODO(b/291053278): Remove canStartPostFling() and instead make it possible to define the // overscroll behavior on the Scene level. - val smallOffset = Offset(available.x.sign, available.y.sign) - onPriorityStart(available = smallOffset) + val smallOffset = availableFloat.sign + onPriorityStart(availableOffset = smallOffset) // This is the last event of a scroll gesture. - return onPriorityStop(available).invoke() + return onPriorityStop(availableFloat).invoke().toVelocity() } /** @@ -138,10 +144,10 @@ class PriorityNestedScrollConnection( */ fun reset() { // Step 3c: To ensure that an onStop is always called for every onStart. - onPriorityStop(velocity = Velocity.Zero) + onPriorityStop(velocity = 0f) } - private fun onPriorityStart(available: Offset): Offset { + private fun onPriorityStart(availableOffset: Float): Float { if (isPriorityMode) { error("This should never happen, onPriorityStart() was called when isPriorityMode") } @@ -152,17 +158,17 @@ class PriorityNestedScrollConnection( // Note: onStop will be called if we cannot continue to scroll (step 3a), or the finger is // lifted (step 3b), or this object has been destroyed (step 3c). - onStart(available) + onStart(availableOffset) - return onScroll(available) + return onScroll(availableOffset) } - private fun onPriorityStop(velocity: Velocity): SuspendedValue<Velocity> { + private fun onPriorityStop(velocity: Float): SuspendedValue<Float> { // We can restart tracking the consumed offsets from scratch. - offsetScrolledBeforePriorityMode = Offset.Zero + offsetScrolledBeforePriorityMode = 0f if (!isPriorityMode) { - return { Velocity.Zero } + return { 0f } } isPriorityMode = false @@ -170,38 +176,3 @@ class PriorityNestedScrollConnection( return onStop(velocity) } } - -fun PriorityNestedScrollConnection( - orientation: Orientation, - canStartPreScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean, - canStartPostScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean, - canStartPostFling: (velocityAvailable: Float) -> Boolean, - canContinueScroll: (source: NestedScrollSource) -> Boolean, - canScrollOnFling: Boolean, - onStart: (offsetAvailable: Float) -> Unit, - onScroll: (offsetAvailable: Float) -> Float, - onStop: (velocityAvailable: Float) -> SuspendedValue<Float>, -) = - with(SpaceVectorConverter(orientation)) { - PriorityNestedScrollConnection( - canStartPreScroll = { offsetAvailable: Offset, offsetBeforeStart: Offset -> - canStartPreScroll(offsetAvailable.toFloat(), offsetBeforeStart.toFloat()) - }, - canStartPostScroll = { offsetAvailable: Offset, offsetBeforeStart: Offset -> - canStartPostScroll(offsetAvailable.toFloat(), offsetBeforeStart.toFloat()) - }, - canStartPostFling = { velocityAvailable: Velocity -> - canStartPostFling(velocityAvailable.toFloat()) - }, - canContinueScroll = canContinueScroll, - canScrollOnFling = canScrollOnFling, - onStart = { offsetAvailable -> onStart(offsetAvailable.toFloat()) }, - onScroll = { offsetAvailable: Offset -> - onScroll(offsetAvailable.toFloat()).toOffset() - }, - onStop = { velocityAvailable: Velocity -> - val consumedVelocity = onStop(velocityAvailable.toFloat()) - suspend { consumedVelocity.invoke().toVelocity() } - }, - ) - } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt index dd4f99f5c64e..ecef6be49df8 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt @@ -507,6 +507,54 @@ class DraggableHandlerTest { } @Test + fun onDragWithActionsInBothDirections_dragToOppositeDirectionReplacesAction() = runGestureTest { + // We are on SceneA. UP -> B, DOWN-> C. + val dragController = onDragStarted(overSlop = up(fractionOfScreen = 0.2f)) + assertTransition( + currentScene = SceneA, + fromScene = SceneA, + toScene = SceneB, + progress = 0.2f, + ) + + // Reverse drag direction, it will replace the previous transition + dragController.onDragDelta(pixels = down(fractionOfScreen = 0.5f)) + assertTransition( + currentScene = SceneA, + fromScene = SceneA, + toScene = SceneC, + progress = 0.3f, + ) + } + + @Test + fun onDragWithActionsInBothDirections_dragToOppositeDirectionNotReplaceable() = runGestureTest { + // We are on SceneA. UP -> B, DOWN-> C. The up swipe is not replaceable though. + mutableUserActionsA = + mapOf(Swipe.Up to UserActionResult(SceneB, isIrreversible = true), Swipe.Down to SceneC) + val dragController = + onDragStarted( + startedPosition = Offset(SCREEN_SIZE * 0.5f, SCREEN_SIZE * 0.5f), + overSlop = up(fractionOfScreen = 0.2f), + ) + assertTransition( + currentScene = SceneA, + fromScene = SceneA, + toScene = SceneB, + progress = 0.2f, + ) + + // Reverse drag direction, it cannot replace the previous transition + dragController.onDragDelta(pixels = down(fractionOfScreen = 0.5f)) + assertTransition( + currentScene = SceneA, + fromScene = SceneA, + toScene = SceneB, + progress = -0.3f, + ) + } + + @Test fun onDragFromEdge_startTransitionToEdgeAction() = runGestureTest { navigateToSceneC() @@ -1241,7 +1289,8 @@ class DraggableHandlerTest { fun overscroll_releaseBetween0And100Percent_up() = runGestureTest { // Make scene B overscrollable. layoutState.transitions = transitions { - from(SceneA, to = SceneB) { spec = spring(dampingRatio = Spring.DampingRatioNoBouncy) } + defaultSwipeSpec = spring(dampingRatio = Spring.DampingRatioNoBouncy) + from(SceneA, to = SceneB) {} overscroll(SceneB, Orientation.Vertical) { fade(TestElements.Foo) } } @@ -1272,7 +1321,8 @@ class DraggableHandlerTest { fun overscroll_releaseBetween0And100Percent_down() = runGestureTest { // Make scene C overscrollable. layoutState.transitions = transitions { - from(SceneA, to = SceneC) { spec = spring(dampingRatio = Spring.DampingRatioNoBouncy) } + defaultSwipeSpec = spring(dampingRatio = Spring.DampingRatioNoBouncy) + from(SceneA, to = SceneC) {} overscroll(SceneC, Orientation.Vertical) { fade(TestElements.Foo) } } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt index ce64628a863c..28d0a473935d 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt @@ -46,6 +46,8 @@ import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTouchInput +import androidx.compose.ui.test.swipeRight +import androidx.compose.ui.test.swipeUp import androidx.compose.ui.test.swipeWithVelocity import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.IntSize @@ -876,4 +878,37 @@ class SwipeToSceneTest { repeat(3) { rule.onRoot().performClick() } rule.onNodeWithTag(buttonTag).assertTextEquals("Count: 3") } + + @Test + fun swipeToSceneSupportsUpdates() { + val state = rule.runOnUiThread { MutableSceneTransitionLayoutState(SceneA) } + + rule.setContent { + SceneTransitionLayout(state) { + // SceneA only has vertical actions, so only one vertical Modifier.swipeToScene() + // is composed. + scene(SceneA, mapOf(Swipe.Up to SceneB)) { Box(Modifier.fillMaxSize()) } + + // SceneB only has horizontal actions, so only one vertical Modifier.swipeToScene() + // is composed, which will be force update it with a new draggableHandler. + scene(SceneB, mapOf(Swipe.Right to SceneC)) { Box(Modifier.fillMaxSize()) } + scene(SceneC) { Box(Modifier.fillMaxSize()) } + } + } + + assertThat(state.transitionState).isIdle() + assertThat(state.transitionState).hasCurrentScene(SceneA) + + // Swipe up to scene B. + rule.onRoot().performTouchInput { swipeUp() } + rule.waitForIdle() + assertThat(state.transitionState).isIdle() + assertThat(state.transitionState).hasCurrentScene(SceneB) + + // Swipe right to scene C. + rule.onRoot().performTouchInput { swipeRight() } + rule.waitForIdle() + assertThat(state.transitionState).isIdle() + assertThat(state.transitionState).hasCurrentScene(SceneC) + } } diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt index bde769920676..badc43bd3e0f 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt @@ -18,8 +18,9 @@ package com.android.compose.nestedscroll +import androidx.compose.foundation.gestures.Orientation import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.input.nestedscroll.NestedScrollSource +import androidx.compose.ui.input.nestedscroll.NestedScrollSource.Companion.UserInput import androidx.compose.ui.unit.Velocity import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat @@ -35,13 +36,14 @@ class PriorityNestedScrollConnectionTest { private var canStartPostFling = false private var canContinueScroll = false private var isStarted = false - private var lastScroll: Offset? = null - private var returnOnScroll = Offset.Zero - private var lastStop: Velocity? = null - private var returnOnStop = Velocity.Zero + private var lastScroll: Float? = null + private var returnOnScroll = 0f + private var lastStop: Float? = null + private var returnOnStop = 0f private val scrollConnection = PriorityNestedScrollConnection( + orientation = Orientation.Vertical, canStartPreScroll = { _, _ -> canStartPreScroll }, canStartPostScroll = { _, _ -> canStartPostScroll }, canStartPostFling = { canStartPostFling }, @@ -58,11 +60,6 @@ class PriorityNestedScrollConnectionTest { }, ) - private val offset1 = Offset(1f, 1f) - private val offset2 = Offset(2f, 2f) - private val velocity1 = Velocity(1f, 1f) - private val velocity2 = Velocity(2f, 2f) - @Test fun step1_priorityModeShouldStartOnlyOnPreScroll() = runTest { canStartPreScroll = true @@ -70,7 +67,7 @@ class PriorityNestedScrollConnectionTest { scrollConnection.onPostScroll( consumed = Offset.Zero, available = Offset.Zero, - source = NestedScrollSource.Drag, + source = UserInput, ) assertThat(isStarted).isEqualTo(false) @@ -80,7 +77,7 @@ class PriorityNestedScrollConnectionTest { scrollConnection.onPostFling(consumed = Velocity.Zero, available = Velocity.Zero) assertThat(isStarted).isEqualTo(false) - scrollConnection.onPreScroll(available = Offset.Zero, source = NestedScrollSource.Drag) + scrollConnection.onPreScroll(available = Offset.Zero, source = UserInput) assertThat(isStarted).isEqualTo(true) } @@ -89,7 +86,7 @@ class PriorityNestedScrollConnectionTest { scrollConnection.onPostScroll( consumed = Offset.Zero, available = Offset.Zero, - source = NestedScrollSource.Drag, + source = UserInput, ) } @@ -97,7 +94,7 @@ class PriorityNestedScrollConnectionTest { fun step1_priorityModeShouldStartOnlyOnPostScroll() = runTest { canStartPostScroll = true - scrollConnection.onPreScroll(available = Offset.Zero, source = NestedScrollSource.Drag) + scrollConnection.onPreScroll(available = Offset.Zero, source = UserInput) assertThat(isStarted).isEqualTo(false) scrollConnection.onPreFling(available = Velocity.Zero) @@ -115,7 +112,7 @@ class PriorityNestedScrollConnectionTest { scrollConnection.onPostScroll( consumed = Offset.Zero, available = Offset.Zero, - source = NestedScrollSource.Drag, + source = UserInput, ) assertThat(isStarted).isEqualTo(false) @@ -128,12 +125,12 @@ class PriorityNestedScrollConnectionTest { canStartPostScroll = true scrollConnection.onPostScroll( - consumed = offset1, - available = offset2, - source = NestedScrollSource.Drag, + consumed = Offset(1f, 1f), + available = Offset(2f, 2f), + source = UserInput, ) - assertThat(lastScroll).isEqualTo(offset2) + assertThat(lastScroll).isEqualTo(2f) } @Test @@ -141,13 +138,13 @@ class PriorityNestedScrollConnectionTest { startPriorityModePostScroll() canContinueScroll = true - scrollConnection.onPreScroll(available = offset1, source = NestedScrollSource.Drag) - assertThat(lastScroll).isEqualTo(offset1) + scrollConnection.onPreScroll(available = Offset(1f, 1f), source = UserInput) + assertThat(lastScroll).isEqualTo(1f) canContinueScroll = false - scrollConnection.onPreScroll(available = offset2, source = NestedScrollSource.Drag) - assertThat(lastScroll).isNotEqualTo(offset2) - assertThat(lastScroll).isEqualTo(offset1) + scrollConnection.onPreScroll(available = Offset(2f, 2f), source = UserInput) + assertThat(lastScroll).isNotEqualTo(2f) + assertThat(lastScroll).isEqualTo(1f) } @Test @@ -155,7 +152,7 @@ class PriorityNestedScrollConnectionTest { startPriorityModePostScroll() canContinueScroll = false - scrollConnection.onPreScroll(available = Offset.Zero, source = NestedScrollSource.Drag) + scrollConnection.onPreScroll(available = Offset.Zero, source = UserInput) assertThat(lastStop).isNotNull() } @@ -184,22 +181,22 @@ class PriorityNestedScrollConnectionTest { fun receive_onPostFling() = runTest { canStartPostFling = true - scrollConnection.onPostFling(consumed = velocity1, available = velocity2) + scrollConnection.onPostFling(consumed = Velocity(1f, 1f), available = Velocity(2f, 2f)) - assertThat(lastStop).isEqualTo(velocity2) + assertThat(lastStop).isEqualTo(2f) } @Test fun step1_priorityModeShouldStartOnlyOnPostFling() = runTest { canStartPostFling = true - scrollConnection.onPreScroll(available = Offset.Zero, source = NestedScrollSource.Drag) + scrollConnection.onPreScroll(available = Offset.Zero, source = UserInput) assertThat(isStarted).isEqualTo(false) scrollConnection.onPostScroll( consumed = Offset.Zero, available = Offset.Zero, - source = NestedScrollSource.Drag, + source = UserInput, ) assertThat(isStarted).isEqualTo(false) diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java index 94d3b2ccc9e5..176824fd4c5d 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java @@ -61,6 +61,7 @@ import com.android.systemui.classifier.FalsingA11yDelegate; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.res.R; import com.android.systemui.statusbar.policy.UserSwitcherController; +import com.android.systemui.statusbar.policy.UserSwitcherController.UserSwitchCallback; import com.android.systemui.user.data.source.UserRecord; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.settings.GlobalSettings; @@ -70,6 +71,8 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -96,6 +99,9 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { private UserSwitcherController mUserSwitcherController; @Mock private FalsingA11yDelegate mFalsingA11yDelegate; + @Captor + private ArgumentCaptor<UserSwitchCallback> mUserSwitchCallbackCaptor = + ArgumentCaptor.forClass(UserSwitchCallback.class); private KeyguardSecurityContainer mKeyguardSecurityContainer; private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); @@ -360,6 +366,18 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { } @Test + public void goingOutOfUserSwitcherRemovesCallback() { + // WHEN UserSwitcherViewMode is initialized + setupUserSwitcher(); + verify(mUserSwitcherController).addUserSwitchCallback(mUserSwitchCallbackCaptor.capture()); + + // Back to default mode, as SIM PIN would be + initMode(MODE_DEFAULT); + verify(mUserSwitcherController).removeUserSwitchCallback( + mUserSwitchCallbackCaptor.getValue()); + } + + @Test public void testOnDensityOrFontScaleChanged() { setupUserSwitcher(); View oldUserSwitcher = mKeyguardSecurityContainer.findViewById( diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationFrameSizePrefsTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/WindowMagnificationFrameSizePrefsTest.java index 944066fa4954..944066fa4954 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationFrameSizePrefsTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/WindowMagnificationFrameSizePrefsTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationFrameSpecTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/WindowMagnificationFrameSpecTest.kt index 791a26ed761d..6f43c2068fc4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationFrameSpecTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/WindowMagnificationFrameSpecTest.kt @@ -16,9 +16,9 @@ package com.android.systemui.accessibility -import android.testing.AndroidTestingRunner import android.util.Size import androidx.test.filters.SmallTest +import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.systemui.SysuiTestCase import com.android.systemui.accessibility.WindowMagnificationSettings.MagnificationSize import com.google.common.truth.Truth.assertThat @@ -26,7 +26,7 @@ import org.junit.Test import org.junit.runner.RunWith @SmallTest -@RunWith(AndroidTestingRunner::class) +@RunWith(AndroidJUnit4::class) class WindowMagnificationFrameSpecTest : SysuiTestCase() { @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java index 24f3a29e64ee..24f3a29e64ee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java index 157cccc3d62f..157cccc3d62f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/fontscaling index 0bd00fb0a0e9..0bd00fb0a0e9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogDelegateTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/fontscaling diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java index 662815ee7cbe..662815ee7cbe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt index a8c3af9488f0..a8c3af9488f0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt index 72163e4d7710..72163e4d7710 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/battery/BatteryMeterViewTest.kt index 2aa33a176ac9..2aa33a176ac9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/battery/BatteryMeterViewTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt index 7889b3cd6cc3..7889b3cd6cc3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java index 65825b2444af..2dcbdc80f695 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -17,6 +17,7 @@ package com.android.systemui.biometrics; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; +import static android.view.Display.INVALID_DISPLAY; import static com.google.common.truth.Truth.assertThat; @@ -68,10 +69,12 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; import android.os.Handler; import android.os.RemoteException; +import android.os.UserHandle; import android.os.UserManager; import android.testing.TestableContext; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; +import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; import android.view.WindowManager; @@ -210,6 +213,7 @@ public class AuthControllerTest extends SysuiTestCase { .thenReturn(true); when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) .thenReturn(true); + when(mUserManager.isVisibleBackgroundUsersSupported()).thenReturn(false); when(mDialog1.getOpPackageName()).thenReturn("Dialog1"); when(mDialog2.getOpPackageName()).thenReturn("Dialog2"); @@ -462,7 +466,7 @@ public class AuthControllerTest extends SysuiTestCase { @Test public void testShowInvoked_whenSystemRequested() { showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */); - verify(mDialog1).show(any()); + verify(mDialog1).show(mWindowManager); } @Test @@ -679,7 +683,7 @@ public class AuthControllerTest extends SysuiTestCase { // 2) Client cancels authentication showDialog(new int[0] /* sensorIds */, true /* credentialAllowed */); - verify(mDialog1).show(any()); + verify(mDialog1).show(mWindowManager); final byte[] credentialAttestation = generateRandomHAT(); @@ -695,7 +699,7 @@ public class AuthControllerTest extends SysuiTestCase { @Test public void testShowNewDialog_beforeOldDialogDismissed_SkipsAnimations() { showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */); - verify(mDialog1).show(any()); + verify(mDialog1).show(mWindowManager); showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */); @@ -703,7 +707,7 @@ public class AuthControllerTest extends SysuiTestCase { verify(mDialog1).dismissWithoutCallback(eq(false) /* animate */); // Second dialog should be shown without animation - verify(mDialog2).show(any()); + verify(mDialog2).show(mWindowManager); } @Test @@ -990,13 +994,97 @@ public class AuthControllerTest extends SysuiTestCase { verify(mDialog1, never()).show(any()); } + @Test + public void testShowDialog_visibleBackgroundUser() { + int backgroundUserId = 1001; + int backgroundDisplayId = 1001; + when(mUserManager.isVisibleBackgroundUsersSupported()).thenReturn(true); + WindowManager wm = mockBackgroundUser(backgroundUserId, backgroundDisplayId, + true /* isVisible */, true /* hasUserManager */, true /* hasDisplay */); + + showDialog(new int[]{1} /* sensorIds */, backgroundUserId /* userId */, + false /* credentialAllowed */); + + verify(mDialog1).show(wm); + } + + @Test + public void testShowDialog_invisibleBackgroundUser_defaultWM() { + int backgroundUserId = 1001; + when(mUserManager.isVisibleBackgroundUsersSupported()).thenReturn(true); + mockBackgroundUser(backgroundUserId, INVALID_DISPLAY, + false /* isVisible */, true /* hasUserManager */, true /* hasDisplay */); + + showDialog(new int[]{1} /* sensorIds */, backgroundUserId /* userId */, + false /* credentialAllowed */); + + verify(mDialog1).show(mWindowManager); + } + + @Test + public void testShowDialog_visibleBackgroundUser_noUserManager_dismissError() + throws RemoteException { + int backgroundUserId = 1001; + int backgroundDisplayId = 1001; + when(mUserManager.isVisibleBackgroundUsersSupported()).thenReturn(true); + mockBackgroundUser(backgroundUserId, backgroundDisplayId, + true /* isVisible */, false /* hasUserManager */, true /* hasDisplay */); + + showDialog(new int[]{1} /* sensorIds */, backgroundUserId /* userId */, + false /* credentialAllowed */); + + verify(mDialog1, never()).show(any()); + verify(mReceiver).onDialogDismissed( + eq(BiometricPrompt.DISMISSED_REASON_ERROR_NO_WM), + eq(null) /* credentialAttestation */); + } + + @Test + public void testShowDialog_visibleBackgroundUser_invalidDisplayId_dismissError() + throws RemoteException { + int backgroundUserId = 1001; + when(mUserManager.isVisibleBackgroundUsersSupported()).thenReturn(true); + mockBackgroundUser(backgroundUserId, INVALID_DISPLAY, + true /* isVisible */, true /* hasUserManager */, false /* hasDisplay */); + + showDialog(new int[]{1} /* sensorIds */, backgroundUserId /* userId */, + false /* credentialAllowed */); + + verify(mDialog1, never()).show(any()); + verify(mReceiver).onDialogDismissed( + eq(BiometricPrompt.DISMISSED_REASON_ERROR_NO_WM), + eq(null) /* credentialAttestation */); + } + + @Test + public void testShowDialog_visibleBackgroundUser_invalidDisplay_dismissError() + throws RemoteException { + int backgroundUserId = 1001; + int backgroundDisplayId = 1001; + when(mUserManager.isVisibleBackgroundUsersSupported()).thenReturn(true); + mockBackgroundUser(backgroundUserId, backgroundDisplayId, + true /* isVisible */, true /* hasUserManager */, false /* hasDisplay */); + + showDialog(new int[]{1} /* sensorIds */, backgroundUserId /* userId */, + false /* credentialAllowed */); + + verify(mDialog1, never()).show(any()); + verify(mReceiver).onDialogDismissed( + eq(BiometricPrompt.DISMISSED_REASON_ERROR_NO_WM), + eq(null) /* credentialAttestation */); + } + private void showDialog(int[] sensorIds, boolean credentialAllowed) { + showDialog(sensorIds, 0 /* userId */, credentialAllowed); + } + + private void showDialog(int[] sensorIds, int userId, boolean credentialAllowed) { mAuthController.showAuthenticationDialog(createTestPromptInfo(), mReceiver /* receiver */, sensorIds, credentialAllowed, true /* requireConfirmation */, - 0 /* userId */, + userId /* userId */, 0 /* operationId */, "testPackage", REQUEST_ID); @@ -1059,6 +1147,40 @@ public class AuthControllerTest extends SysuiTestCase { assertTrue(mAuthController.isFaceAuthEnrolled(userId)); } + /** + * Create mocks related to visible background users. + * + * @param userId the user id of the background user to mock + * @param displayId display id of the background user + * @param isVisible whether the background user is a visible background user or not + * @param hasUserManager simulate whether the background user's context will return a mock + * UserManager instance or null + * @param hasDisplay simulate whether the background user's context will return a mock Display + * instance or null + * @return mock WindowManager instance associated with the background user's display context + */ + private WindowManager mockBackgroundUser(int userId, int displayId, boolean isVisible, + boolean hasUserManager, boolean hasDisplay) { + Context mockUserContext = mock(Context.class); + Context mockDisplayContext = mock(Context.class); + UserManager mockUserManager = mock(UserManager.class); + Display mockDisplay = mock(Display.class); + WindowManager mockDisplayWM = mock(WindowManager.class); + doReturn(mockUserContext).when(mContextSpy).createContextAsUser(eq(UserHandle.of(userId)), + anyInt()); + if (hasUserManager) { + when(mockUserContext.getSystemService(UserManager.class)).thenReturn(mockUserManager); + } + when(mockUserManager.isUserVisible()).thenReturn(isVisible); + when(mockUserManager.getMainDisplayIdAssignedToUser()).thenReturn(displayId); + if (hasDisplay) { + when(mDisplayManager.getDisplay(displayId)).thenReturn(mockDisplay); + } + doReturn(mockDisplayContext).when(mContextSpy).createDisplayContext(mockDisplay); + when(mockDisplayContext.getSystemService(WindowManager.class)).thenReturn(mockDisplayWM); + return mockDisplayWM; + } + private final class TestableAuthController extends AuthController { private int mBuildCount = 0; diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsViewTest.kt index 9fbe09619ff1..9fbe09619ff1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsViewTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/CredentialInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/CredentialInteractorImplTest.kt index 4856f156c4c7..4856f156c4c7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/CredentialInteractorImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/CredentialInteractorImplTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt index 30207bb310ba..30207bb310ba 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptCredentialInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/PromptCredentialInteractorTest.kt index 5a3637668cfe..5a3637668cfe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptCredentialInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/PromptCredentialInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt index dc499cd2fe8d..dc499cd2fe8d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractorImplTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequestTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/model index 08f139c6a3af..08f139c6a3af 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequestTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/model diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/shared/model/BiometricModalitiesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/shared/model/BiometricModalitiesTest.kt index 4d8fafc2111a..4d8fafc2111a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/shared/model/BiometricModalitiesTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/shared/model/BiometricModalitiesTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/CredentialViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/viewmodel/CredentialViewModelTest.kt index e4c5cd456f03..e4c5cd456f03 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/CredentialViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/viewmodel/CredentialViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt index 55fd3440ea07..55fd3440ea07 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable index 0d369a3ea80c..97f2e56e6eec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/composable @@ -67,7 +67,6 @@ import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.sceneDataSourceDelegator import com.android.systemui.scene.ui.composable.Scene import com.android.systemui.scene.ui.composable.SceneContainer -import com.android.systemui.settings.displayTracker import com.android.systemui.testKosmos import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.awaitCancellation @@ -127,7 +126,7 @@ class BouncerPredictiveBackTest : SysuiTestCase() { private val sceneContainerViewModel by lazy { kosmos.sceneContainerViewModelFactory - .create(view, kosmos.displayTracker.defaultDisplayId, {}) + .create(view) {} .apply { setTransitionState(transitionState) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineClassifierTest.java index 637771790b28..637771790b28 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineClassifierTest.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/ZigZagClassifierTest.java index 1fe726863f7f..1fe726863f7f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/ZigZagClassifierTest.java diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt index 3d30eccc4572..8ae9d2e8f7e8 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt @@ -25,8 +25,10 @@ import android.content.applicationContext import android.graphics.Bitmap import android.os.UserHandle import android.os.userManager +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_WIDGET_RESIZING import com.android.systemui.SysuiTestCase import com.android.systemui.common.data.repository.fakePackageChangeRepository import com.android.systemui.common.shared.model.PackageInstallSession @@ -156,6 +158,7 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { appWidgetId = communalWidgetItemEntry.widgetId, providerInfo = providerInfoA, rank = communalItemRankEntry.rank, + spanY = communalWidgetItemEntry.spanY, ) ) @@ -188,11 +191,13 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { appWidgetId = 1, providerInfo = providerInfoA, rank = 1, + spanY = 3, ), CommunalWidgetContentModel.Available( appWidgetId = 2, providerInfo = providerInfoB, rank = 2, + spanY = 3, ), ) } @@ -219,11 +224,13 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { appWidgetId = 1, providerInfo = providerInfoA, rank = 1, + spanY = 3, ), CommunalWidgetContentModel.Available( appWidgetId = 2, providerInfo = providerInfoB, rank = 2, + spanY = 3, ), ) @@ -238,11 +245,13 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { // Verify that provider info updated providerInfo = providerInfoC, rank = 1, + spanY = 3, ), CommunalWidgetContentModel.Available( appWidgetId = 2, providerInfo = providerInfoB, rank = 2, + spanY = 3, ), ) } @@ -681,6 +690,7 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { appWidgetId = 1, providerInfo = providerInfoA, rank = 1, + spanY = 3, ), CommunalWidgetContentModel.Pending( appWidgetId = 2, @@ -688,6 +698,7 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { componentName = ComponentName("pk_2", "cls_2"), icon = fakeIcon, user = mainUser, + spanY = 3, ), ) } @@ -723,6 +734,7 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { componentName = ComponentName("pk_1", "cls_1"), icon = fakeIcon, user = mainUser, + spanY = 3, ) ) @@ -740,20 +752,23 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { appWidgetId = 1, providerInfo = providerInfoA, rank = 1, + spanY = 3, ) ) } @Test + @EnableFlags(FLAG_COMMUNAL_WIDGET_RESIZING) fun updateWidgetSpanY_updatesWidgetInDaoAndRequestsBackup() = testScope.runTest { val widgetId = 1 val newSpanY = 6 + val widgetIdToRankMap = emptyMap<Int, Int>() - underTest.updateWidgetSpanY(widgetId, newSpanY) + underTest.resizeWidget(widgetId, newSpanY, widgetIdToRankMap) runCurrent() - verify(communalWidgetDao).updateWidgetSpanY(widgetId, newSpanY) + verify(communalWidgetDao).resizeWidget(widgetId, newSpanY, widgetIdToRankMap) verify(backupManager).dataChanged() } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt index b96e40f43318..611a61a6282c 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt @@ -24,6 +24,7 @@ import android.content.pm.UserInfo import android.os.UserHandle import android.os.UserManager import android.os.userManager +import android.platform.test.annotations.EnableFlags import android.provider.Settings import android.provider.Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED import android.widget.RemoteViews @@ -31,6 +32,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.Flags.FLAG_COMMUNAL_HUB +import com.android.systemui.Flags.FLAG_COMMUNAL_WIDGET_RESIZING import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.broadcastDispatcher import com.android.systemui.communal.data.model.CommunalSmartspaceTimer @@ -1078,6 +1080,108 @@ class CommunalInteractorTest : SysuiTestCase() { assertThat(managedProfileController.isWorkModeEnabled()).isTrue() } + @Test + @EnableFlags(FLAG_COMMUNAL_WIDGET_RESIZING) + fun resizeWidget_withoutUpdatingOrder() = + testScope.runTest { + val userInfos = listOf(MAIN_USER_INFO) + userRepository.setUserInfos(userInfos) + userTracker.set(userInfos = userInfos, selectedUserIndex = 0) + runCurrent() + + // Widgets available. + widgetRepository.addWidget( + appWidgetId = 1, + userId = MAIN_USER_INFO.id, + rank = 0, + spanY = CommunalContentSize.HALF.span, + ) + widgetRepository.addWidget( + appWidgetId = 2, + userId = MAIN_USER_INFO.id, + rank = 1, + spanY = CommunalContentSize.HALF.span, + ) + widgetRepository.addWidget( + appWidgetId = 3, + userId = MAIN_USER_INFO.id, + rank = 2, + spanY = CommunalContentSize.HALF.span, + ) + + val widgetContent by collectLastValue(underTest.widgetContent) + + assertThat(widgetContent?.map { it.appWidgetId to it.size }) + .containsExactly( + 1 to CommunalContentSize.HALF, + 2 to CommunalContentSize.HALF, + 3 to CommunalContentSize.HALF, + ) + .inOrder() + + underTest.resizeWidget(2, CommunalContentSize.FULL.span, emptyMap()) + + // Widget 2 should have been resized to FULL + assertThat(widgetContent?.map { it.appWidgetId to it.size }) + .containsExactly( + 1 to CommunalContentSize.HALF, + 2 to CommunalContentSize.FULL, + 3 to CommunalContentSize.HALF, + ) + .inOrder() + } + + @Test + @EnableFlags(FLAG_COMMUNAL_WIDGET_RESIZING) + fun resizeWidget_andUpdateOrder() = + testScope.runTest { + val userInfos = listOf(MAIN_USER_INFO) + userRepository.setUserInfos(userInfos) + userTracker.set(userInfos = userInfos, selectedUserIndex = 0) + runCurrent() + + // Widgets available. + widgetRepository.addWidget( + appWidgetId = 1, + userId = MAIN_USER_INFO.id, + rank = 0, + spanY = CommunalContentSize.HALF.span, + ) + widgetRepository.addWidget( + appWidgetId = 2, + userId = MAIN_USER_INFO.id, + rank = 1, + spanY = CommunalContentSize.HALF.span, + ) + widgetRepository.addWidget( + appWidgetId = 3, + userId = MAIN_USER_INFO.id, + rank = 2, + spanY = CommunalContentSize.HALF.span, + ) + + val widgetContent by collectLastValue(underTest.widgetContent) + + assertThat(widgetContent?.map { it.appWidgetId to it.size }) + .containsExactly( + 1 to CommunalContentSize.HALF, + 2 to CommunalContentSize.HALF, + 3 to CommunalContentSize.HALF, + ) + .inOrder() + + underTest.resizeWidget(2, CommunalContentSize.FULL.span, mapOf(2 to 0, 1 to 1)) + + // Widget 2 should have been resized to FULL and moved to the front of the list + assertThat(widgetContent?.map { it.appWidgetId to it.size }) + .containsExactly( + 2 to CommunalContentSize.FULL, + 1 to CommunalContentSize.HALF, + 3 to CommunalContentSize.HALF, + ) + .inOrder() + } + private fun setKeyguardFeaturesDisabled(user: UserInfo, disabledFlags: Int) { whenever(kosmos.devicePolicyManager.getKeyguardDisabledFeatures(nullable(), eq(user.id))) .thenReturn(disabledFlags) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt index 58b59ffd8894..755c4ebf5016 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalUserActionsViewModelTest.kt @@ -85,7 +85,8 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() { assertThat(actions).isNotEmpty() assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home)) assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer)) - assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade)) + assertThat(actions?.get(Swipe.Down)) + .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true)) setUpState( isShadeTouchable = false, @@ -102,7 +103,8 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() { assertThat(actions).isNotEmpty() assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home)) assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone)) - assertThat(actions?.get(Swipe.Down)).isEqualTo(UserActionResult(Scenes.Shade)) + assertThat(actions?.get(Swipe.Down)) + .isEqualTo(UserActionResult(Scenes.Shade, isIrreversible = true)) } @Test @@ -120,7 +122,7 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() { assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home)) assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer)) assertThat(actions?.get(Swipe.Down)) - .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade)) + .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true)) setUpState( isShadeTouchable = false, @@ -138,7 +140,7 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() { assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home)) assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone)) assertThat(actions?.get(Swipe.Down)) - .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade)) + .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true)) } @Test @@ -156,7 +158,9 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() { assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home)) assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Bouncer)) assertThat(actions?.get(Swipe.Down)) - .isEqualTo(UserActionResult(Overlays.NotificationsShade)) + .isEqualTo( + UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true) + ) setUpState( isShadeTouchable = false, @@ -170,7 +174,9 @@ class CommunalUserActionsViewModelTest : SysuiTestCase() { assertThat(actions?.get(Swipe.End)).isEqualTo(UserActionResult(SceneFamilies.Home)) assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Gone)) assertThat(actions?.get(Swipe.Down)) - .isEqualTo(UserActionResult(Overlays.NotificationsShade)) + .isEqualTo( + UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true) + ) } private fun TestScope.setUpState( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/ResizeableItemFrameViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/ResizeableItemFrameViewModelTest.kt new file mode 100644 index 000000000000..f0d88ab41ad4 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/ResizeableItemFrameViewModelTest.kt @@ -0,0 +1,340 @@ +/* + * 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.communal.ui.viewmodel + +import androidx.compose.foundation.gestures.DraggableAnchors +import androidx.compose.runtime.snapshots.Snapshot +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.kosmos.testScope +import com.android.systemui.lifecycle.activateIn +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlin.time.Duration +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(AndroidJUnit4::class) +class ResizeableItemFrameViewModelTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val underTest = kosmos.resizeableItemFrameViewModel + + /** Total viewport height of the entire grid */ + private val viewportHeightPx = 100 + /** Total amount of vertical padding around the viewport */ + private val verticalContentPaddingPx = 20f + + private val singleSpanGrid = + GridLayout( + verticalItemSpacingPx = 10f, + verticalContentPaddingPx = verticalContentPaddingPx, + viewportHeightPx = viewportHeightPx, + maxItemSpan = 1, + minItemSpan = 1, + currentSpan = 1, + currentRow = 0, + ) + + @Before + fun setUp() { + underTest.activateIn(testScope) + } + + @Test + fun testDefaultState() { + val topState = underTest.topDragState + assertThat(topState.currentValue).isEqualTo(0) + assertThat(topState.offset).isEqualTo(0f) + assertThat(topState.anchors.toList()).containsExactly(0 to 0f) + + val bottomState = underTest.bottomDragState + assertThat(bottomState.currentValue).isEqualTo(0) + assertThat(bottomState.offset).isEqualTo(0f) + assertThat(bottomState.anchors.toList()).containsExactly(0 to 0f) + } + + @Test + fun testSingleSpanGrid() = + testScope.runTest(timeout = Duration.INFINITE) { + updateGridLayout(singleSpanGrid) + + val topState = underTest.topDragState + assertThat(topState.currentValue).isEqualTo(0) + assertThat(topState.anchors.toList()).containsExactly(0 to 0f) + + val bottomState = underTest.bottomDragState + assertThat(bottomState.currentValue).isEqualTo(0) + assertThat(bottomState.anchors.toList()).containsExactly(0 to 0f) + } + + /** + * Verifies element in first row which is already at the minimum size can only be expanded + * downwards. + */ + @Test + fun testTwoSpanGrid_elementInFirstRow_sizeSingleSpan() = + testScope.runTest { + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 2)) + + val topState = underTest.topDragState + assertThat(topState.currentValue).isEqualTo(0) + assertThat(topState.anchors.toList()).containsExactly(0 to 0f) + + val bottomState = underTest.bottomDragState + assertThat(bottomState.currentValue).isEqualTo(0) + assertThat(bottomState.anchors.toList()).containsExactly(0 to 0f, 1 to 45f) + } + + /** + * Verifies element in second row which is already at the minimum size can only be expanded + * upwards. + */ + @Test + fun testTwoSpanGrid_elementInSecondRow_sizeSingleSpan() = + testScope.runTest { + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 2, currentRow = 1)) + + val topState = underTest.topDragState + assertThat(topState.currentValue).isEqualTo(0) + assertThat(topState.anchors.toList()).containsExactly(0 to 0f, -1 to -45f) + + val bottomState = underTest.bottomDragState + assertThat(bottomState.currentValue).isEqualTo(0) + assertThat(bottomState.anchors.toList()).containsExactly(0 to 0f) + } + + /** + * Verifies element in first row which is already at full size (2 span) can only be shrunk from + * the bottom. + */ + @Test + fun testTwoSpanGrid_elementInFirstRow_sizeTwoSpan() = + testScope.runTest { + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 2, currentSpan = 2)) + + val topState = underTest.topDragState + assertThat(topState.currentValue).isEqualTo(0) + assertThat(topState.anchors.toList()).containsExactly(0 to 0f) + + val bottomState = underTest.bottomDragState + assertThat(bottomState.currentValue).isEqualTo(0) + assertThat(bottomState.anchors.toList()).containsExactly(0 to 0f, -1 to -45f) + } + + /** + * Verifies element in a middle row at minimum size can be expanded from either top or bottom. + */ + @Test + fun testThreeSpanGrid_elementInMiddleRow_sizeOneSpan() = + testScope.runTest { + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 3, currentRow = 1)) + + val topState = underTest.topDragState + assertThat(topState.currentValue).isEqualTo(0) + assertThat(topState.anchors.toList()).containsExactly(0 to 0f, -1 to -30f) + + val bottomState = underTest.bottomDragState + assertThat(bottomState.currentValue).isEqualTo(0) + assertThat(bottomState.anchors.toList()).containsExactly(0 to 0f, 1 to 30f) + } + + @Test + fun testThreeSpanGrid_elementInTopRow_sizeOneSpan() = + testScope.runTest { + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 3)) + + val topState = underTest.topDragState + assertThat(topState.currentValue).isEqualTo(0) + assertThat(topState.anchors.toList()).containsExactly(0 to 0f) + + val bottomState = underTest.bottomDragState + assertThat(bottomState.currentValue).isEqualTo(0) + assertThat(bottomState.anchors.toList()).containsExactly(0 to 0f, 1 to 30f, 2 to 60f) + } + + @Test + fun testSixSpanGrid_minSpanThree_itemInThirdRow_sizeThreeSpans() = + testScope.runTest { + updateGridLayout( + singleSpanGrid.copy( + maxItemSpan = 6, + currentRow = 3, + currentSpan = 3, + minItemSpan = 3, + ) + ) + + val topState = underTest.topDragState + assertThat(topState.currentValue).isEqualTo(0) + assertThat(topState.anchors.toList()).containsExactly(0 to 0f, -3 to -45f) + + val bottomState = underTest.bottomDragState + assertThat(bottomState.currentValue).isEqualTo(0) + assertThat(bottomState.anchors.toList()).containsExactly(0 to 0f) + } + + @Test + fun testTwoSpanGrid_elementMovesFromFirstRowToSecondRow() = + testScope.runTest { + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 2)) + + val topState = underTest.topDragState + val bottomState = underTest.bottomDragState + + assertThat(topState.anchors.toList()).containsExactly(0 to 0f) + assertThat(bottomState.anchors.toList()).containsExactly(0 to 0f, 1 to 45f) + + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 2, currentRow = 1)) + + assertThat(topState.anchors.toList()).containsExactly(0 to 0f, -1 to -45f) + assertThat(bottomState.anchors.toList()).containsExactly(0 to 0f) + } + + @Test + fun testTwoSpanGrid_expandElementFromBottom() = runTestWithSnapshots { + val resizeInfo by collectLastValue(underTest.resizeInfo) + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 2)) + + assertThat(resizeInfo).isNull() + underTest.bottomDragState.anchoredDrag { dragTo(45f) } + assertThat(resizeInfo).isEqualTo(ResizeInfo(1, DragHandle.BOTTOM)) + } + + @Test + fun testThreeSpanGrid_expandMiddleElementUpwards() = runTestWithSnapshots { + val resizeInfo by collectLastValue(underTest.resizeInfo) + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 3, currentRow = 1)) + + assertThat(resizeInfo).isNull() + underTest.topDragState.anchoredDrag { dragTo(-30f) } + assertThat(resizeInfo).isEqualTo(ResizeInfo(1, DragHandle.TOP)) + } + + @Test + fun testThreeSpanGrid_expandTopElementDownBy2Spans() = runTestWithSnapshots { + val resizeInfo by collectLastValue(underTest.resizeInfo) + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 3)) + + assertThat(resizeInfo).isNull() + underTest.bottomDragState.anchoredDrag { dragTo(60f) } + assertThat(resizeInfo).isEqualTo(ResizeInfo(2, DragHandle.BOTTOM)) + } + + @Test + fun testTwoSpanGrid_shrinkElementFromBottom() = runTestWithSnapshots { + val resizeInfo by collectLastValue(underTest.resizeInfo) + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 2, currentSpan = 2)) + + assertThat(resizeInfo).isNull() + underTest.bottomDragState.anchoredDrag { dragTo(-45f) } + assertThat(resizeInfo).isEqualTo(ResizeInfo(-1, DragHandle.BOTTOM)) + } + + @Test + fun testRowInfoBecomesNull_revertsBackToDefault() = + testScope.runTest { + val gridLayout = singleSpanGrid.copy(maxItemSpan = 3, currentRow = 1) + updateGridLayout(gridLayout) + + val topState = underTest.topDragState + assertThat(topState.anchors.toList()).containsExactly(0 to 0f, -1 to -30f) + + val bottomState = underTest.bottomDragState + assertThat(bottomState.anchors.toList()).containsExactly(0 to 0f, 1 to 30f) + + updateGridLayout(gridLayout.copy(currentRow = null)) + assertThat(topState.anchors.toList()).containsExactly(0 to 0f) + assertThat(bottomState.anchors.toList()).containsExactly(0 to 0f) + } + + @Test(expected = IllegalArgumentException::class) + fun testIllegalState_maxSpanSmallerThanMinSpan() = + testScope.runTest { + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 2, minItemSpan = 3)) + } + + @Test(expected = IllegalArgumentException::class) + fun testIllegalState_minSpanOfZero() = + testScope.runTest { + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 2, minItemSpan = 0)) + } + + @Test(expected = IllegalArgumentException::class) + fun testIllegalState_maxSpanOfZero() = + testScope.runTest { + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 0, minItemSpan = 0)) + } + + @Test(expected = IllegalArgumentException::class) + fun testIllegalState_currentRowNotMultipleOfMinSpan() = + testScope.runTest { + updateGridLayout(singleSpanGrid.copy(maxItemSpan = 6, minItemSpan = 3, currentSpan = 2)) + } + + private fun TestScope.updateGridLayout(gridLayout: GridLayout) { + underTest.setGridLayoutInfo( + gridLayout.verticalItemSpacingPx, + gridLayout.verticalContentPaddingPx, + gridLayout.viewportHeightPx, + gridLayout.maxItemSpan, + gridLayout.minItemSpan, + gridLayout.currentRow, + gridLayout.currentSpan, + ) + runCurrent() + } + + private fun DraggableAnchors<Int>.toList() = buildList { + for (index in 0 until this@toList.size) { + add(anchorAt(index) to positionAt(index)) + } + } + + private fun runTestWithSnapshots(testBody: suspend TestScope.() -> Unit) { + val globalWriteObserverHandle = + Snapshot.registerGlobalWriteObserver { + // This is normally done by the compose runtime. + Snapshot.sendApplyNotifications() + } + + try { + testScope.runTest(testBody = testBody) + } finally { + globalWriteObserverHandle.dispose() + } + } + + private data class GridLayout( + val verticalItemSpacingPx: Float, + val verticalContentPaddingPx: Float, + val viewportHeightPx: Int, + val maxItemSpan: Int, + val minItemSpan: Int, + val currentRow: Int?, + val currentSpan: Int?, + ) +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt index 40b2a0864a8c..a0c56b4a27a6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt @@ -139,7 +139,7 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { TransitionStep( KeyguardState.OFF, KeyguardState.LOCKSCREEN, - transitionState = TransitionState.STARTED + transitionState = TransitionState.STARTED, ) ) @@ -181,7 +181,7 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { TransitionStep( KeyguardState.AOD, KeyguardState.LOCKSCREEN, - transitionState = TransitionState.STARTED + transitionState = TransitionState.STARTED, ) ) @@ -206,7 +206,7 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { TransitionStep( KeyguardState.DOZING, KeyguardState.LOCKSCREEN, - transitionState = TransitionState.STARTED + transitionState = TransitionState.STARTED, ) ) @@ -229,7 +229,7 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { TransitionStep( KeyguardState.DOZING, KeyguardState.LOCKSCREEN, - transitionState = TransitionState.STARTED + transitionState = TransitionState.STARTED, ) ) @@ -244,12 +244,14 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { fun faceAuthLockedOutStateIsUpdatedAfterUserSwitch() = testScope.runTest { underTest.start() + runCurrent() + fakeBiometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(true) // User switching has started fakeUserRepository.setSelectedUserInfo(primaryUser, SelectionStatus.SELECTION_COMPLETE) fakeUserRepository.setSelectedUserInfo( primaryUser, - SelectionStatus.SELECTION_IN_PROGRESS + SelectionStatus.SELECTION_IN_PROGRESS, ) runCurrent() @@ -258,7 +260,7 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { facePropertyRepository.setLockoutMode(secondaryUser.id, LockoutMode.NONE) fakeUserRepository.setSelectedUserInfo( secondaryUser, - SelectionStatus.SELECTION_COMPLETE + SelectionStatus.SELECTION_COMPLETE, ) runCurrent() @@ -316,7 +318,7 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { .isEqualTo( Pair( FaceAuthUiEvent.FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN, - false + false, ) ) } @@ -600,7 +602,7 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { faceAuthRepository.requestAuthenticate( FaceAuthUiEvent.FACE_AUTH_UPDATED_KEYGUARD_VISIBILITY_CHANGED, - true + true, ) facePropertyRepository.setCameraIno(CameraInfo("0", "1", null)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt index 6c6de61c638a..6c6de61c638a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt index a3314e8900ce..a3314e8900ce 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch index c2c94a88603a..c2c94a88603a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch diff --git a/packages/SystemUI/tests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt index 98e09474d5f2..98e09474d5f2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadStatsInteractorTest.kt diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt index d7fe263df581..dd8370231ef0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt @@ -71,7 +71,7 @@ class ContextualEduUiCoordinatorTest : SysuiTestCase() { @Mock private lateinit var accessibilityManagerWrapper: AccessibilityManagerWrapper @get:Rule val mockitoRule = MockitoJUnit.rule() private var toastContent = "" - private val timeoutMillis = 3500L + private val timeoutMillis = 5000L @Before fun setUp() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt index 4a80d7242e03..4a80d7242e03 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperCategoriesRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperCategoriesRepositoryTest.kt index 6e883c24b5d2..6e883c24b5d2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperCategoriesRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperCategoriesRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt index 57c8b444b922..57c8b444b922 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/domain/interactor/ShortcutHelperCategoriesInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperActivityStarterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui index f8e2f47f939a..f8e2f47f939a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/ShortcutHelperActivityStarterTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt index 1e9db6466de6..1e9db6466de6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryImplTest.kt index 5a597fe8e920..5a597fe8e920 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepositoryImplTest.kt 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 17e3006812ca..047d8c2b31a9 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 @@ -42,7 +42,8 @@ import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepositor import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository -import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepositorySpy +import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.util.KeyguardTransitionRepositorySpySubject.Companion.assertThat import com.android.systemui.kosmos.testScope @@ -57,7 +58,6 @@ import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mockito import org.mockito.Mockito.reset @ExperimentalCoroutinesApi @@ -66,7 +66,7 @@ import org.mockito.Mockito.reset class FromAlternateBouncerTransitionInteractorTest : SysuiTestCase() { private val kosmos = testKosmos().apply { - this.fakeKeyguardTransitionRepository = Mockito.spy(FakeKeyguardTransitionRepository()) + this.keyguardTransitionRepository = fakeKeyguardTransitionRepositorySpy } private val testScope = kosmos.testScope private lateinit var underTest: FromAlternateBouncerTransitionInteractor @@ -74,7 +74,7 @@ class FromAlternateBouncerTransitionInteractorTest : SysuiTestCase() { @Before fun setup() { - transitionRepository = kosmos.fakeKeyguardTransitionRepository + transitionRepository = kosmos.fakeKeyguardTransitionRepositorySpy underTest = kosmos.fromAlternateBouncerTransitionInteractor underTest.start() } @@ -86,7 +86,7 @@ class FromAlternateBouncerTransitionInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.OCCLUDED, to = KeyguardState.ALTERNATE_BOUNCER, - testScope + testScope, ) reset(transitionRepository) @@ -111,7 +111,7 @@ class FromAlternateBouncerTransitionInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.OCCLUDED, to = KeyguardState.ALTERNATE_BOUNCER, - testScope + testScope, ) reset(transitionRepository) @@ -129,7 +129,7 @@ class FromAlternateBouncerTransitionInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.OCCLUDED, to = KeyguardState.ALTERNATE_BOUNCER, - testScope + testScope, ) reset(transitionRepository) @@ -158,7 +158,7 @@ class FromAlternateBouncerTransitionInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.OCCLUDED, to = KeyguardState.ALTERNATE_BOUNCER, - testScope + testScope, ) reset(transitionRepository) @@ -168,7 +168,7 @@ class FromAlternateBouncerTransitionInteractorTest : SysuiTestCase() { assertThat(transitionRepository) .startedTransition( from = KeyguardState.ALTERNATE_BOUNCER, - to = KeyguardState.OCCLUDED + to = KeyguardState.OCCLUDED, ) } @@ -183,7 +183,7 @@ class FromAlternateBouncerTransitionInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.ALTERNATE_BOUNCER, - testScope + testScope, ) reset(transitionRepository) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt index 33f3cd4ac167..930096463354 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt @@ -42,8 +42,9 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository -import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepositorySpy import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository +import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.shared.model.BiometricUnlockMode import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState.GONE @@ -69,7 +70,6 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.reset -import org.mockito.Mockito.spy @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @@ -77,7 +77,7 @@ import org.mockito.Mockito.spy class FromAodTransitionInteractorTest : SysuiTestCase() { private val kosmos = testKosmos().apply { - this.fakeKeyguardTransitionRepository = spy(FakeKeyguardTransitionRepository()) + this.keyguardTransitionRepository = fakeKeyguardTransitionRepositorySpy } private val testScope = kosmos.testScope @@ -89,7 +89,7 @@ class FromAodTransitionInteractorTest : SysuiTestCase() { @Before fun setup() { powerInteractor = kosmos.powerInteractor - transitionRepository = kosmos.fakeKeyguardTransitionRepository + transitionRepository = kosmos.fakeKeyguardTransitionRepositorySpy underTest = kosmos.fromAodTransitionInteractor underTest.start() @@ -101,7 +101,7 @@ class FromAodTransitionInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.AOD, - testScope + testScope, ) kosmos.fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockMode.NONE) reset(transitionRepository) @@ -117,10 +117,7 @@ class FromAodTransitionInteractorTest : SysuiTestCase() { // Under default conditions, we should transition to LOCKSCREEN when waking up. assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.AOD, - to = KeyguardState.LOCKSCREEN, - ) + .startedTransition(from = KeyguardState.AOD, to = KeyguardState.LOCKSCREEN) } @Test @@ -133,10 +130,7 @@ class FromAodTransitionInteractorTest : SysuiTestCase() { // Waking with a SHOW_WHEN_LOCKED activity on top should transition to OCCLUDED. assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.AOD, - to = KeyguardState.OCCLUDED, - ) + .startedTransition(from = KeyguardState.AOD, to = KeyguardState.OCCLUDED) } @Test @@ -363,13 +357,13 @@ class FromAodTransitionInteractorTest : SysuiTestCase() { from = KeyguardState.GONE, to = KeyguardState.AOD, transitionState = TransitionState.STARTED, - value = 0f + value = 0f, ), TransitionStep( from = KeyguardState.GONE, to = KeyguardState.AOD, transitionState = TransitionState.RUNNING, - value = 0.1f + value = 0.1f, ), ), testScope = testScope, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt index ff0a4a16fe2a..3b6e5d09a37c 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt @@ -36,8 +36,9 @@ import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository -import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepositorySpy import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository +import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.shared.model.BiometricUnlockMode import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState.GONE @@ -79,7 +80,7 @@ import platform.test.runner.parameterized.Parameters class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiTestCase() { private val kosmos = testKosmos().apply { - this.fakeKeyguardTransitionRepository = spy(FakeKeyguardTransitionRepository()) + this.keyguardTransitionRepository = fakeKeyguardTransitionRepositorySpy this.fakeCommunalSceneRepository = spy(FakeCommunalSceneRepository(applicationScope = applicationCoroutineScope)) } @@ -105,7 +106,7 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT @Before fun setup() { powerInteractor = kosmos.powerInteractor - transitionRepository = kosmos.fakeKeyguardTransitionRepository + transitionRepository = kosmos.fakeKeyguardTransitionRepositorySpy underTest = kosmos.fromDozingTransitionInteractor underTest.start() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt index fa304c99ecc9..9ca3ce6929b0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt @@ -32,7 +32,9 @@ import com.android.systemui.flags.andSceneContainer import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepositorySpy import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository +import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.shared.model.BiometricUnlockMode import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.util.KeyguardTransitionRepositorySpySubject.Companion.assertThat @@ -53,7 +55,6 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.reset -import org.mockito.Mockito.spy import org.mockito.kotlin.whenever import platform.test.runner.parameterized.ParameterizedAndroidJunit4 import platform.test.runner.parameterized.Parameters @@ -77,14 +78,21 @@ class FromDreamingTransitionInteractorTest(flags: FlagsParameterization?) : Sysu private val kosmos = testKosmos().apply { - this.fakeKeyguardTransitionRepository = spy(FakeKeyguardTransitionRepository()) + this.fakeKeyguardTransitionRepository = + FakeKeyguardTransitionRepository( + // This test sends transition steps manually in the test cases. + sendTransitionStepsOnStartTransition = false, + testScope = testScope, + ) + + this.keyguardTransitionRepository = fakeKeyguardTransitionRepositorySpy } private val testScope = kosmos.testScope private val underTest by lazy { kosmos.fromDreamingTransitionInteractor } private val powerInteractor = kosmos.powerInteractor - private val transitionRepository = kosmos.fakeKeyguardTransitionRepository + private val transitionRepository = kosmos.fakeKeyguardTransitionRepositorySpy @Before fun setup() { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorTest.kt index af76b088787e..57b12990fb97 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorTest.kt @@ -23,10 +23,10 @@ import androidx.test.filters.SmallTest import com.android.internal.widget.LockPatternUtils import com.android.systemui.Flags import com.android.systemui.SysuiTestCase -import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository -import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepositorySpy +import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.shared.model.AuthenticationFlags import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionState @@ -41,18 +41,17 @@ import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.reset -import org.mockito.Mockito.spy @SmallTest @RunWith(AndroidJUnit4::class) class FromGoneTransitionInteractorTest : SysuiTestCase() { private val kosmos = testKosmos().apply { - fakeKeyguardTransitionRepository = spy(FakeKeyguardTransitionRepository()) + this.keyguardTransitionRepository = fakeKeyguardTransitionRepositorySpy } private val testScope = kosmos.testScope private val underTest = kosmos.fromGoneTransitionInteractor - private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepositorySpy @Before fun setUp() { @@ -101,9 +100,7 @@ class FromGoneTransitionInteractorTest : SysuiTestCase() { // We're in the middle of a GONE -> LOCKSCREEN transition. assertThat(keyguardTransitionRepository) - .startedTransition( - to = KeyguardState.LOCKSCREEN, - ) + .startedTransition(to = KeyguardState.LOCKSCREEN) } @Test @@ -121,15 +118,13 @@ class FromGoneTransitionInteractorTest : SysuiTestCase() { kosmos.fakeBiometricSettingsRepository.setAuthenticationFlags( AuthenticationFlags( 0, - LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN + LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN, ) ) runCurrent() // We're in the middle of a GONE -> LOCKSCREEN transition. assertThat(keyguardTransitionRepository) - .startedTransition( - to = KeyguardState.LOCKSCREEN, - ) + .startedTransition(to = KeyguardState.LOCKSCREEN) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt index 4d81317b7755..9c2e6313a1f0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractorTest.kt @@ -27,9 +27,11 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectValues import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository -import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepositorySpy import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository +import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.StatusBarState.KEYGUARD import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep @@ -42,10 +44,10 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.reset -import org.mockito.Mockito.spy @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @@ -53,15 +55,20 @@ import org.mockito.Mockito.spy class FromLockscreenTransitionInteractorTest : SysuiTestCase() { private val kosmos = testKosmos().apply { - fakeKeyguardTransitionRepository = spy(FakeKeyguardTransitionRepository()) + this.keyguardTransitionRepository = fakeKeyguardTransitionRepositorySpy } private val testScope = kosmos.testScope private val underTest = kosmos.fromLockscreenTransitionInteractor - private val transitionRepository = kosmos.fakeKeyguardTransitionRepository + private lateinit var transitionRepository: FakeKeyguardTransitionRepository private val shadeRepository = kosmos.fakeShadeRepository private val keyguardRepository = kosmos.fakeKeyguardRepository + @Before + fun setup() { + transitionRepository = kosmos.fakeKeyguardTransitionRepositorySpy + } + @Test fun testSurfaceBehindVisibility() = testScope.runTest { @@ -256,4 +263,43 @@ class FromLockscreenTransitionInteractorTest : SysuiTestCase() { assertThatRepository(transitionRepository) .startedTransition(from = KeyguardState.LOCKSCREEN, to = KeyguardState.DREAMING) } + + @Test + fun testTransitionsBackToOccluded_ifOccluded_andCanceledSwipe() = + testScope.runTest { + underTest.start() + keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD) + keyguardRepository.setKeyguardDismissible(false) + keyguardRepository.setKeyguardOccluded(false) + runCurrent() + + reset(transitionRepository) + + shadeRepository.setLegacyShadeTracking(true) + runCurrent() + shadeRepository.setLegacyShadeExpansion(0.5f) + runCurrent() + + assertThatRepository(transitionRepository) + .startedTransition( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.PRIMARY_BOUNCER, + ) + reset(transitionRepository) + + runCurrent() + + shadeRepository.setLegacyShadeExpansion(0.6f) + shadeRepository.setLegacyShadeExpansion(0.7f) + runCurrent() + + shadeRepository.setLegacyShadeExpansion(1f) + runCurrent() + + assertThatRepository(transitionRepository) + .startedTransition( + from = KeyguardState.PRIMARY_BOUNCER, + to = KeyguardState.LOCKSCREEN, + ) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractorTest.kt index 74243208cd98..4a90722274bd 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractorTest.kt @@ -42,9 +42,9 @@ import com.android.systemui.Flags.FLAG_COMMUNAL_SCENE_KTF_REFACTOR import com.android.systemui.SysuiTestCase import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository import com.android.systemui.communal.shared.model.CommunalScenes -import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository -import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepositorySpy import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository +import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.util.KeyguardTransitionRepositorySpySubject.Companion.assertThat import com.android.systemui.kosmos.testScope @@ -60,7 +60,6 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.reset -import org.mockito.Mockito.spy @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @@ -68,14 +67,14 @@ import org.mockito.Mockito.spy class FromOccludedTransitionInteractorTest : SysuiTestCase() { private val kosmos = testKosmos().apply { - this.fakeKeyguardTransitionRepository = spy(FakeKeyguardTransitionRepository()) + this.keyguardTransitionRepository = fakeKeyguardTransitionRepositorySpy } private val testScope = kosmos.testScope private val underTest = kosmos.fromOccludedTransitionInteractor private val powerInteractor = kosmos.powerInteractor - private val transitionRepository = kosmos.fakeKeyguardTransitionRepository + private val transitionRepository = kosmos.fakeKeyguardTransitionRepositorySpy @Before fun setup() { @@ -88,7 +87,7 @@ class FromOccludedTransitionInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.OCCLUDED, - testScope + testScope, ) reset(transitionRepository) } @@ -102,10 +101,7 @@ class FromOccludedTransitionInteractorTest : SysuiTestCase() { runCurrent() assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.OCCLUDED, - to = KeyguardState.LOCKSCREEN, - ) + .startedTransition(from = KeyguardState.OCCLUDED, to = KeyguardState.LOCKSCREEN) } @Test @@ -122,9 +118,6 @@ class FromOccludedTransitionInteractorTest : SysuiTestCase() { runCurrent() assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.OCCLUDED, - to = KeyguardState.GLANCEABLE_HUB, - ) + .startedTransition(from = KeyguardState.OCCLUDED, to = KeyguardState.GLANCEABLE_HUB) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt index 14f2d654a031..a7da23065dec 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt @@ -26,9 +26,9 @@ import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepositor import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.coroutines.collectValues -import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository -import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepositorySpy import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository +import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep @@ -44,20 +44,19 @@ import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.reset -import org.mockito.Mockito.spy @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class FromPrimaryBouncerTransitionInteractorTest : SysuiTestCase() { - val kosmos = + private val kosmos = testKosmos().apply { - this.fakeKeyguardTransitionRepository = spy(FakeKeyguardTransitionRepository()) + this.keyguardTransitionRepository = fakeKeyguardTransitionRepositorySpy } val underTest = kosmos.fromPrimaryBouncerTransitionInteractor val testScope = kosmos.testScope val selectedUserInteractor = kosmos.selectedUserInteractor - val transitionRepository = kosmos.fakeKeyguardTransitionRepository + val transitionRepository = kosmos.fakeKeyguardTransitionRepositorySpy val bouncerRepository = kosmos.fakeKeyguardBouncerRepository @Test @@ -67,12 +66,7 @@ class FromPrimaryBouncerTransitionInteractorTest : SysuiTestCase() { runCurrent() // Transition-specific surface visibility should be null ("don't care") initially. - assertEquals( - listOf( - null, - ), - values - ) + assertEquals(listOf(null), values) transitionRepository.sendTransitionStep( TransitionStep( @@ -86,9 +80,9 @@ class FromPrimaryBouncerTransitionInteractorTest : SysuiTestCase() { assertEquals( listOf( - null, // PRIMARY_BOUNCER -> LOCKSCREEN does not have any specific visibility. + null // PRIMARY_BOUNCER -> LOCKSCREEN does not have any specific visibility. ), - values + values, ) transitionRepository.sendTransitionStep( @@ -117,7 +111,7 @@ class FromPrimaryBouncerTransitionInteractorTest : SysuiTestCase() { null, false, // Surface is only made visible once the bouncer UI animates out. ), - values + values, ) transitionRepository.sendTransitionStep( @@ -137,7 +131,7 @@ class FromPrimaryBouncerTransitionInteractorTest : SysuiTestCase() { false, true, // Surface should eventually be visible. ), - values + values, ) } @@ -150,7 +144,7 @@ class FromPrimaryBouncerTransitionInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.PRIMARY_BOUNCER, - testScope + testScope, ) reset(transitionRepository) @@ -161,7 +155,7 @@ class FromPrimaryBouncerTransitionInteractorTest : SysuiTestCase() { assertThat(transitionRepository) .startedTransition( from = KeyguardState.PRIMARY_BOUNCER, - to = KeyguardState.LOCKSCREEN + to = KeyguardState.LOCKSCREEN, ) } @@ -177,7 +171,7 @@ class FromPrimaryBouncerTransitionInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.PRIMARY_BOUNCER, - testScope + testScope, ) reset(transitionRepository) @@ -188,7 +182,7 @@ class FromPrimaryBouncerTransitionInteractorTest : SysuiTestCase() { assertThat(transitionRepository) .startedTransition( from = KeyguardState.PRIMARY_BOUNCER, - to = KeyguardState.GLANCEABLE_HUB + to = KeyguardState.GLANCEABLE_HUB, ) } @@ -201,7 +195,7 @@ class FromPrimaryBouncerTransitionInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.PRIMARY_BOUNCER, - testScope + testScope, ) reset(transitionRepository) @@ -218,7 +212,7 @@ class FromPrimaryBouncerTransitionInteractorTest : SysuiTestCase() { assertThat(transitionRepository) .startedTransition( from = KeyguardState.PRIMARY_BOUNCER, - to = KeyguardState.OCCLUDED + to = KeyguardState.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 a617484d7d94..8f3d54961483 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 @@ -41,9 +41,9 @@ import com.android.systemui.flags.FakeFeatureFlags 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.fakeKeyguardRepository -import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepositorySpy +import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.shared.model.BiometricUnlockMode import com.android.systemui.keyguard.shared.model.DozeStateModel import com.android.systemui.keyguard.shared.model.DozeTransitionModel @@ -76,7 +76,6 @@ import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.reset -import org.mockito.Mockito.spy import org.mockito.MockitoAnnotations import platform.test.runner.parameterized.ParameterizedAndroidJunit4 import platform.test.runner.parameterized.Parameters @@ -91,7 +90,7 @@ import platform.test.runner.parameterized.Parameters class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTestCase() { private val kosmos = testKosmos().apply { - fakeKeyguardTransitionRepository = spy(FakeKeyguardTransitionRepository()) + this.keyguardTransitionRepository = fakeKeyguardTransitionRepositorySpy } private val testScope = kosmos.testScope @@ -99,7 +98,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest private val keyguardInteractor by lazy { kosmos.keyguardInteractor } private val bouncerRepository by lazy { kosmos.fakeKeyguardBouncerRepository } private val shadeTestUtil by lazy { kosmos.shadeTestUtil } - private val transitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository } + private val transitionRepository by lazy { kosmos.fakeKeyguardTransitionRepositorySpy } private lateinit var featureFlags: FakeFeatureFlags // Used to verify transition requests for test output diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt index 073ed61a949b..b6ec6a67b212 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt @@ -21,16 +21,23 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectValues import com.android.systemui.keyguard.data.fakeLightRevealScrimRepository +import com.android.systemui.keyguard.data.repository.DEFAULT_REVEAL_DURATION import com.android.systemui.keyguard.data.repository.DEFAULT_REVEAL_EFFECT import com.android.systemui.keyguard.data.repository.FakeLightRevealScrimRepository +import com.android.systemui.keyguard.data.repository.FakeLightRevealScrimRepository.RevealAnimatorRequest 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.TransitionStep import com.android.systemui.kosmos.testScope +import com.android.systemui.power.data.repository.fakePowerRepository +import com.android.systemui.power.domain.interactor.powerInteractor +import com.android.systemui.power.shared.model.WakeSleepReason +import com.android.systemui.power.shared.model.WakefulnessState import com.android.systemui.statusbar.LightRevealEffect import com.android.systemui.statusbar.LightRevealScrim 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 @@ -52,6 +59,8 @@ class LightRevealScrimInteractorTest : SysuiTestCase() { private val fakeKeyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + private val fakePowerRepository = kosmos.fakePowerRepository + private val underTest = kosmos.lightRevealScrimInteractor private val reveal1 = @@ -107,4 +116,50 @@ class LightRevealScrimInteractorTest : SysuiTestCase() { runCurrent() assertEquals(listOf(DEFAULT_REVEAL_EFFECT, reveal1, reveal2), values) } + + @Test + fun transitionToAod_folding_doesNotAnimateTheScrim() = + kosmos.testScope.runTest { + updateWakefulness(goToSleepReason = WakeSleepReason.FOLD) + runCurrent() + + // Transition to AOD + fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep(to = KeyguardState.AOD, transitionState = TransitionState.STARTED) + ) + runCurrent() + + assertThat(fakeLightRevealScrimRepository.revealAnimatorRequests.last()) + .isEqualTo(RevealAnimatorRequest(reveal = false, duration = 0)) + } + + @Test + fun transitionToAod_powerButton_animatesTheScrim() = + kosmos.testScope.runTest { + updateWakefulness(goToSleepReason = WakeSleepReason.POWER_BUTTON) + runCurrent() + + // Transition to AOD + fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep(to = KeyguardState.AOD, transitionState = TransitionState.STARTED) + ) + runCurrent() + + assertThat(fakeLightRevealScrimRepository.revealAnimatorRequests.last()) + .isEqualTo( + RevealAnimatorRequest( + reveal = false, + duration = DEFAULT_REVEAL_DURATION + ) + ) + } + + private fun updateWakefulness(goToSleepReason: WakeSleepReason) { + fakePowerRepository.updateWakefulness( + rawState = WakefulnessState.STARTING_TO_SLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = goToSleepReason, + powerButtonLaunchGestureTriggered = false + ) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt index 43c7ed6a769d..43c7ed6a769d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelTest.kt new file mode 100644 index 000000000000..22677b2f8e3e --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelTest.kt @@ -0,0 +1,90 @@ +/* + * 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.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.TransitionState.STARTED +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 DeviceEntryBackgroundViewModelTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val underTest: DeviceEntryBackgroundViewModel by lazy { + kosmos.deviceEntryBackgroundViewModel + } + + @Test + fun lockscreenToDozingTransitionChangesBackgroundViewAlphaToZero() = + testScope.runTest { + kosmos.fingerprintPropertyRepository.supportsUdfps() + val alpha by collectLastValue(underTest.alpha) + + kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( + listOf(dozingToLockscreen(0f, STARTED), dozingToLockscreen(0.1f)), + testScope, + ) + runCurrent() + assertThat(alpha).isEqualTo(1.0f) + + kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( + listOf(lockscreenToDozing(0f, STARTED)), + testScope, + ) + runCurrent() + + assertThat(alpha).isEqualTo(0.0f) + } + + private fun lockscreenToDozing(value: Float, state: TransitionState = RUNNING): TransitionStep { + return TransitionStep( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.DOZING, + value = value, + transitionState = state, + ownerName = "DeviceEntryBackgroundViewModelTest", + ) + } + + private fun dozingToLockscreen(value: Float, state: TransitionState = RUNNING): TransitionStep { + return TransitionStep( + from = KeyguardState.DOZING, + to = KeyguardState.LOCKSCREEN, + value = value, + transitionState = state, + ownerName = "DeviceEntryBackgroundViewModelTest", + ) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt index fb1bf281715d..6397979d9627 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt @@ -303,7 +303,8 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() { // Top edge is not applicable in dual shade, as well as two-finger swipe. assertThat(downDestination).isNull() } else { - assertThat(downDestination).isEqualTo(ShowOverlay(Overlays.NotificationsShade)) + assertThat(downDestination) + .isEqualTo(ShowOverlay(Overlays.NotificationsShade, isIrreversible = true)) assertThat(downDestination?.transitionKey).isNull() } @@ -320,7 +321,7 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() { downWithTwoPointers -> assertThat(downFromTopRightDestination).isNull() else -> { assertThat(downFromTopRightDestination) - .isEqualTo(ShowOverlay(Overlays.QuickSettingsShade)) + .isEqualTo(ShowOverlay(Overlays.QuickSettingsShade, isIrreversible = true)) assertThat(downFromTopRightDestination?.transitionKey).isNull() } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt index 030b1726bb73..030b1726bb73 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt index dfd964f0eaa7..dfd964f0eaa7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/table/TableLogBufferTest.kt index 9c4c862cccf2..9c4c862cccf2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/log/table/TableLogBufferTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt index 414974cc2941..414974cc2941 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/interactor/MediaCarouselInteractorTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/taskswitcher/ui/viewmodel/TaskSwitcherNotificationViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/taskswitcher/ui/viewmodel/TaskSwitcherNotificationViewModelTest.kt index 5bedc134a1ee..5bedc134a1ee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/taskswitcher/ui/viewmodel/TaskSwitcherNotificationViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediaprojection/taskswitcher/ui/viewmodel/TaskSwitcherNotificationViewModelTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediarouter/data/repository/MediaRouterRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediarouter/data/repository/MediaRouterRepositoryTest.kt index 84ec1a5677aa..77be8c718b14 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/mediarouter/data/repository/MediaRouterRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediarouter/data/repository/MediaRouterRepositoryTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.mediarouter.data.repository import androidx.test.filters.SmallTest +import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.Kosmos @@ -28,9 +29,11 @@ import kotlin.test.Test import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest +import org.junit.runner.RunWith @SmallTest @OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) class MediaRouterRepositoryTest : SysuiTestCase() { val kosmos = Kosmos() val testScope = kosmos.testScope diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelForceQSTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelForceQSTest.kt index acd69af2736a..da166408b926 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelForceQSTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelForceQSTest.kt @@ -26,10 +26,11 @@ import com.android.systemui.statusbar.sysuiStatusBarStateController import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.Parameterized +import platform.test.runner.parameterized.ParameterizedAndroidJunit4 +import platform.test.runner.parameterized.Parameters @SmallTest -@RunWith(Parameterized::class) +@RunWith(ParameterizedAndroidJunit4::class) @RunWithLooper class QSFragmentComposeViewModelForceQSTest(private val testData: TestData) : AbstractQSFragmentComposeViewModelTest() { @@ -75,7 +76,7 @@ class QSFragmentComposeViewModelForceQSTest(private val testData: TestData) : companion object { private const val EXPANSION = 0.3f - @Parameterized.Parameters(name = "{0}") + @Parameters(name = "{0}") @JvmStatic fun createTestData(): List<TestData> { return statusBarStates.flatMap { statusBarState -> diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt index 3e5dee69c85c..a1edfc1dbcd5 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt @@ -53,7 +53,7 @@ class IssueRecordingServiceSessionTest : SysuiTestCase() { private val bgExecutor = kosmos.fakeExecutor private val userContextProvider: UserContextProvider = kosmos.userTracker private val dialogTransitionAnimator: DialogTransitionAnimator = kosmos.dialogTransitionAnimator - private lateinit var traceurMessageSender: TraceurMessageSender + private lateinit var traceurConnection: TraceurConnection private val issueRecordingState = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager) @@ -65,13 +65,13 @@ class IssueRecordingServiceSessionTest : SysuiTestCase() { @Before fun setup() { - traceurMessageSender = mock<TraceurMessageSender>() + traceurConnection = mock<TraceurConnection>() underTest = IssueRecordingServiceSession( bgExecutor, dialogTransitionAnimator, panelInteractor, - traceurMessageSender, + traceurConnection, issueRecordingState, iActivityManager, notificationManager, @@ -85,7 +85,7 @@ class IssueRecordingServiceSessionTest : SysuiTestCase() { bgExecutor.runAllReady() Truth.assertThat(issueRecordingState.isRecording).isTrue() - verify(traceurMessageSender).startTracing(any<TraceConfig>()) + verify(traceurConnection).startTracing(any<TraceConfig>()) } @Test @@ -94,12 +94,12 @@ class IssueRecordingServiceSessionTest : SysuiTestCase() { bgExecutor.runAllReady() Truth.assertThat(issueRecordingState.isRecording).isFalse() - verify(traceurMessageSender).stopTracing() + verify(traceurConnection).stopTracing() } @Test fun cancelsNotification_afterReceivingShareCommand() { - underTest.share(0, null, mContext) + underTest.share(0, null) bgExecutor.runAllReady() verify(notificationManager).cancelAsUser(isNull(), anyInt(), any<UserHandle>()) @@ -110,7 +110,7 @@ class IssueRecordingServiceSessionTest : SysuiTestCase() { issueRecordingState.takeBugreport = true val uri = mock<Uri>() - underTest.share(0, uri, mContext) + underTest.share(0, uri) bgExecutor.runAllReady() verify(iActivityManager).requestBugReportWithExtraAttachment(uri) @@ -121,17 +121,17 @@ class IssueRecordingServiceSessionTest : SysuiTestCase() { issueRecordingState.takeBugreport = false val uri = mock<Uri>() - underTest.share(0, uri, mContext) + underTest.share(0, uri) bgExecutor.runAllReady() - verify(traceurMessageSender).shareTraces(mContext, uri) + verify(traceurConnection).shareTraces(uri) } @Test fun closesShade_afterReceivingShareCommand() { val uri = mock<Uri>() - underTest.share(0, uri, mContext) + underTest.share(0, uri) bgExecutor.runAllReady() verify(panelInteractor).collapsePanels() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/RecordIssueDialogDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/RecordIssueDialogDelegateTest.kt index 8d84c3e7392e..963973588236 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/RecordIssueDialogDelegateTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/RecordIssueDialogDelegateTest.kt @@ -78,7 +78,6 @@ class RecordIssueDialogDelegateTest : SysuiTestCase() { @Mock private lateinit var sysuiState: SysUiState @Mock private lateinit var systemUIDialogManager: SystemUIDialogManager @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher - @Mock private lateinit var traceurMessageSender: TraceurMessageSender private val systemClock = FakeSystemClock() private val bgExecutor = FakeExecutor(systemClock) private val mainExecutor = FakeExecutor(systemClock) @@ -104,7 +103,7 @@ class RecordIssueDialogDelegateTest : SysuiTestCase() { systemUIDialogManager, sysuiState, broadcastDispatcher, - mDialogTransitionAnimator + mDialogTransitionAnimator, ) ) @@ -120,7 +119,6 @@ class RecordIssueDialogDelegateTest : SysuiTestCase() { mediaProjectionMetricsLogger, screenCaptureDisabledDialogDelegate, state, - traceurMessageSender ) { latch.countDown() } @@ -166,7 +164,7 @@ class RecordIssueDialogDelegateTest : SysuiTestCase() { verify(mediaProjectionMetricsLogger, never()) .notifyProjectionInitiated( anyInt(), - eq(SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER) + eq(SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER), ) assertThat(screenRecordSwitch.isChecked).isFalse() } @@ -188,7 +186,7 @@ class RecordIssueDialogDelegateTest : SysuiTestCase() { verify(mediaProjectionMetricsLogger) .notifyProjectionInitiated( anyInt(), - eq(SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER) + eq(SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER), ) verify(factory, times(2)).create(any(SystemUIDialog.Delegate::class.java)) } @@ -208,7 +206,7 @@ class RecordIssueDialogDelegateTest : SysuiTestCase() { verify(mediaProjectionMetricsLogger) .notifyProjectionInitiated( anyInt(), - eq(SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER) + eq(SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER), ) verify(factory, never()).create() } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/TraceurConnectionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/TraceurConnectionTest.kt new file mode 100644 index 000000000000..d90cca9b23fe --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/TraceurConnectionTest.kt @@ -0,0 +1,77 @@ +/* + * 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.recordissue + +import android.os.IBinder +import android.os.Looper +import android.os.Messenger +import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import androidx.test.platform.app.InstrumentationRegistry +import com.android.systemui.SysuiTestCase +import com.android.systemui.settings.UserContextProvider +import com.android.traceur.PresetTraceConfigs +import java.util.concurrent.CountDownLatch +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.mock +import org.mockito.MockitoAnnotations +import org.mockito.kotlin.any +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +@SmallTest +@RunWith(AndroidJUnit4::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class TraceurConnectionTest : SysuiTestCase() { + + @Mock private lateinit var userContextProvider: UserContextProvider + + private lateinit var underTest: TraceurConnection + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + whenever(userContextProvider.userContext).thenReturn(mContext) + underTest = TraceurConnection.Provider(userContextProvider, Looper.getMainLooper()).create() + } + + @Test + fun onBoundRunnables_areRun_whenServiceIsBound() { + val latch = CountDownLatch(1) + underTest.onBound.add { latch.countDown() } + + underTest.onServiceConnected( + InstrumentationRegistry.getInstrumentation().componentName, + mock(IBinder::class.java), + ) + + latch.await() + } + + @Test + fun startTracing_sendsMsg_toStartTracing() { + underTest.binder = mock(Messenger::class.java) + + underTest.startTracing(PresetTraceConfigs.getThermalConfig()) + + verify(underTest.binder)!!.send(any()) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/UserAwareConnectionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/UserAwareConnectionTest.kt new file mode 100644 index 000000000000..f671bf44c42b --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/UserAwareConnectionTest.kt @@ -0,0 +1,70 @@ +/* + * 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.recordissue + +import android.content.Context +import android.content.Intent +import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.settings.UserContextProvider +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.Mock +import org.mockito.Mockito.any +import org.mockito.MockitoAnnotations +import org.mockito.kotlin.times +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +@SmallTest +@RunWith(AndroidJUnit4::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class UserAwareConnectionTest : SysuiTestCase() { + + @Mock private lateinit var userContextProvider: UserContextProvider + @Mock private lateinit var mockContext: Context + + private lateinit var underTest: UserAwareConnection + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + whenever(userContextProvider.userContext).thenReturn(mockContext) + whenever(mockContext.bindService(any(), any(), anyInt())).thenReturn(true) + underTest = UserAwareConnection(userContextProvider, Intent()) + } + + @Test + fun doBindService_requestToBindToTheService_viaTheCorrectUserContext() { + underTest.doBind() + + verify(userContextProvider).userContext + } + + @Test + fun doBindService_DoesntRequestToBindToTheService_IfAlreadyRequested() { + underTest.doBind() + underTest.doBind() + underTest.doBind() + + verify(userContextProvider, times(1)).userContext + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt index 5c47f552e400..47fae9f0629f 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt @@ -106,7 +106,7 @@ class GoneUserActionsViewModelTest : SysuiTestCase() { runCurrent() assertThat(userActions?.get(swipeDownFromTopWithTwoFingers())) - .isEqualTo(UserActionResult(Scenes.QuickSettings)) + .isEqualTo(UserActionResult(Scenes.QuickSettings, isIrreversible = true)) } @Test @@ -118,7 +118,7 @@ class GoneUserActionsViewModelTest : SysuiTestCase() { runCurrent() assertThat(userActions?.get(swipeDownFromTopWithTwoFingers())) - .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade)) + .isEqualTo(UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true)) } @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilterTest.kt deleted file mode 100644 index efde1ecec512..000000000000 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilterTest.kt +++ /dev/null @@ -1,112 +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. - */ - -@file:OptIn(ExperimentalCoroutinesApi::class) - -package com.android.systemui.scene.ui.viewmodel - -import android.graphics.Region -import android.view.setSystemGestureExclusionRegion -import androidx.compose.ui.geometry.Offset -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.kosmos.testScope -import com.android.systemui.lifecycle.activateIn -import com.android.systemui.scene.sceneContainerGestureFilterFactory -import com.android.systemui.settings.displayTracker -import com.android.systemui.testKosmos -import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.Job -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest -import org.junit.Test -import org.junit.runner.RunWith - -@SmallTest -@RunWith(AndroidJUnit4::class) -class SceneContainerGestureFilterTest : SysuiTestCase() { - - private val kosmos = testKosmos() - private val testScope = kosmos.testScope - private val displayId = kosmos.displayTracker.defaultDisplayId - - private val underTest = kosmos.sceneContainerGestureFilterFactory.create(displayId) - private val activationJob = Job() - - @Test - fun shouldFilterGesture_whenNoRegion_returnsFalse() = - testScope.runTest { - activate() - setSystemGestureExclusionRegion(displayId, null) - runCurrent() - - assertThat(underTest.shouldFilterGesture(Offset(100f, 100f))).isFalse() - } - - @Test - fun shouldFilterGesture_whenOutsideRegion_returnsFalse() = - testScope.runTest { - activate() - setSystemGestureExclusionRegion(displayId, Region(0, 0, 200, 200)) - runCurrent() - - assertThat(underTest.shouldFilterGesture(Offset(300f, 100f))).isFalse() - } - - @Test - fun shouldFilterGesture_whenInsideRegion_returnsTrue() = - testScope.runTest { - activate() - setSystemGestureExclusionRegion(displayId, Region(0, 0, 200, 200)) - runCurrent() - - assertThat(underTest.shouldFilterGesture(Offset(100f, 100f))).isTrue() - } - - @Test(expected = IllegalStateException::class) - fun shouldFilterGesture_beforeActivation_throws() = - testScope.runTest { - setSystemGestureExclusionRegion(displayId, Region(0, 0, 200, 200)) - runCurrent() - - underTest.shouldFilterGesture(Offset(100f, 100f)) - } - - @Test(expected = IllegalStateException::class) - fun shouldFilterGesture_afterCancellation_throws() = - testScope.runTest { - activate() - setSystemGestureExclusionRegion(displayId, Region(0, 0, 200, 200)) - runCurrent() - - cancel() - - underTest.shouldFilterGesture(Offset(100f, 100f)) - } - - private fun TestScope.activate() { - underTest.activateIn(testScope, activationJob) - runCurrent() - } - - private fun TestScope.cancel() { - activationJob.cancel() - runCurrent() - } -} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerHapticsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerHapticsViewModelTest.kt index 664315d19494..ca9500b5d74b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerHapticsViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerHapticsViewModelTest.kt @@ -51,7 +51,7 @@ import org.junit.runner.RunWith import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.verify -import org.mockito.kotlin.verifyZeroInteractions +import org.mockito.kotlin.verifyNoMoreInteractions @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @@ -134,7 +134,7 @@ class SceneContainerHapticsViewModelTest() : SysuiTestCase() { runCurrent() // THEN the view does not play a haptic feedback constant - verifyZeroInteractions(view) + verifyNoMoreInteractions(view) } @EnableFlags(Flags.FLAG_MSDL_FEEDBACK, Flags.FLAG_DUAL_SHADE) @@ -202,7 +202,7 @@ class SceneContainerHapticsViewModelTest() : SysuiTestCase() { runCurrent() // THEN the view does not play a haptic feedback constant - verifyZeroInteractions(view) + verifyNoMoreInteractions(view) } private fun createTransitionState(from: SceneKey, to: ContentKey) = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt index a37f511cef69..b632a8aaad46 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt @@ -39,7 +39,6 @@ import com.android.systemui.scene.sceneContainerViewModelFactory import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource -import com.android.systemui.settings.displayTracker import com.android.systemui.shade.data.repository.fakeShadeRepository import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.shade.shared.flag.DualShade @@ -82,7 +81,6 @@ class SceneContainerViewModelTest : SysuiTestCase() { underTest = kosmos.sceneContainerViewModelFactory.create( view, - kosmos.displayTracker.defaultDisplayId, { motionEventHandler -> this@SceneContainerViewModelTest.motionEventHandler = motionEventHandler }, @@ -178,8 +176,8 @@ class SceneContainerViewModelTest : SysuiTestCase() { sceneContainerConfig.sceneKeys .filter { it != currentScene } .filter { - // Moving to the Communal scene is not currently falsing protected. - it != Scenes.Communal + // Moving to the Communal and Dream scene is not currently falsing protected. + it != Scenes.Communal && it != Scenes.Dream } .forEach { toScene -> assertWithMessage("Protected scene $toScene not properly protected") diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt index 15d68813808c..fcb366bfd8ee 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt @@ -29,6 +29,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.coroutines.collectValues import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.flags.EnableSceneContainer @@ -50,6 +51,7 @@ import com.android.systemui.shade.domain.startable.shadeStartable import com.android.systemui.shade.shared.flag.DualShade import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat +import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope @@ -248,6 +250,27 @@ class ShadeUserActionsViewModelTest : SysuiTestCase() { assertThat(actions?.get(Swipe.Up)).isEqualTo(UserActionResult(Scenes.Communal)) } + @Test + fun upTransitionSceneKey_neverGoesBackToShadeScene() = + testScope.runTest { + val actions by collectValues(underTest.actions) + val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene) + assertThat(currentScene).isEqualTo(Scenes.Lockscreen) + kosmos.sceneInteractor.changeScene(Scenes.Shade, "") + assertThat(currentScene).isEqualTo(Scenes.Shade) + + kosmos.sceneInteractor.changeScene(Scenes.QuickSettings, "") + assertThat(currentScene).isEqualTo(Scenes.QuickSettings) + + actions.forEachIndexed { index, map -> + assertWithMessage( + "Actions on index $index is incorrectly mapping back to the Shade scene!" + ) + .that((map[Swipe.Up] as? UserActionResult.ChangeScene)?.toScene) + .isNotEqualTo(Scenes.Shade) + } + } + private fun TestScope.setDeviceEntered(isEntered: Boolean) { if (isEntered) { // Unlock the device marking the device has entered. diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java index beba16229c12..ea5c29ef30aa 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java @@ -20,8 +20,6 @@ import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertFalse; -import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow; - import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -31,12 +29,16 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow; + +import android.platform.test.annotations.EnableFlags; import android.testing.TestableLooper; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.compose.animation.scene.ObservableTransitionState; +import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.communal.shared.model.CommunalScenes; import com.android.systemui.dump.DumpManager; @@ -67,9 +69,6 @@ import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.kotlin.JavaAdapter; import com.android.systemui.util.time.FakeSystemClock; -import kotlinx.coroutines.flow.MutableStateFlow; -import kotlinx.coroutines.test.TestScope; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -79,6 +78,9 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.verification.VerificationMode; +import kotlinx.coroutines.flow.MutableStateFlow; +import kotlinx.coroutines.test.TestScope; + @SmallTest @RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper @@ -517,6 +519,32 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase { } @Test + @EnableFlags(Flags.FLAG_CHECK_LOCKSCREEN_GONE_TRANSITION) + public void testNotLockscreenInGoneTransition_invalidationCalled() { + // GIVEN visual stability is being maintained b/c animation is playing + mKosmos.getKeyguardTransitionRepository().sendTransitionStepJava( + mTestScope, new TransitionStep( + KeyguardState.LOCKSCREEN, + KeyguardState.GONE, + 1f, + TransitionState.RUNNING), /* validateStep = */ false); + mTestScope.getTestScheduler().runCurrent(); + assertFalse(mNotifStabilityManager.isPipelineRunAllowed()); + + // WHEN the animation has stopped playing + mKosmos.getKeyguardTransitionRepository().sendTransitionStepJava( + mTestScope, new TransitionStep( + KeyguardState.LOCKSCREEN, + KeyguardState.GONE, + 1f, + TransitionState.FINISHED), /* validateStep = */ false); + mTestScope.getTestScheduler().runCurrent(); + + // invalidate is called, b/c we were previously suppressing the pipeline from running + verifyStabilityManagerWasInvalidated(times(1)); + } + + @Test public void testNeverSuppressPipelineRunFromPanelCollapse_noInvalidationCalled() { // GIVEN animation is playing setPanelCollapsing(true); diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/EnRouteViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/EnRouteViewModelTest.kt deleted file mode 100644 index a310ef44cf35..000000000000 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/EnRouteViewModelTest.kt +++ /dev/null @@ -1,85 +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. - */ - -@file:OptIn(ExperimentalCoroutinesApi::class) - -package com.android.systemui.statusbar.notification.row.ui.viewmodel - -import android.platform.test.annotations.EnableFlags -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.kosmos.testScope -import com.android.systemui.statusbar.notification.row.data.repository.fakeNotificationRowRepository -import com.android.systemui.statusbar.notification.row.shared.EnRouteContentModel -import com.android.systemui.statusbar.notification.row.shared.IconModel -import com.android.systemui.statusbar.notification.row.shared.RichOngoingNotificationFlag -import com.android.systemui.testKosmos -import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.runTest -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.kotlin.mock - -@RunWith(AndroidJUnit4::class) -@SmallTest -@EnableFlags(RichOngoingNotificationFlag.FLAG_NAME) -class EnRouteViewModelTest : SysuiTestCase() { - private val kosmos = testKosmos() - private val testScope = kosmos.testScope - private val repository = kosmos.fakeNotificationRowRepository - - private var contentModel: EnRouteContentModel? - get() = repository.richOngoingContentModel.value as? EnRouteContentModel - set(value) { - repository.richOngoingContentModel.value = value - } - - private lateinit var underTest: EnRouteViewModel - - @Before - fun setup() { - underTest = kosmos.getEnRouteViewModel(repository) - } - - @Test - fun viewModelShowsContent() = - testScope.runTest { - val title by collectLastValue(underTest.title) - val text by collectLastValue(underTest.text) - contentModel = - exampleEnRouteContent( - title = "Example EnRoute Title", - text = "Example EnRoute Text", - ) - assertThat(title).isEqualTo("Example EnRoute Title") - assertThat(text).isEqualTo("Example EnRoute Text") - } - - private fun exampleEnRouteContent( - icon: IconModel = mock(), - title: CharSequence = "example text", - text: CharSequence = "example title", - ) = - EnRouteContentModel( - smallIcon = icon, - title = title, - text = text, - ) -} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/TimerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/TimerViewModelTest.kt deleted file mode 100644 index 61873ad294e3..000000000000 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/TimerViewModelTest.kt +++ /dev/null @@ -1,108 +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. - */ - -@file:OptIn(ExperimentalCoroutinesApi::class) - -package com.android.systemui.statusbar.notification.row.ui.viewmodel - -import android.app.Notification -import android.app.PendingIntent -import android.platform.test.annotations.EnableFlags -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.kosmos.testScope -import com.android.systemui.statusbar.notification.row.data.repository.fakeNotificationRowRepository -import com.android.systemui.statusbar.notification.row.shared.IconModel -import com.android.systemui.statusbar.notification.row.shared.RichOngoingNotificationFlag -import com.android.systemui.statusbar.notification.row.shared.TimerContentModel -import com.android.systemui.statusbar.notification.row.shared.TimerContentModel.TimerState.Paused -import com.android.systemui.testKosmos -import com.google.common.truth.Truth.assertThat -import java.time.Duration -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.runTest -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.kotlin.mock - -@RunWith(AndroidJUnit4::class) -@SmallTest -@EnableFlags(RichOngoingNotificationFlag.FLAG_NAME) -class TimerViewModelTest : SysuiTestCase() { - private val kosmos = testKosmos() - private val testScope = kosmos.testScope - private val repository = kosmos.fakeNotificationRowRepository - - private var contentModel: TimerContentModel? - get() = repository.richOngoingContentModel.value as? TimerContentModel - set(value) { - repository.richOngoingContentModel.value = value - } - - private lateinit var underTest: TimerViewModel - - @Before - fun setup() { - underTest = kosmos.getTimerViewModel(repository) - } - - @Test - fun labelShowsTheTimerName() = - testScope.runTest { - val label by collectLastValue(underTest.label) - contentModel = pausedTimer(name = "Example Timer Name") - assertThat(label).isEqualTo("Example Timer Name") - } - - @Test - fun pausedTimeRemainingFormatsWell() = - testScope.runTest { - val label by collectLastValue(underTest.pausedTime) - contentModel = pausedTimer(timeRemaining = Duration.ofMinutes(3)) - assertThat(label).isEqualTo("3:00") - contentModel = pausedTimer(timeRemaining = Duration.ofSeconds(119)) - assertThat(label).isEqualTo("1:59") - contentModel = pausedTimer(timeRemaining = Duration.ofSeconds(121)) - assertThat(label).isEqualTo("2:01") - contentModel = pausedTimer(timeRemaining = Duration.ofHours(1)) - assertThat(label).isEqualTo("1:00:00") - contentModel = pausedTimer(timeRemaining = Duration.ofHours(24)) - assertThat(label).isEqualTo("24:00:00") - } - - private fun pausedTimer( - icon: IconModel = mock(), - name: String = "example", - timeRemaining: Duration = Duration.ofMinutes(3), - resumeIntent: PendingIntent? = null, - addMinuteAction: Notification.Action? = null, - resetAction: Notification.Action? = null - ) = - TimerContentModel( - icon = icon, - name = name, - state = - Paused( - timeRemaining = timeRemaining, - resumeIntent = resumeIntent, - addMinuteAction = addMinuteAction, - resetAction = resetAction, - ) - ) -} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt index f40bfbdeb54b..8d678ef00b4a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt @@ -506,7 +506,7 @@ class NotificationListViewModelTest(flags: FlagsParameterization) : SysuiTestCas @EnableSceneContainer fun pinnedHeadsUpRows_filtersForPinnedItems() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) // WHEN there are no pinned rows val rows = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.kt new file mode 100644 index 000000000000..9abdf42e735c --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.kt @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.android.systemui.statusbar.policy + +import android.app.NotificationManager +import android.os.Handler +import android.provider.Settings +import android.service.notification.ZenModeConfig +import android.testing.TestableLooper +import android.testing.TestableLooper.RunWithLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.broadcastDispatcher +import com.android.systemui.dump.dumpManager +import com.android.systemui.kosmos.testScope +import com.android.systemui.settings.userTracker +import com.android.systemui.testKosmos +import com.android.systemui.util.settings.fakeGlobalSettings +import com.google.common.truth.Truth.assertThat +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicInteger +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers +import org.mockito.Mockito +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(AndroidJUnit4::class) +@RunWithLooper +class ZenModeControllerImplTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private lateinit var testableLooper: TestableLooper + private lateinit var controller: ZenModeControllerImpl + + private val globalSettings = kosmos.fakeGlobalSettings + private val config: ZenModeConfig = mock<ZenModeConfig>() + private val mNm: NotificationManager = mock<NotificationManager>() + + @Before + fun setUp() { + testableLooper = TestableLooper.get(this) + mContext.addMockSystemService(NotificationManager::class.java, mNm) + whenever(mNm.zenModeConfig).thenReturn(config) + + controller = + ZenModeControllerImpl( + mContext, + Handler.createAsync(testableLooper.looper), + kosmos.broadcastDispatcher, + kosmos.dumpManager, + globalSettings, + kosmos.userTracker, + ) + } + + @Test + fun testRemoveDuringCallback() { + val callback = + object : ZenModeController.Callback { + override fun onConfigChanged(config: ZenModeConfig) { + controller.removeCallback(this) + } + } + + controller.addCallback(callback) + val mockCallback = Mockito.mock(ZenModeController.Callback::class.java) + controller.addCallback(mockCallback) + controller.fireConfigChanged(config) + Mockito.verify(mockCallback).onConfigChanged(ArgumentMatchers.eq(config)) + } + + @Test + fun testAreNotificationsHiddenInShade_zenOffShadeSuppressed() { + config.suppressedVisualEffects = + NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST + controller.updateZenMode(Settings.Global.ZEN_MODE_OFF) + controller.updateZenModeConfig() + assertThat(controller.areNotificationsHiddenInShade()).isFalse() + } + + @Test + fun testAreNotificationsHiddenInShade_zenOnShadeNotSuppressed() { + val policy = + NotificationManager.Policy( + 0, + 0, + 0, + NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR, + ) + whenever(mNm.consolidatedNotificationPolicy).thenReturn(policy) + controller.updateConsolidatedNotificationPolicy() + controller.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) + assertThat(controller.areNotificationsHiddenInShade()).isFalse() + } + + @Test + fun testAreNotificationsHiddenInShade_zenOnShadeSuppressed() { + val policy = + NotificationManager.Policy( + 0, + 0, + 0, + NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST, + ) + whenever(mNm.consolidatedNotificationPolicy).thenReturn(policy) + controller.updateConsolidatedNotificationPolicy() + controller.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) + assertThat(controller.areNotificationsHiddenInShade()).isTrue() + } + + @Test + fun testModeChange() = + testScope.runTest { + val states = + listOf( + Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, + Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, + Settings.Global.ZEN_MODE_ALARMS, + Settings.Global.ZEN_MODE_ALARMS, + ) + + for (state in states) { + globalSettings.putInt(Settings.Global.ZEN_MODE, state) + testScope.runCurrent() + testableLooper.processAllMessages() + assertThat(controller.zen).isEqualTo(state) + } + } + + @Test + fun testModeChange_callbackNotified() = + testScope.runTest { + val currentState = AtomicInteger(-1) + + val callback: ZenModeController.Callback = + object : ZenModeController.Callback { + override fun onZenChanged(zen: Int) { + currentState.set(zen) + } + } + + controller.addCallback(callback) + + val states = + listOf( + Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, + Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, + Settings.Global.ZEN_MODE_ALARMS, + Settings.Global.ZEN_MODE_ALARMS, + ) + + for (state in states) { + globalSettings.putInt(Settings.Global.ZEN_MODE, state) + testScope.runCurrent() + testableLooper.processAllMessages() + assertThat(currentState.get()).isEqualTo(state) + } + } + + @Test + fun testCallbackRemovedWhileDispatching_doesntCrash() = + testScope.runTest { + val remove = AtomicBoolean(false) + globalSettings.putInt(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF) + testableLooper.processAllMessages() + val callback: ZenModeController.Callback = + object : ZenModeController.Callback { + override fun onZenChanged(zen: Int) { + if (remove.get()) { + controller.removeCallback(this) + } + } + } + controller.addCallback(callback) + controller.addCallback(object : ZenModeController.Callback {}) + + remove.set(true) + + globalSettings.putInt( + Settings.Global.ZEN_MODE, + Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, + ) + testScope.runCurrent() + testableLooper.processAllMessages() + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt index a0f64314098c..9d93a9c7fe0b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt @@ -61,7 +61,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { interactor, kosmos.testDispatcher, mockDialogDelegate, - mockDialogEventLogger + mockDialogEventLogger, ) @Test @@ -97,7 +97,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { assertThat(tiles?.size).isEqualTo(3) with(tiles?.elementAt(0)!!) { assertThat(this.text).isEqualTo("Disabled by other") - assertThat(this.subtext).isEqualTo("Set up") + assertThat(this.subtext).isEqualTo("Not set") assertThat(this.enabled).isEqualTo(false) } with(tiles?.elementAt(1)!!) { @@ -323,10 +323,10 @@ class ModesDialogViewModelTest : SysuiTestCase() { assertThat(tiles!!).hasSize(6) assertThat(tiles!![0].subtext).isEqualTo("When the going gets tough") assertThat(tiles!![1].subtext).isEqualTo("On • When in Rome") - assertThat(tiles!![2].subtext).isEqualTo("Set up") + assertThat(tiles!![2].subtext).isEqualTo("Not set") assertThat(tiles!![3].subtext).isEqualTo("Off") assertThat(tiles!![4].subtext).isEqualTo("On") - assertThat(tiles!![5].subtext).isEqualTo("Set up") + assertThat(tiles!![5].subtext).isEqualTo("Not set") } @Test @@ -387,7 +387,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { } with(tiles?.elementAt(2)!!) { assertThat(this.stateDescription).isEqualTo("Off") - assertThat(this.subtextDescription).isEqualTo("Set up") + assertThat(this.subtextDescription).isEqualTo("Not set") } with(tiles?.elementAt(3)!!) { assertThat(this.stateDescription).isEqualTo("Off") @@ -399,7 +399,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { } with(tiles?.elementAt(5)!!) { assertThat(this.stateDescription).isEqualTo("Off") - assertThat(this.subtextDescription).isEqualTo("Set up") + assertThat(this.subtextDescription).isEqualTo("Not set") } // All tiles have the same long click info @@ -451,7 +451,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { .setName("Active without manual") .setActive(true) .setManualInvocationAllowed(false) - .build(), + .build() ) ) runCurrent() @@ -492,7 +492,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { .setId("ID") .setName("Disabled by other") .setEnabled(false, /* byUser= */ false) - .build(), + .build() ) ) runCurrent() @@ -500,7 +500,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { assertThat(tiles?.size).isEqualTo(1) with(tiles?.elementAt(0)!!) { assertThat(this.text).isEqualTo("Disabled by other") - assertThat(this.subtext).isEqualTo("Set up") + assertThat(this.subtext).isEqualTo("Not set") assertThat(this.enabled).isEqualTo(false) // Click the tile @@ -519,7 +519,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { // Check that nothing happened to the tile with(tiles?.elementAt(0)!!) { assertThat(this.text).isEqualTo("Disabled by other") - assertThat(this.subtext).isEqualTo("Set up") + assertThat(this.subtext).isEqualTo("Not set") assertThat(this.enabled).isEqualTo(false) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt index 9064f7c8889d..ba9fa926947c 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt @@ -20,9 +20,9 @@ import android.view.MotionEvent 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.android.systemui.touchpad.tutorial.ui.gesture.GestureState.Finished +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.InProgress +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NotStarted import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -32,28 +32,28 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class BackGestureMonitorTest : SysuiTestCase() { - private var gestureState = NOT_STARTED + private var gestureState: GestureState = NotStarted private val gestureMonitor = BackGestureMonitor( gestureDistanceThresholdPx = SWIPE_DISTANCE.toInt(), - gestureStateChangedCallback = { gestureState = it } + gestureStateChangedCallback = { gestureState = it }, ) @Test fun triggersGestureFinishedForThreeFingerGestureRight() { - assertStateAfterEvents(events = ThreeFingerGesture.swipeRight(), expectedState = FINISHED) + assertStateAfterEvents(events = ThreeFingerGesture.swipeRight(), expectedState = Finished) } @Test fun triggersGestureFinishedForThreeFingerGestureLeft() { - assertStateAfterEvents(events = ThreeFingerGesture.swipeLeft(), expectedState = FINISHED) + assertStateAfterEvents(events = ThreeFingerGesture.swipeLeft(), expectedState = Finished) } @Test fun triggersGestureProgressForThreeFingerGestureStarted() { assertStateAfterEvents( events = ThreeFingerGesture.startEvents(x = 0f, y = 0f), - expectedState = IN_PROGRESS + expectedState = InProgress(), ) } @@ -61,24 +61,24 @@ class BackGestureMonitorTest : SysuiTestCase() { fun doesntTriggerGestureFinished_onGestureDistanceTooShort() { assertStateAfterEvents( events = ThreeFingerGesture.swipeLeft(distancePx = SWIPE_DISTANCE / 2), - expectedState = NOT_STARTED + expectedState = NotStarted, ) } @Test fun doesntTriggerGestureFinished_onThreeFingersSwipeInOtherDirections() { - assertStateAfterEvents(events = ThreeFingerGesture.swipeUp(), expectedState = NOT_STARTED) - assertStateAfterEvents(events = ThreeFingerGesture.swipeDown(), expectedState = NOT_STARTED) + assertStateAfterEvents(events = ThreeFingerGesture.swipeUp(), expectedState = NotStarted) + assertStateAfterEvents(events = ThreeFingerGesture.swipeDown(), expectedState = NotStarted) } @Test fun doesntTriggerGestureFinished_onTwoFingersSwipe() { - assertStateAfterEvents(events = TwoFingerGesture.swipeRight(), expectedState = NOT_STARTED) + assertStateAfterEvents(events = TwoFingerGesture.swipeRight(), expectedState = NotStarted) } @Test fun doesntTriggerGestureFinished_onFourFingersSwipe() { - assertStateAfterEvents(events = FourFingerGesture.swipeRight(), expectedState = NOT_STARTED) + assertStateAfterEvents(events = FourFingerGesture.swipeRight(), expectedState = NotStarted) } private fun assertStateAfterEvents(events: List<MotionEvent>, expectedState: GestureState) { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureMonitorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureMonitorTest.kt index 6aefbe9bf059..59cc026e82ee 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureMonitorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureMonitorTest.kt @@ -20,9 +20,9 @@ import android.view.MotionEvent 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.android.systemui.touchpad.tutorial.ui.gesture.GestureState.Finished +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.InProgress +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NotStarted import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -32,23 +32,23 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class HomeGestureMonitorTest : SysuiTestCase() { - private var gestureState = NOT_STARTED + private var gestureState: GestureState = GestureState.NotStarted private val gestureMonitor = HomeGestureMonitor( gestureDistanceThresholdPx = SWIPE_DISTANCE.toInt(), - gestureStateChangedCallback = { gestureState = it } + gestureStateChangedCallback = { gestureState = it }, ) @Test fun triggersGestureFinishedForThreeFingerGestureUp() { - assertStateAfterEvents(events = ThreeFingerGesture.swipeUp(), expectedState = FINISHED) + assertStateAfterEvents(events = ThreeFingerGesture.swipeUp(), expectedState = Finished) } @Test fun triggersGestureProgressForThreeFingerGestureStarted() { assertStateAfterEvents( events = ThreeFingerGesture.startEvents(x = 0f, y = 0f), - expectedState = IN_PROGRESS + expectedState = InProgress(), ) } @@ -56,28 +56,25 @@ class HomeGestureMonitorTest : SysuiTestCase() { fun doesntTriggerGestureFinished_onGestureDistanceTooShort() { assertStateAfterEvents( events = ThreeFingerGesture.swipeUp(distancePx = SWIPE_DISTANCE / 2), - expectedState = NOT_STARTED + expectedState = NotStarted, ) } @Test fun doesntTriggerGestureFinished_onThreeFingersSwipeInOtherDirections() { - assertStateAfterEvents(events = ThreeFingerGesture.swipeDown(), expectedState = NOT_STARTED) - assertStateAfterEvents(events = ThreeFingerGesture.swipeLeft(), expectedState = NOT_STARTED) - assertStateAfterEvents( - events = ThreeFingerGesture.swipeRight(), - expectedState = NOT_STARTED - ) + assertStateAfterEvents(events = ThreeFingerGesture.swipeDown(), expectedState = NotStarted) + assertStateAfterEvents(events = ThreeFingerGesture.swipeLeft(), expectedState = NotStarted) + assertStateAfterEvents(events = ThreeFingerGesture.swipeRight(), expectedState = NotStarted) } @Test fun doesntTriggerGestureFinished_onTwoFingersSwipe() { - assertStateAfterEvents(events = TwoFingerGesture.swipeUp(), expectedState = NOT_STARTED) + assertStateAfterEvents(events = TwoFingerGesture.swipeUp(), expectedState = NotStarted) } @Test fun doesntTriggerGestureFinished_onFourFingersSwipe() { - assertStateAfterEvents(events = FourFingerGesture.swipeUp(), expectedState = NOT_STARTED) + assertStateAfterEvents(events = FourFingerGesture.swipeUp(), expectedState = NotStarted) } private fun assertStateAfterEvents(events: List<MotionEvent>, expectedState: GestureState) { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureMonitorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureMonitorTest.kt index d059c14785a5..7eac6bb09264 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureMonitorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureMonitorTest.kt @@ -21,9 +21,9 @@ import androidx.compose.ui.input.pointer.util.VelocityTracker1D 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.android.systemui.touchpad.tutorial.ui.gesture.GestureState.Finished +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.InProgress +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NotStarted import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -43,7 +43,7 @@ class RecentAppsGestureMonitorTest : SysuiTestCase() { const val FAST = THRESHOLD_VELOCITY_PX_PER_MS * 1000 + 1 } - private var gestureState = NOT_STARTED + private var gestureState: GestureState = GestureState.NotStarted private val velocityTracker = mock<VelocityTracker1D> { // by default return correct speed for the gesture - as if pointer is slowing down @@ -54,25 +54,25 @@ class RecentAppsGestureMonitorTest : SysuiTestCase() { gestureDistanceThresholdPx = SWIPE_DISTANCE.toInt(), gestureStateChangedCallback = { gestureState = it }, velocityThresholdPxPerMs = THRESHOLD_VELOCITY_PX_PER_MS, - velocityTracker = velocityTracker + velocityTracker = velocityTracker, ) @Test fun triggersGestureFinishedForThreeFingerGestureUp() { - assertStateAfterEvents(events = ThreeFingerGesture.swipeUp(), expectedState = FINISHED) + assertStateAfterEvents(events = ThreeFingerGesture.swipeUp(), expectedState = Finished) } @Test fun doesntTriggerGestureFinished_onGestureSpeedTooHigh() { whenever(velocityTracker.calculateVelocity()).thenReturn(FAST) - assertStateAfterEvents(events = ThreeFingerGesture.swipeUp(), expectedState = NOT_STARTED) + assertStateAfterEvents(events = ThreeFingerGesture.swipeUp(), expectedState = NotStarted) } @Test fun triggersGestureProgressForThreeFingerGestureStarted() { assertStateAfterEvents( events = ThreeFingerGesture.startEvents(x = 0f, y = 0f), - expectedState = IN_PROGRESS + expectedState = InProgress(), ) } @@ -80,28 +80,25 @@ class RecentAppsGestureMonitorTest : SysuiTestCase() { fun doesntTriggerGestureFinished_onGestureDistanceTooShort() { assertStateAfterEvents( events = ThreeFingerGesture.swipeUp(distancePx = SWIPE_DISTANCE / 2), - expectedState = NOT_STARTED + expectedState = NotStarted, ) } @Test fun doesntTriggerGestureFinished_onThreeFingersSwipeInOtherDirections() { - assertStateAfterEvents(events = ThreeFingerGesture.swipeDown(), expectedState = NOT_STARTED) - assertStateAfterEvents(events = ThreeFingerGesture.swipeLeft(), expectedState = NOT_STARTED) - assertStateAfterEvents( - events = ThreeFingerGesture.swipeRight(), - expectedState = NOT_STARTED - ) + assertStateAfterEvents(events = ThreeFingerGesture.swipeDown(), expectedState = NotStarted) + assertStateAfterEvents(events = ThreeFingerGesture.swipeLeft(), expectedState = NotStarted) + assertStateAfterEvents(events = ThreeFingerGesture.swipeRight(), expectedState = NotStarted) } @Test fun doesntTriggerGestureFinished_onTwoFingersSwipe() { - assertStateAfterEvents(events = TwoFingerGesture.swipeUp(), expectedState = NOT_STARTED) + assertStateAfterEvents(events = TwoFingerGesture.swipeUp(), expectedState = NotStarted) } @Test fun doesntTriggerGestureFinished_onFourFingersSwipe() { - assertStateAfterEvents(events = FourFingerGesture.swipeUp(), expectedState = NOT_STARTED) + assertStateAfterEvents(events = FourFingerGesture.swipeUp(), expectedState = NotStarted) } private fun assertStateAfterEvents(events: List<MotionEvent>, expectedState: GestureState) { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandlerTest.kt index 466ddbe25c54..4d26366614f6 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandlerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandlerTest.kt @@ -25,8 +25,6 @@ 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.MultiFingerGesture.Companion.SWIPE_DISTANCE import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -36,7 +34,7 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class TouchpadGestureHandlerTest : SysuiTestCase() { - private var gestureState = NOT_STARTED + private var gestureState: GestureState = GestureState.NotStarted private val handler = TouchpadGestureHandler( BackGestureMonitor( @@ -82,7 +80,7 @@ class TouchpadGestureHandlerTest : SysuiTestCase() { fun triggersGestureDoneForThreeFingerGesture() { backGestureEvents().forEach { handler.onMotionEvent(it) } - assertThat(gestureState).isEqualTo(FINISHED) + assertThat(gestureState).isEqualTo(GestureState.Finished) } private fun backGestureEvents(): List<MotionEvent> { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractorTest.kt new file mode 100644 index 000000000000..7ce421a5aa62 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractorTest.kt @@ -0,0 +1,150 @@ +/* + * 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.dialog.domain.interactor + +import android.app.ActivityManager +import android.testing.TestableLooper +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.kosmos.Kosmos +import com.android.systemui.kosmos.testScope +import com.android.systemui.plugins.fakeVolumeDialogController +import com.android.systemui.testKosmos +import com.android.systemui.volume.Events +import com.android.systemui.volume.dialog.domain.model.VolumeDialogVisibilityModel +import com.google.common.truth.Truth.assertThat +import kotlin.time.Duration.Companion.days +import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.advanceTimeBy +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +private val dialogTimeoutDuration = 3.seconds + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(AndroidJUnit4::class) +@TestableLooper.RunWithLooper() +class VolumeDialogVisibilityInteractorTest : SysuiTestCase() { + + private val kosmos: Kosmos = testKosmos() + + private lateinit var underTest: VolumeDialogVisibilityInteractor + + @Before + fun setUp() { + underTest = kosmos.volumeDialogVisibilityInteractor + } + + @Test + fun testShowRequest_visible() = + with(kosmos) { + testScope.runTest { + runCurrent() + val visibilityModel by collectLastValue(underTest.dialogVisibility) + fakeVolumeDialogController.onShowRequested( + Events.SHOW_REASON_VOLUME_CHANGED, + false, + ActivityManager.LOCK_TASK_MODE_LOCKED, + ) + runCurrent() + + assertThat(visibilityModel!!) + .isEqualTo( + VolumeDialogVisibilityModel.Visible( + Events.SHOW_REASON_VOLUME_CHANGED, + false, + ActivityManager.LOCK_TASK_MODE_LOCKED, + ) + ) + } + } + + @Test + fun testDismissRequest_dismissed() = + with(kosmos) { + testScope.runTest { + runCurrent() + val visibilityModel by collectLastValue(underTest.dialogVisibility) + fakeVolumeDialogController.onShowRequested( + Events.SHOW_REASON_VOLUME_CHANGED, + false, + ActivityManager.LOCK_TASK_MODE_LOCKED, + ) + runCurrent() + + fakeVolumeDialogController.onDismissRequested(Events.DISMISS_REASON_SCREEN_OFF) + + assertThat(visibilityModel!!) + .isEqualTo( + VolumeDialogVisibilityModel.Dismissed(Events.DISMISS_REASON_SCREEN_OFF) + ) + } + } + + @Test + fun testTimeout_dismissed() = + with(kosmos) { + testScope.runTest { + runCurrent() + underTest.resetDismissTimeout() + val visibilityModel by collectLastValue(underTest.dialogVisibility) + fakeVolumeDialogController.onShowRequested( + Events.SHOW_REASON_VOLUME_CHANGED, + false, + ActivityManager.LOCK_TASK_MODE_LOCKED, + ) + runCurrent() + + advanceTimeBy(1.days) + + assertThat(visibilityModel!!) + .isEqualTo(VolumeDialogVisibilityModel.Dismissed(Events.DISMISS_REASON_TIMEOUT)) + } + } + + @Test + fun testResetTimeoutInterruptsEvents() = + with(kosmos) { + testScope.runTest { + runCurrent() + underTest.resetDismissTimeout() + val visibilityModel by collectLastValue(underTest.dialogVisibility) + fakeVolumeDialogController.onShowRequested( + Events.SHOW_REASON_VOLUME_CHANGED, + false, + ActivityManager.LOCK_TASK_MODE_LOCKED, + ) + runCurrent() + + advanceTimeBy(dialogTimeoutDuration / 2) + underTest.resetDismissTimeout() + advanceTimeBy(dialogTimeoutDuration / 2) + underTest.resetDismissTimeout() + advanceTimeBy(dialogTimeoutDuration / 2) + + assertThat(visibilityModel) + .isInstanceOf(VolumeDialogVisibilityModel.Visible::class.java) + } + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/WMShellTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/WMShellTest.kt index e1be6b008903..d2688a8fc146 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/WMShellTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/WMShellTest.kt @@ -53,7 +53,7 @@ import com.android.systemui.testKosmos import com.android.systemui.user.data.repository.fakeUserRepository import com.android.systemui.util.kotlin.JavaAdapter import com.android.wm.shell.desktopmode.DesktopMode -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener +import com.android.wm.shell.desktopmode.DesktopRepository.VisibleTasksListener import com.android.wm.shell.onehanded.OneHanded import com.android.wm.shell.onehanded.OneHandedEventCallback import com.android.wm.shell.onehanded.OneHandedTransitionCallback diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml index fcb3a3ec8edc..042067b12e8a 100644 --- a/packages/SystemUI/res-keyguard/values-ur/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml @@ -20,7 +20,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"اپنا PIN درج کریں"</string> + <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"اپنا PIN درج کریں"</string> <string name="keyguard_enter_pin" msgid="8114529922480276834">"PIN درج کریں"</string> <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"اپنا پیٹرن درج کریں"</string> <string name="keyguard_enter_pattern" msgid="7616595160901084119">"پیٹرن ڈرا کریں"</string> diff --git a/packages/SystemUI/res/drawable/contextual_edu_all_apps.xml b/packages/SystemUI/res/drawable/contextual_edu_all_apps.xml new file mode 100644 index 000000000000..263e11caf03d --- /dev/null +++ b/packages/SystemUI/res/drawable/contextual_edu_all_apps.xml @@ -0,0 +1,25 @@ +<!-- + ~ 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. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="32dp" + android:viewportHeight="32" + android:viewportWidth="32"> + <path + android:fillColor="#001E2D" + android:pathData="M28.6 30.3l-4.1-4a5.2 5.2 0 0 1-2.7 0.7a5.2 5.2 0 0 1-5.3-5.3a5 5 0 0 1 1.5-3.6q1.6-1.6 3.8-1.6a5 5 0 0 1 3.7 1.6a5 5 0 0 1 1.3 5.1q-0.2 0.9-0.6 1.3l4.1 4l-1.7 1.8zm-21.7-3.3a5 5 0 0 1-3.7-1.5a5 5 0 0 1-1.5-3.7a5 5 0 0 1 1.5-3.7a5 5 0 0 1 3.7-1.6a5 5 0 0 1 3.8 1.6a5 5 0 0 1 1.5 3.7a5 5 0 0 1-1.5 3.7a5 5 0 0 1-3.8 1.5zm14.9-2.3q1 0 2-0.8q0.8-1 0.8-2q0-1.2-0.8-2t-2-0.8q-1.3 0-2 0.8q-0.9 0.8-0.9 2q0 1.1 0.9 2q0.8 0.8 2 0.8zm-14.9-12.5a5 5 0 0 1-3.7-1.5q-1.5-1.5-1.5-3.7a5 5 0 0 1 1.5-3.7a5 5 0 0 1 3.7-1.6a5 5 0 0 1 3.8 1.6a5 5 0 0 1 1.5 3.7q0 2.2-1.5 3.7a5 5 0 0 1-3.8 1.5zm14.9 0a5.2 5.2 0 0 1-5.3-5.3a5 5 0 0 1 1.5-3.6q1.6-1.6 3.8-1.6a5 5 0 0 1 3.7 1.6a5 5 0 0 1 1.5 3.7q0 2.2-1.5 3.7a5 5 0 0 1-3.7 1.5z" /> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/contextual_edu_dialog_bg.xml b/packages/SystemUI/res/drawable/contextual_edu_dialog_bg.xml new file mode 100644 index 000000000000..d7000d7f5a5c --- /dev/null +++ b/packages/SystemUI/res/drawable/contextual_edu_dialog_bg.xml @@ -0,0 +1,24 @@ +<?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. + --> +<!-- Setting insetBottom to avoid bottom elevation of dialog being clipped off --> +<inset xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:insetBottom="@dimen/contextual_edu_dialog_elevation"> + <shape> + <corners android:radius="28dp" /> + <solid android:color="?androidprv:attr/materialColorTertiaryFixed" /> + </shape> +</inset>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/contextual_edu_swipe_back.xml b/packages/SystemUI/res/drawable/contextual_edu_swipe_back.xml new file mode 100644 index 000000000000..8b0142c4638e --- /dev/null +++ b/packages/SystemUI/res/drawable/contextual_edu_swipe_back.xml @@ -0,0 +1,25 @@ +<!-- + ~ 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. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="28dp" + android:height="32dp" + android:viewportHeight="32" + android:viewportWidth="28"> + <path + android:fillColor="#001E2D" + android:pathData="M27.3 9.8h-6.4v-1.8h4a17.4 17.4 0 0 0-5.1-3.1a15.2 15.2 0 0 0-5.8-1.1c-2 0-4 0.4-5.9 1.1a17.6 17.6 0 0 0-5.1 3.1h4v1.8h-6.4v-6.4h1.8l0 2.8a18.6 18.6 0 0 1 11.6-4.2a18.5 18.5 0 0 1 11.6 4.2v-2.8h1.8l0 6.4zm-13.6 20.2c-0.5 0-1-0.1-1.5-0.3s-0.9-0.5-1.3-0.9l-6.8-6.9l0.8-0.9a2.4 2.4 0 0 1 2.5-0.7l2.5 0.7v-11c0-0.3 0.1-0.6 0.3-0.9c0.3-0.3 0.6-0.4 0.9-0.4s0.6 0.1 0.8 0.4c0.2 0.2 0.4 0.5 0.4 0.9v9.4h1.6v-4.3c0-0.3 0.1-0.6 0.3-0.8s0.5-0.4 0.9-0.4s0.6 0.1 0.9 0.4c0.2 0.2 0.4 0.5 0.4 0.8v4.3h1.6v-3c0-0.3 0.1-0.6 0.3-0.8s0.5-0.4 0.9-0.4c0.3 0 0.6 0.1 0.9 0.4c0.3 0.2 0.4 0.5 0.4 0.8v3h1.6v-0.3c0-0.3 0.1-0.6 0.3-0.8s0.5-0.4 0.9-0.4s0.7 0.1 0.9 0.4c0.2 0.2 0.4 0.5 0.4 0.8v5.6c0 1.5-0.5 2.7-1.6 3.8a5.1 5.1 0 0 1-3.8 1.6h-5.6z" /> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/contextual_edu_swipe_up.xml b/packages/SystemUI/res/drawable/contextual_edu_swipe_up.xml new file mode 100644 index 000000000000..294b62658c22 --- /dev/null +++ b/packages/SystemUI/res/drawable/contextual_edu_swipe_up.xml @@ -0,0 +1,28 @@ +<!-- + ~ 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. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="32dp" + android:viewportHeight="32" + android:viewportWidth="32"> + <group> + <clip-path android:pathData="M0,0h32v32H0z" /> + <path + android:fillColor="#001E2D" + android:pathData="M21.8 27.1a3.5 3.5 0 0 1-3-0.1l-8.8-4.1l0.5-1.2c0.2-0.4 0.5-0.8 0.8-1c0.4-0.3 0.8-0.5 1.3-0.5l2.6-0.2l-3.8-10.4a1.1 1.1 0 0 1 0-0.9c0.2-0.3 0.4-0.5 0.7-0.6s0.6-0.1 0.9 0s0.5 0.4 0.6 0.7l3.2 8.9l1.5-0.6l-1.5-4.1a1.1 1.1 0 0 1 0-0.9c0.2-0.3 0.4-0.5 0.7-0.6s0.6-0.1 0.9 0s0.5 0.4 0.6 0.7l1.5 4.1l1.5-0.6l-1-2.8a1.1 1.1 0 0 1 0-0.9c0.2-0.3 0.4-0.5 0.7-0.6s0.7-0.1 0.9 0c0.3 0.1 0.5 0.4 0.6 0.7l1 2.8l1.6-0.6l-0.1-0.3a1.1 1.1 0 0 1 0-0.9c0.2-0.3 0.4-0.5 0.7-0.7c0.3-0.1 0.6-0.1 0.9 0.1c0.3 0.1 0.5 0.4 0.6 0.7l1.9 5.2c0.5 1.4 0.5 2.8-0.2 4.1a5.1 5.1 0 0 1-3 2.7l-5.3 1.9zm-13.8-9.4a15.5 15.5 0 0 1-3.4-9.8a17.8 17.8 0 0 1 0.4-3.8l-2.4 2.4l-1.3-1.2l4.5-4.5l4.5 4.5l-1.2 1.2l-2.3-2.3c-0.2 0.6-0.3 1.2-0.4 1.8a14.1 14.1 0 0 0 0.6 6.4a13.5 13.5 0 0 0 2.2 4l-1.3 1.3z" /> + </group> +</vector> diff --git a/packages/SystemUI/res/drawable/touchpad_tutorial_home_icon.xml b/packages/SystemUI/res/drawable/touchpad_tutorial_home_icon.xml new file mode 100644 index 000000000000..9f3d07500910 --- /dev/null +++ b/packages/SystemUI/res/drawable/touchpad_tutorial_home_icon.xml @@ -0,0 +1,26 @@ +<!-- + ~ 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" + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M240,760L360,760L360,520L600,520L600,760L720,760L720,400L480,220L240,400L240,760ZM160,840L160,360L480,120L800,360L800,840L520,840L520,600L440,600L440,840L160,840ZM480,490L480,490L480,490L480,490L480,490L480,490L480,490L480,490L480,490Z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/touchpad_tutorial_recents_icon.xml b/packages/SystemUI/res/drawable/touchpad_tutorial_recents_icon.xml new file mode 100644 index 000000000000..113908aa8bca --- /dev/null +++ b/packages/SystemUI/res/drawable/touchpad_tutorial_recents_icon.xml @@ -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. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:autoMirrored="true" + android:tint="?attr/colorControlNormal" + android:viewportHeight="960" + android:viewportWidth="960"> + <path + android:fillColor="@android:color/white" + android:pathData="M120,800Q87,800 63.5,776.5Q40,753 40,720L40,240Q40,207 63.5,183.5Q87,160 120,160L200,160Q233,160 256.5,183.5Q280,207 280,240L280,720Q280,753 256.5,776.5Q233,800 200,800L120,800ZM120,721L200,721Q200,721 200,721Q200,721 200,721L200,239Q200,239 200,239Q200,239 200,239L120,239Q120,239 120,239Q120,239 120,239L120,721Q120,721 120,721Q120,721 120,721ZM440,800Q407,800 383.5,776.5Q360,753 360,720L360,240Q360,207 383.5,183.5Q407,160 440,160L840,160Q873,160 896.5,183.5Q920,207 920,240L920,720Q920,753 896.5,776.5Q873,800 840,800L440,800ZM440,721L840,721Q840,721 840,721Q840,721 840,721L840,239Q840,239 840,239Q840,239 840,239L440,239Q440,239 440,239Q440,239 440,239L440,721Q440,721 440,721Q440,721 440,721ZM200,721Q200,721 200,721Q200,721 200,721L200,239Q200,239 200,239Q200,239 200,239L200,239Q200,239 200,239Q200,239 200,239L200,721Q200,721 200,721Q200,721 200,721ZM440,721Q440,721 440,721Q440,721 440,721L440,239Q440,239 440,239Q440,239 440,239L440,239Q440,239 440,239Q440,239 440,239L440,721Q440,721 440,721Q440,721 440,721Z" /> +</vector> diff --git a/packages/SystemUI/res/layout/contextual_edu_dialog.xml b/packages/SystemUI/res/layout/contextual_edu_dialog.xml new file mode 100644 index 000000000000..ee42b2363dd5 --- /dev/null +++ b/packages/SystemUI/res/layout/contextual_edu_dialog.xml @@ -0,0 +1,45 @@ +<?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. + --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/contextual_edu_dialog_bg" + android:elevation="@dimen/contextual_edu_dialog_elevation" + android:gravity="center_vertical" + android:orientation="horizontal" + android:padding="12dp"> + + <ImageView + android:id="@+id/edu_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@null" + android:importantForAccessibility="no" + android:paddingRight="16dp" /> + + <TextView + android:id="@+id/edu_message" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@color/transparent" + android:ellipsize="end" + android:fontFamily="google-sans-medium" + android:maxWidth="280dp" + android:textColor="?androidprv:attr/materialColorOnTertiaryFixed" + android:textSize="14sp" + android:textStyle="bold" /> +</LinearLayout> diff --git a/packages/SystemUI/res/layout/notification_template_en_route_expanded.xml b/packages/SystemUI/res/layout/notification_template_en_route_expanded.xml deleted file mode 100644 index ca6d66a370bd..000000000000 --- a/packages/SystemUI/res/layout/notification_template_en_route_expanded.xml +++ /dev/null @@ -1,86 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?><!-- - ~ Copyright (C) 2014 The Android Open Source Project - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License - --> -<com.android.systemui.statusbar.notification.row.ui.view.EnRouteView - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@*android:id/status_bar_latest_event_content" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:clipChildren="false" - android:tag="big" - > - - <LinearLayout - android:id="@*android:id/notification_action_list_margin_target" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginBottom="@*android:dimen/notification_content_margin" - android:orientation="vertical" - > - - <FrameLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_gravity="top" - > - - <include layout="@*android:layout/notification_template_header" /> - - <LinearLayout - android:id="@*android:id/notification_main_column" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="@*android:dimen/notification_content_margin_start" - android:layout_marginEnd="@*android:dimen/notification_content_margin_end" - android:layout_marginTop="@*android:dimen/notification_content_margin_top" - android:orientation="vertical" - > - - <include layout="@*android:layout/notification_template_part_line1" /> - - <include layout="@*android:layout/notification_template_text_multiline" /> - - <include - android:layout_width="match_parent" - android:layout_height="@*android:dimen/notification_progress_bar_height" - android:layout_marginTop="@*android:dimen/notification_progress_margin_top" - layout="@*android:layout/notification_template_progress" - /> - </LinearLayout> - - <include layout="@*android:layout/notification_template_right_icon" /> - </FrameLayout> - - <ViewStub - android:layout="@*android:layout/notification_material_reply_text" - android:id="@*android:id/notification_material_reply_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - /> - - <include - layout="@*android:layout/notification_template_smart_reply_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="@*android:dimen/notification_content_margin_start" - android:layout_marginEnd="@*android:dimen/notification_content_margin_end" - android:layout_marginTop="@*android:dimen/notification_content_margin" - /> - - <include layout="@*android:layout/notification_material_action_list" /> - </LinearLayout> -</com.android.systemui.statusbar.notification.row.ui.view.EnRouteView> diff --git a/packages/SystemUI/res/layout/rich_ongoing_timer_notification.xml b/packages/SystemUI/res/layout/rich_ongoing_timer_notification.xml deleted file mode 100644 index 3a679e3c16cb..000000000000 --- a/packages/SystemUI/res/layout/rich_ongoing_timer_notification.xml +++ /dev/null @@ -1,122 +0,0 @@ -<?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 - --> -<com.android.systemui.statusbar.notification.row.ui.view.TimerView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="wrap_content" - xmlns:app="http://schemas.android.com/apk/res-auto"> - - <androidx.constraintlayout.widget.Guideline - android:id="@+id/topBaseline" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal" - app:layout_constraintGuide_begin="22sp" - /> - - <ImageView - android:id="@+id/icon" - android:layout_width="24dp" - android:layout_height="24dp" - app:tint="@android:color/white" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/label" - android:baseline="18dp" - app:layout_constraintBaseline_toTopOf="@id/topBaseline" - /> - <TextView - android:id="@+id/label" - android:layout_width="0dp" - android:layout_height="wrap_content" - app:layout_constraintStart_toEndOf="@id/icon" - app:layout_constraintEnd_toStartOf="@id/chronoRemaining" - android:singleLine="true" - tools:text="15s Timer" - app:layout_constraintBaseline_toTopOf="@id/topBaseline" - android:paddingEnd="4dp" - /> - <Chronometer - android:id="@+id/chronoRemaining" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:singleLine="true" - android:textSize="20sp" - android:gravity="end" - tools:text="0:12" - app:layout_constraintBaseline_toTopOf="@id/topBaseline" - app:layout_constraintEnd_toStartOf="@id/pausedTimeRemaining" - app:layout_constraintStart_toEndOf="@id/label" - android:countDown="true" - android:paddingEnd="4dp" - /> - <TextView - android:id="@+id/pausedTimeRemaining" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:singleLine="true" - android:textSize="20sp" - android:gravity="end" - tools:text="0:12" - app:layout_constraintBaseline_toTopOf="@id/topBaseline" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@id/chronoRemaining" - android:paddingEnd="4dp" - /> - - <androidx.constraintlayout.widget.Barrier - android:id="@+id/bottomOfTop" - android:layout_width="match_parent" - android:layout_height="match_parent" - app:barrierDirection="bottom" - app:constraint_referenced_ids="icon,label,chronoRemaining,pausedTimeRemaining" - /> - - <com.android.systemui.statusbar.notification.row.ui.view.TimerButtonView - style="@*android:style/NotificationEmphasizedAction" - android:id="@+id/mainButton" - android:layout_width="124dp" - android:layout_height="wrap_content" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/altButton" - app:layout_constraintTop_toBottomOf="@id/bottomOfTop" - app:layout_constraintHorizontal_chainStyle="spread" - android:paddingEnd="4dp" - /> - - <com.android.systemui.statusbar.notification.row.ui.view.TimerButtonView - style="@*android:style/NotificationEmphasizedAction" - android:id="@+id/altButton" - android:layout_width="124dp" - android:layout_height="wrap_content" - app:layout_constraintTop_toBottomOf="@id/bottomOfTop" - app:layout_constraintStart_toEndOf="@id/mainButton" - app:layout_constraintEnd_toEndOf="@id/resetButton" - android:paddingEnd="4dp" - /> - - <com.android.systemui.statusbar.notification.row.ui.view.TimerButtonView - style="@*android:style/NotificationEmphasizedAction" - android:id="@+id/resetButton" - android:layout_width="124dp" - android:layout_height="wrap_content" - app:layout_constraintTop_toBottomOf="@id/bottomOfTop" - app:layout_constraintStart_toEndOf="@id/altButton" - app:layout_constraintEnd_toEndOf="parent" - android:paddingEnd="4dp" - /> -</com.android.systemui.statusbar.notification.row.ui.view.TimerView>
\ 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 a9f9fafd505f..0f411ca5bfea 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Aan"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Op • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Af"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Stel op"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Bestuur in instellings"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Geen aktiewe modusse nie}=1{{mode} is aktief}other{# modusse is aktief}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Gesprekke"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Vee alle stil kennisgewings uit"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Kennisgewings onderbreek deur Moenie Steur Nie"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Geen kennisgewings nie}=1{Kennisgewings is deur {mode} onderbreek}=2{Kennisgewings is deur {mode} en een ander modus onderbreek}other{Kennisgewings is deur {mode} en # ander modusse onderbreek}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Wys demonstrasiemodus"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Wekker"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> is aan"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Stel op om vinniger, veiliger aankope met jou foon te doen"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Wys alles"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Leer raakpaneelgebare"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigeer met jou sleutelbord en raakpaneel"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Leer raakpaneelgebare, kortpadsleutels en meer"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Teruggebaar"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Tuisgebaar"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Bekyk onlangse apps"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klaar"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gaan terug"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Swiep enige plek op die raakpaneel links of regs met drie vingers om terug te gaan.\n\nJy kan ook die kortpadsleutelhandeling + Esc hiervoor gebruik."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Knap gedaan!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Jy het die Gaan Terug-gebaar voltooi."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Gaan na tuisskerm"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Swiep enige tyd van die onderkant van jou skerm af op met drie vingers om na jou tuisskerm toe te gaan."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Mooi so!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Jy het die Gaan na Tuisskerm-gebaar voltooi."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Bekyk onlangse apps"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Swiep op en hou met drie vingers op jou raakpaneel."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Knap gedaan!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Jy het die Bekyk Onlangse Apps-gebaar voltooi."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Handelingsleutel"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Druk die handelingsleutel op jou sleutelbord om toegang tot jou apps te kry."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Geluk!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Jy het die Handelingsleutel-gebaar voltooi.\n\nHandeling + / wys al die kortpaaie wat vir jou beskikbaar is."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Sleutelbordlig"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Vlak %1$d van %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Huiskontroles"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Druk die handelingsleutel op jou sleutelbord om al jou apps te bekyk"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Gewysig"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Ontsluit om te kyk"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstuele opvoeding"</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> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 704bdcaa108a..553142448330 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"በርቷል"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"በርቷል • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ጠፍቷል"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"አዋቅር"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"ውይይቶች"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"ሁሉንም ጸጥ ያሉ ማሳወቂያዎችን ያጽዱ"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"ማሳወቂያዎች በአትረብሽ ባሉበት ቆመዋል"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{ምንም ማሳወቂያዎች የሉም}=1{ማሳወቂያዎች በ{mode} ባሉበት ቆመዋል}=2{ማሳወቂያዎች በ{mode} እና አንድ ሌላ ሁነታ ባሉበት ቆመዋል}one{ማሳወቂያዎች በ{mode} እና # ሌላ ሁነታ ባሉበት ቆመዋል}other{ማሳወቂያዎች በ{mode} እና # ሌላ ሁነታዎች ባሉበት ቆመዋል}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> በርቷል"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"በስልክዎ በመጠቀም ፈጣን እና የበለጠ ደህንነቱ በተጠበቀ መንገድ ግዢዎችን ለመፈጸም ዝግጁ ይሁኑ"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"ሁሉንም አሳይ"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"የመዳሰሻ ሰሌዳ ምልክቶችን ይወቁ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"የእርስዎን የቁልፍ ሰሌዳ እና የመዳሰሻ ሰሌዳ በመጠቀም ያስሱ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"የመዳሰሻ ሰሌዳ ምልክቶችን፣ የቁልፍ ሰሌዳ አቋራጮችን እና ሌሎችን ይወቁ"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"የተመለስ ምልክት"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"የቤት ምልክት"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"የቅርብ ጊዜ መተግበሪያዎችን አሳይ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ተከናውኗል"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ወደኋላ ተመለስ"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ወደኋላ ለመመለስ የመዳሰሻ ሰሌዳው ላይ የትኛውም ቦታ በሦስት ጣቶች ወደግራ ወይም ወደቀኝ ያንሸራትቱ።\n\nእንዲሁም የቁልፍ ሰሌዳ አቋራጭ + ESC ለዚህ መጠቀም ይችላሉ።"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"ጥሩ ሠርተዋል!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ወደኋላ የመመለስ ምልክትን አጠናቅቀዋል።"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ወደ መነሻ ሂድ"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"በማንኛውም ጊዜ ወደ መነሻ ማያ ገፅዎ ለመሄድ ከማያ ገፅዎ ታች በሦስት ጣቶች ወደላይ ያሸብልሉ።"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"አሪፍ!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"ወደ መነሻ ሂድ ምልክትን አጠናቅቀዋል።"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"የቅርብ ጊዜ መተግበሪያዎችን አሳይ"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"የመዳሰሻ ሰሌዳዎ ላይ ሦስት ጣቶችን በመጠቀም ወደ ላይ ያንሸራትቱ እና ይያዙ።"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ጥሩ ሠርተዋል!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"የቅርብ ጊዜ መተግበሪያዎች አሳይ ምልክትን አጠናቅቀዋል።"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"የተግባር ቁልፍ"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"መተግበሪያዎችዎን ለመድረስ በቁልፍ ሰሌዳዎ ላይ የእርምጃ ቁልፉን ይጫኑ።"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"እንኳን ደስ አለዎት!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"የተግባር ቁልፍ ምልክቱን አጠናቅቀዋል።\n\nእርምጃ + / ለእርስዎ ተገኚ የሆኑትን አቋራጮች በሙሉ ያሳያል።"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"የቁልፍ ሰሌዳ የጀርባ ብርሃን"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"ደረጃ %1$d ከ %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"የቤት ውስጥ ቁጥጥሮች"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ሁሉንም መተግበሪያዎችዎን ለማየት በቁልፍ ሰሌዳዎ ላይ ያለውን የተግባር ቁልፍ ይጫኑ"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ጽሁፍ ተቀይሯል"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ለመመልከት ይክፈቱ"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"የዓውድ ትምህርት"</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> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 8ed225df457b..091b58e9f414 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"مفعَّل"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"مفعّل • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"غير مفعَّل"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"إعداد"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"الإدارة في الإعدادات"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{ما مِن أوضاع مفعَّلة}=1{الوضع \"{mode}\" مفعَّل}two{وضعان مفعَّلان}few{# أوضاع مفعَّلة}many{# وضعًا مفعَّلاً}other{# وضع مفعَّل}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"لن يتم إزعاجك بالأصوات والاهتزاز، باستثناء المُنبِّهات والتذكيرات والأحداث والمتصلين الذين تحددهم. وسيظل بإمكانك سماع أي عناصر أخرى تختار تشغيلها، بما في ذلك الموسيقى والفيديوهات والألعاب."</string> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"المحادثات"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"محو جميع الإشعارات الصامتة"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"تم إيقاف الإشعارات مؤقتًا وفقًا لإعداد \"عدم الإزعاج\""</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{ما مِن إشعارات}=1{تم إيقاف الإشعارات مؤقتًا بواسطة \"{mode}\"}=2{تم إيقاف الإشعارات مؤقتًا بواسطة \"{mode}\" ووضع واحد آخر}few{تم إيقاف الإشعارات مؤقتًا بواسطة \"{mode}\" و# أوضاع أخرى}many{تم إيقاف الإشعارات مؤقتًا بواسطة \"{mode}\" و# وضعًا آخر}other{تم إيقاف الإشعارات مؤقتًا بواسطة \"{mode}\" و# وضع آخر}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"وضع \"<xliff:g id="MODENAME">%1$s</xliff:g>\" مفعَّل"</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> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"تعرَّف على إيماءات لوحة اللمس"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"التنقّل باستخدام لوحة المفاتيح ولوحة اللمس"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"تعرَّف على إيماءات لوحة اللمس واختصارات لوحة المفاتيح والمزيد"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"إيماءة الرجوع"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"إيماءة الانتقال إلى الشاشة الرئيسية"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"عرض التطبيقات المستخدَمة مؤخرًا"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"تم"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"رجوع"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"للرجوع، مرِّر سريعًا لليمين أو لليسار باستخدام ثلاثة أصابع في أي مكان على لوحة اللمس.\n\nيمكنك أيضًا الرجوع باستخدام اختصار لوحة المفاتيح \"مفتاح الإجراء + ESC\"."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"أحسنت"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"لقد أكملت التدريب على إيماءة الرجوع."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"الانتقال إلى الشاشة الرئيسية"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"للانتقال إلى الشاشة الرئيسية في أي وقت، مرِّر سريعًا من أسفل الشاشة إلى أعلاها بثلاثة أصابع."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"أحسنت"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"لقد أكملت التدريب على إيماءة الانتقال إلى الشاشة الرئيسية."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"عرض التطبيقات المستخدَمة مؤخرًا"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"مرِّر سريعًا للأعلى مع استمرار الضغط باستخدام ثلاثة أصابع على لوحة اللمس."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"أحسنت."</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"لقد أكملْت الدليل التوجيهي على إيماءة \"عرض التطبيقات المستخدَمة مؤخرًا\"."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"مفتاح الإجراء"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"للوصول إلى التطبيقات، اضغط على مفتاح الإجراء في لوحة المفاتيح."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"تهانينا!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"لقد أكملت التدريب على إيماءة مفتاح الإجراء.\n\nيؤدي الضغط على مفتاح الإجراء + / إلى عرض جميع الاختصارات المتاحة."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"الإضاءة الخلفية للوحة المفاتيح"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"مستوى الإضاءة: %1$d من %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"إدارة المنزل آليًّا"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"لعرض جميع التطبيقات، اضغط على مفتاح الإجراء في لوحة المفاتيح"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"إشعار مخفي"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"افتح القفل لعرض المعلومات"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"التعليم السياقي"</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> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 07c6f73c8975..bbaf97450cc2 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"অন আছে"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"অন আছে • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"অফ আছে"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"ছেট আপ কৰক"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"বাৰ্তালাপ"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"আটাইবোৰ নীৰৱ জাননী মচক"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"অসুবিধা নিদিব-ই জাননী পজ কৰিছে"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{কোনো জাননী নাই}=1{{mode}এ জাননী পজ কৰিছে}=2{{mode} আৰু আন এটা ম’ডে জাননী পজ কৰিছে}one{{mode} আৰু আন # টা ম’ডে জাননী পজ কৰিছে}other{{mode} আৰু আন # টা ম’ডে জাননী পজ কৰিছে}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"ডেম\' ম\'ড দেখুৱাওক"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"ইথাৰনেট"</string> <string name="status_bar_alarm" msgid="87160847643623352">"এলাৰ্ম"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"ৱালেট"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"আপোনাৰ ফ’নটোৰে দ্ৰুত তথা অধিক সুৰক্ষিত ক্ৰয় কৰিবলৈ ছেট আপ পাওক"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"আটাইবোৰ দেখুৱাওক"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"টাচ্চপেডৰ নিৰ্দেশসমূহ জানক"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"আপোনাৰ কীব’ৰ্ড আৰু টাচ্চপেড ব্যৱহাৰ কৰি নেভিগে’ট কৰক"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"টাচ্চপেডৰ নিৰ্দেশ, কীব’ৰ্ডৰ শ্বৰ্টকাট আৰু অধিকৰ বিষয়ে জানক"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"উভতি যাওক নিৰ্দেশ"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"গৃহ স্ক্ৰীনলৈ যোৱাৰ নিৰ্দেশ"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"শেহতীয়া এপ্সমূহ চাওক"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"হ’ল"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"উভতি যাওক"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"উভতি যাবলৈ, টাচ্চপেডৰ যিকোনো স্থানত তিনিটা আঙুলি ব্যৱহাৰ কৰি বাওঁ বা সোঁফালে ছোৱাইপ কৰক।\n\nইয়াৰ বাবে আপুনি কীব’ৰ্ড শ্বৰ্টকাট কাৰ্য + ESC ব্যৱহাৰ কৰিবও পাৰে।"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"বঢ়িয়া!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"আপুনি উভতি যোৱাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"গৃহ পৃষ্ঠালৈ যাওক"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"যিকোনো সময়তে আপোনাৰ গৃহ স্ক্ৰীনলৈ যাবলৈ, আপোনাৰ স্ক্ৰীনখনৰ একেবাৰে তলৰ পৰা ওপৰলৈ তিনিটা আঙুলিৰে ছোৱাইপ কৰক।"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"সুন্দৰ!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"আপুনি গৃহ স্ক্ৰীনলৈ উভতি যোৱাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"শেহতীয়া এপ্সমূহ চাওক"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"আপোনাৰ টাচ্চপেডত তিনিটা আঙুলি ব্যৱহাৰ কৰি ওপৰলৈ ছোৱাইপ কৰি কিছু সময় ধৰি ৰাখক।"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"বঢ়িয়া!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"আপুনি শেহতীয়া এপ্ চোৱাৰ নিৰ্দেশনাটো সম্পূৰ্ণ কৰিছে।"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"কাৰ্য কী"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"আপোনাৰ এপ্সমূহ এক্সেছ কৰিবলৈ আপোনাৰ কীব’ৰ্ডৰ কাৰ্য কীটোত টিপক।"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"অভিনন্দন!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"আপুনি কাৰ্য কীৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।\n\nকাৰ্য + /এ আপোনাৰ বাবে উপলব্ধ আটাইবোৰ শ্বৰ্টকাট দেখুৱায়।"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"কীব’ৰ্ডৰ বেকলাইট"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dৰ %1$d স্তৰ"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ঘৰৰ সা-সৰঞ্জামৰ নিয়ন্ত্ৰণ"</string> @@ -1436,6 +1450,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"আপোনাৰ আটাইবোৰ এপ্ চাবলৈ আপোনাৰ কীব’ৰ্ডৰ কাৰ্য কীটোত টিপক"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"সম্পাদনা কৰা হৈছে"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"চাবলৈ আনলক কৰক"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"প্ৰাসংগিক শিক্ষা"</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> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 551ec5cd436b..211a05d8b08d 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Aktiv"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Aktiv • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Deaktiv"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Ayarlayın"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Ayarlarda idarə edin"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Aktiv rejim yoxdur}=1{{mode} aktivdir}other{# rejim aktivdir}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Söhbətlər"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Səssiz bildirişlərin hamısını silin"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Bildirişlər \"Narahat Etməyin\" rejimi tərəfindən dayandırıldı"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Bildiriş yoxdur}=1{Bildirişlər {mode} tərəfindən dayandırıldı}=2{Bildirişlər {mode} və digər rejim tərəfindən dayandırıldı}other{Bildirişlər {mode} və # digər rejim tərəfindən dayandırıldı}}"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"İndi başlayın"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Heç bir bildiriş yoxdur"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Yeni bildiriş yoxdur"</string> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Demo rejimini göstərin"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Zəngli saat"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Pulqabı"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Telefonunuzla daha sürətli və təhlükəsiz satınalmalar etmək üçün ayarlayın"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Hamısını göstər"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Taçped jestlərini öyrənin"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Klaviatura və taçpeddən istifadə edərək hərəkət edin"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Taçped jestləri, klaviatura qısayolları və s. haqqında öyrənin"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Geri jesti"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Əsas ekran jesti"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Son tətbiqlərə baxın"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hazırdır"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Geri qayıdın"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Geri getmək üçün taçpeddə istənilən yerdə üç barmaqla sola və ya sağa çəkin.\n\nBunun üçün Action + ESC klaviatura qısayolundan da istifadə edə bilərsiniz."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Əla!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Geri getmə jestini tamamladınız."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ana ekrana qayıdın"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"İstənilən vaxt ana ekrana keçmək üçün ekranın aşağısından üç barmağınızla yuxarı çəkin."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Əla!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Əsas ekrana keçid jestini tamamladınız."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Son tətbiqlərə baxın"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Taçpeddə üç barmaq ilə yuxarı çəkib saxlayın."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Əla!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Son tətbiqlərə baxmaq jestini tamamladınız."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Fəaliyyət açarı"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Tətbiqlərə daxil olmaq üçün klaviaturada fəaliyyət açarını basın."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Təbriklər!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Fəaliyyət açarı jestini tamamladınız.\n\nFəaliyyət + / əlçatan bütün qısayolları göstərir."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatura işığı"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Səviyyə %1$d/%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Ev nizamlayıcıları"</string> @@ -1436,6 +1450,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Çıxarılıb"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Baxmaq üçün kiliddən çıxarın"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstual təhsil"</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> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 20dee4603e7b..6064cc10c821 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Uklj. • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Isključeno"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Podesi"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Upravljajte u podešavanjima"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nema aktivnih režima}=1{Aktivan je {mode} režim}one{Aktivan je # režim}few{Aktivna su # režima}other{Aktivno je # režima}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzacije"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Obrišite sva nečujna obaveštenja"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Obaveštenja su pauzirana režimom Ne uznemiravaj"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Nema obaveštenja}=1{Obaveštenja je pauzirao {mode}}=2{Obaveštenja su pauzirali {mode} i još jedan režim}one{Obaveštenja su pauzirali {mode} i još # režim}few{Obaveštenja su pauzirali {mode} i još # režima}other{Obaveštenja su pauzirali {mode} i još # režima}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Prikaži režim demonstracije"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Eternet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g>: uključeno"</string> <string name="wallet_title" msgid="5369767670735827105">"Novčanik"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Obavite konfigurisanje da biste mogli brže i sigurnije da kupujete pomoću telefona"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Prikaži sve"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Naučite pokrete za tačped"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Krećite se pomoću tastature i tačpeda"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Naučite pokrete za tačped, tasterske prečice i drugo"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Pokret za vraćanje"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pokret za početnu stranicu"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Prikaži nedavno korišćene aplikacije"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazad"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Da biste se vratili, prevucite ulevo sa tri prsta bilo gde na tačpedu.\n\nMožete da koristite i tastersku prečicu Alt + ESC za ovo."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Odlično!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Dovršili ste pokret za povratak."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Idi na početni ekran"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Da biste otišli na početni ekran u bilo kom trenutku, prevucite nagore od dna ekrana pomoću tri prsta."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Svaka čast!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Dovršili ste pokret za povratak na početnu stranicu."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Prikaži nedavno korišćene aplikacije"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Prevucite nagore i zadržite pomoću tri prsta na tačpedu."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Odlično!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Dovršili ste pokret za prikazivanje nedavno korišćenih aplikacija."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Taster radnji"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Da biste pristupili aplikacijama, pritisnite taster radnji na tastaturi."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Čestitamo!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Dovršili ste pokret pomoću tastera radnji.\n\nRadnja + / prikazuje sve prečice koje su vam dostupne."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvetljenje tastature"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. nivo od %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrole za dom"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Da biste pogledali sve aplikacije, pritisnite taster radnji na tastaturi"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redigovano"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Otključajte za prikaz"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstualno obrazovanje"</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> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index ba0a8b422474..cdaca7efcde0 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Уключана"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Уключана • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Выключана"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Наладзіць"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Адкрыць налады"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Актыўных рэжымаў няма}=1{Рэжым \"{mode}\" актыўны}one{# рэжым актыўны}few{# рэжымы актыўныя}many{# рэжымаў актыўныя}other{# рэжыму актыўныя}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Вас не будуць турбаваць гукі і вібрацыя, за выключэннем будзільнікаў, напамінаў, падзей і выбраных вамі абанентаў. Вы будзеце чуць усё, што ўключыце, у тым ліку музыку, відэа і гульні."</string> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Размовы"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Выдаліць усе апавяшчэнні без гуку"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Паказ апавяшчэнняў прыпынены ў рэжыме \"Не турбаваць\""</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Апавяшчэнняў няма}=1{Атрыманне апавяшчэнняў прыпынена рэжымам \"{mode}\"}=2{Атрыманне апавяшчэнняў прыпынена рэжымам \"{mode}\" і яшчэ адным рэжымам}one{Атрыманне апавяшчэнняў прыпынена рэжымам \"{mode}\" і яшчэ # рэжымам}few{Атрыманне апавяшчэнняў прыпынена рэжымам \"{mode}\" і яшчэ # рэжымамі}many{Атрыманне апавяшчэнняў прыпынена рэжымам \"{mode}\" і яшчэ # рэжымамі}other{Атрыманне апавяшчэнняў прыпынена рэжымам \"{mode}\" і яшчэ # рэжыму}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Паказваць дэманстрацыйны рэжым"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Будзільнік"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Кашалёк"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Наладзьце картку, каб рабіць больш хуткія і бяспечныя куплі з дапамогай тэлефона"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Паказаць усе"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Азнаёмцеся з жэстамі для сэнсарнай панэлі"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Навігацыя з дапамогай клавіятуры і сэнсарнай панэлі"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Азнаёмцеся з жэстамі для сэнсарнай панэлі, спалучэннямі клавіш і г. д."</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Жэст для вяртання на папярэдні экран"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жэст для вяртання на галоўны экран"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Прагляд нядаўніх праграм"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Гатова"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Каб вярнуцца, правядзіце трыма пальцамі ўлева ці ўправа ў любым месцы сэнсарнай панэлі.\n\nТаксама можна выкарыстоўваць спалучэнне \"клавіша дзеяння + ESC\"."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Выдатная праца!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Вы навучыліся рабіць жэст вяртання."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"На галоўны экран"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Каб у любы момант перайсці на галоўны экран, правядзіце па экране трыма пальцамі знізу ўверх."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Выдатна!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Вы навучыліся рабіць жэст для пераходу на галоўны экран."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Прагляд нядаўніх праграм"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Правядзіце па сэнсарнай панэлі трыма пальцамі ўверх і затрымайце пальцы."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Выдатная праца!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Вы скончылі вывучэнне жэсту для прагляду нядаўніх праграм."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Клавіша дзеяння"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Каб атрымаць доступ да праграм, націсніце клавішу дзеяння на клавіятуры."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Віншуем!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Вы навучыліся рабіць жэст з клавішай дзеяння.\n\nКалі націснуць клавішу дзеяння разам з \"/\", будуць паказаны ўсе даступныя спалучэнні клавіш."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Падсветка клавіятуры"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Узровень %1$d з %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Кіраванне домам"</string> @@ -1436,6 +1450,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Каб праглядзець усе праграмы, націсніце на клавішу дзеяння на клавіятуры"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Схавана"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Разблакіруйце экран, каб праглядзець"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Кантэкстнае навучанне"</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> @@ -1445,7 +1460,7 @@ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Выкарыстайце клавіятуру для прагляду ўсіх праграм"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Можна націснуць на клавішу дзеяння ў любы момант. Націсніце, каб азнаёміцца з іншымі жэстамі."</string> <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"Цяпер кіраваць дадатковым памяншэннем яркасці можна з дапамогай паўзунка яркасці"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Цяпер вы можаце дадаткова зацямніць экран, яшчэ больш панізіўшы ўзровень яркасці.\n\nПаколькі гэта функцыя цяпер уваходзіць у склад паўзунка яркасці, хуткія каманды для дадатковага памяншэння яркасці былі выдалены."</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Цяпер вы можаце дадаткова зацямніць экран, яшчэ больш панізіўшы ўзровень яркасці.\n\nПаколькі гэта функцыя цяпер уваходзіць у склад паўзунка яркасці, хуткія каманды для дадатковага памяншэння яркасці будуць выдалены."</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"Выдаліць хуткія каманды для дадатковага памяншэння яркасці"</string> <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"Хуткія каманды для дадатковага памяншэння яркасці выдалены"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Магчымасць падключэння"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index bf558eb42708..79fc4b278527 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Вкл."</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Вкл. • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Изкл."</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Настройване"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Разговори"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Изчистване на всички беззвучни известия"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Известията са поставени на пауза от режима „Не безпокойте“"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Няма известия}=1{Известията са поставени на пауза от {mode}}=2{Известията са поставени на пауза от {mode} и един друг режим}other{Известията са поставени на пауза от {mode} и # други режима}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Показване на демонстрационния режим"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Будилник"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Режимът „<xliff:g id="MODENAME">%1$s</xliff:g>“ е включен"</string> <string name="wallet_title" msgid="5369767670735827105">"Портфейл"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Купувайте по-бързо и по-сигурно с телефона си"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Показване на всички"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Научете за жестовете със сензорния панел"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Навигирайте посредством клавиатурата и сензорния панел"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Научете за жестовете със сензорния панел, клавишните комбинации и др."</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Жест за връщане назад"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жест за преминаване към началния екран"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Преглед на скорошните приложения"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"За да се върнете назад, прекарайте три пръста наляво или надясно по сензорния панел.\n\nЗа целта можете също да използвате комбинацията с клавиша за действия + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Отлично!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Изпълнихте жеста за връщане назад."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Към началния екран"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"За да преминете към началния екран по всяко време, прекарайте три пръста нагоре от долната част на екрана."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Чудесно!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Изпълнихте жеста за преминаване към началния екран."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Преглед на скорошните приложения"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Плъзнете нагоре с три пръста по сензорния панел и задръжте."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Отлично!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Изпълнихте жеста за преглед на скорошните приложения."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Клавиш за действия"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"За да осъществите достъп до приложенията, натиснете клавиша за действия на клавиатурата си."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Поздравления!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Изпълнихте жеста с клавиша за действия.\n\nНатискането на клавиша за действия и / показва всички налични клавишни комбинации."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Подсветка на клавиатурата"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Ниво %1$d от %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Контроли за дома"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"За да прегледате всичките си приложения, натиснете клавиша за действия на клавиатурата си"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Скрито"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Отключете за преглед"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Контекстуално обучение"</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> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index cf55feb343e8..485221a76580 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"চালু আছে"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"চালু আছে • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"বন্ধ আছে"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"সেট-আপ করুন"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"কথোপকথন"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"সব নীরব বিজ্ঞপ্তি মুছুন"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'বিরক্ত করবে না\' দিয়ে বিজ্ঞপ্তি পজ করা হয়েছে"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{কোনও বিজ্ঞপ্তি নেই}=1{{mode}-এর জন্য বিজ্ঞপ্তি পজ করা হয়েছে}=2{{mode} ও অন্য আরেকটি মোডের জন্য বিজ্ঞপ্তি পজ করা হয়েছে}one{{mode} ও অন্য #টি মোডের জন্য বিজ্ঞপ্তি পজ করা হয়েছে}other{{mode} ও অন্য #টি মোডের জন্য বিজ্ঞপ্তি পজ করা হয়েছে}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> চালু আছে"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"ফোন ব্যবহার করে আরও দ্রুত ও আরও নিরাপদে কেনাকাটা করার জন্য সেট-আপ করুন"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"সবকটি দেখুন"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"টাচপ্যাডের জেসচার সম্পর্কে জানুন"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"আপনার কীবোর্ড এবং টাচপ্যাড ব্যবহার করে নেভিগেট করুন"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"টাচপ্যাড জেসচার, কীবোর্ড শর্টকাট এবং আরও অনেক কিছু সম্পর্কে জানুন"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ফিরে যাওয়ার জেসচার"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"হোমপেজে যাওয়ার জেসচার"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"সম্প্রতি ব্যবহার করা হয়েছে এমন অ্যাপ দেখুন"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"হয়ে গেছে"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ফিরে যান"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ফিরে যেতে, টাচপ্যাডে যেকোনও জায়গায় তিনটি আঙুল দিয়ে বাঁদিক বা ডানদিকে সোয়াইপ করুন।\n\nএছাড়া, এটির জন্য আপনি কীবোর্ড শর্টকাট অ্যাকশন + ESC বোতাম প্রেস করতে পারবেন।"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"অসাধারণ!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"জেসচার ব্যবহার করে কীভাবে ফিরে যাওয়া যায় সেই সম্পর্কে আপনি জেনেছেন।"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"হোমে যান"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"যেকোনও সময়ে আপনার হোম স্ক্রিনে যেতে, আপনার স্ক্রিনের একদম নিচের থেকে তিনটি আঙুল দিয়ে উপরের দিকে সোয়াইপ করুন।"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"সাবাস!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"জেসচার ব্যবহার করে কীভাবে হোমে ফিরে যাওয়া যায় সেই সম্পর্কে আপনি জেনেছেন।"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"সম্প্রতি ব্যবহার করা হয়েছে এমন অ্যাপ দেখুন"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"আপনার টাচপ্যাডে তিনটি আঙুল ব্যবহার করে উপরের দিকে সোয়াইপ করে ধরে রাখুন।"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"অসাধারণ!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"সম্প্রতি ব্যবহার করা হয়েছে এমন অ্যাপের জেসচার দেখা সম্পূর্ণ করেছেন।"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"অ্যাকশন কী"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"আপনার অ্যাপ অ্যাক্সেস করতে, কীবোর্ডে অ্যাকশন কী প্রেস করুন"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"অভিনন্দন!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"অ্যাকশন কী জেসচার সম্পর্কে আপনি জেনেছেন।\n\nঅ্যাকশন + / প্রেস করলে আপনার কাছে উপলভ্য থাকা সব শর্টকাট দেখতে পাবেন।"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"কীবোর্ড ব্যাকলাইট"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d-এর মধ্যে %1$d লেভেল"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"হোম কন্ট্রোল"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"আপনার সব অ্যাপ দেখতে, কীবোর্ডে অ্যাকশন কী প্রেস করুন"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"রিড্যাক্ট করা হয়েছে"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"দেখার জন্য আনলক করুন"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"প্রাসঙ্গিক শিক্ষা"</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> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 679becec2b15..4c79f4879043 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Uključeno • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Isključeno"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Postavite"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Upravljajte opcijom u postavkama"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nema aktivnih načina rada}=1{Način rada {mode} je aktivan}one{# način rada je aktivan}few{# načina rada su aktivna}other{# načina rada je aktivno}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Razgovori"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Obriši sva nečujna obavještenja"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Obavještenja su pauzirana načinom rada Ne ometaj"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Nema obavještenja}=1{Obavještenja su pauzirana putem načina rada {mode}}=2{Obavještenja su pauzirana putem načina rada {mode} i još jednog načina rada}one{Obavještenja su pauzirana putem načina rada {mode} i još # načina rada}few{Obavještenja su pauzirana putem načina rada {mode} i još # načina rada}other{Obavještenja su pauzirana putem načina rada {mode} i još # načina rada}}"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Započni odmah"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nema obavještenja"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nema novih obavještenja"</string> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Prikaži način rada za demonstraciju"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Način rada <xliff:g id="MODENAME">%1$s</xliff:g> je uključen"</string> <string name="wallet_title" msgid="5369767670735827105">"Novčanik"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Postavite aplikaciju za brže i sigurnije kupovine putem telefona"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Prikaži sve"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Saznajte više o pokretima na dodirnoj podlozi"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Krećite se pomoću tastature i dodirne podloge"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Saznajte više o pokretima na dodirnoj podlozi, prečicama tastature i drugim opcijama"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Pokret za povratak"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pokret za povratak na početni ekran"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Prikaži nedavne aplikacije"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazad"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Da se vratite, prevucite ulijevo ili udesno s tri prsta bilo gdje na dodirnoj podlozi.\n\nZa ovo možete koristiti i radnju za prečicu i Esc na tastaturi."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Sjajno!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Savladali ste pokret za vraćanje."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Odlazak na početni ekran"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Da odete na početni ekran bilo kada, prevucite s dna ekrana nagore s tri prsta."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Lijepo!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Savladali ste pokret za odlazak na početni ekran."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Prikaz nedavnih aplikacija"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Prevucite nagore i zadržite s tri prsta na dodirnoj podlozi."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Sjajno!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Izvršili ste pokret za prikaz nedavnih aplikacija."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tipka radnji"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Da pristupite aplikacijama, pritisnite tipku radnji na tastaturi."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Čestitamo!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Savladali ste pokret za tipku radnji.\n\nRadnja + / prikazuje sve prečice koje su vam dostupne."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvjetljenje tastature"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. nivo od %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrole za dom"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Da pregledate sve aplikacije, pritisnite tipku radnji na tastaturi"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redigovano"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Otključajte da pregledate"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstualno obrazovanje"</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> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index a0c0bf9defc8..1552c87fc181 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Activat"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Activat • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desactivat"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Configura"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gestiona a la configuració"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No hi ha cap mode actiu}=1{{mode} està actiu}many{Hi ha # de modes actius}other{Hi ha # modes actius}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Converses"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Esborra totes les notificacions silencioses"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificacions pausades pel mode No molestis"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{No hi ha cap notificació}=1{{mode} ha posat en pausa les notificacions}=2{{mode} i un altre mode han posat en pausa les notificacions}many{{mode} i # de modes més han posat en pausa les notificacions}other{{mode} i # modes més han posat en pausa les notificacions}}"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Comença ara"</string> <string name="empty_shade_text" msgid="8935967157319717412">"No hi ha cap notificació"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"No hi ha cap notificació nova"</string> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Mostra el mode de demostració"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"El mode <xliff:g id="MODENAME">%1$s</xliff:g> està activat"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configura una manera més ràpida i segura de fer compres amb el telèfon"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Mostra-ho tot"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Aprèn els gestos del ratolí tàctil"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navega amb el teclat i el ratolí tàctil"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Aprèn els gestos del ratolí tàctil, les tecles de drecera i més"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gest Enrere"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gest Inici"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Mostra les aplicacions recents"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fet"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Torna"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Per tornar enrere, llisca cap a l\'esquerra o cap a la dreta amb tres dits en qualsevol lloc del ratolí tàctil.\n\nTambé pots utilitzar les tecles d\'accions de drecera+Esc."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Ben fet!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Has completat el gest per tornar enrere."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ves a la pantalla d\'inici"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Per anar a la pantalla d\'inici en qualsevol moment, fes lliscar tres dits cap amunt des de la part inferior de la pantalla."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Molt bé!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Has completat el gest per anar a la pantalla d\'inici."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Mostra les aplicacions recents"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Llisca cap amunt amb tres dits i mantén premut al ratolí tàctil."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Ben fet!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Has completat el gest per veure les aplicacions recents."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tecla d\'acció"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Per accedir a les aplicacions, prem la tecla d\'acció al teclat."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Enhorabona!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Has completat el gest de la tecla d\'acció.\n\nTecla d\'acció+/ mostra totes les dreceres que tens disponibles."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroil·luminació del teclat"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivell %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Controls de la llar"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Per veure totes les aplicacions, prem la tecla d\'acció al teclat"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Emmascarat"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloqueja per veure"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Educació contextual"</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> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 107bac6b01a4..16895034b4f5 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Zapnuto"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Zapnuto • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Vypnuto"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Nastavit"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Spravovat v nastavení"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Žádné aktivní}=1{Režim {mode} je aktivní}few{# režimy jsou aktivní}many{# režimu je aktivních}other{# režimů je aktivních}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzace"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Vymazat všechna tichá oznámení"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Oznámení jsou pozastavena režimem Nerušit"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Žádná oznámení}=1{Oznámení jsou pozastavená režimem {mode}}=2{Oznámení jsou pozastavená režimem {mode} a 1 dalším}few{Oznámení jsou pozastavená režimem {mode} a # dalšími}many{Oznámení jsou pozastavená režimem {mode} a # dalšího}other{Oznámení jsou pozastavená režimem {mode} a # dalšími}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Zobrazit ukázkový režim"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Budík"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Je zapnutý režim <xliff:g id="MODENAME">%1$s</xliff:g>"</string> <string name="wallet_title" msgid="5369767670735827105">"Peněženka"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Nastavte si rychlejší a bezpečnější platby pomocí telefonu"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Zobrazit vše"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Naučte se gesta touchpadu"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigujte pomocí klávesnice a touchpadu"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Naučte se gesta touchpadu, klávesové zkratky a další"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto zpět"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto domů"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Zobrazit nedávné aplikace"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hotovo"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Zpět"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Pokud se chcete vrátit zpět, stačí kdekoli na touchpadu přejet třemi prsty doleva nebo doprava.\n\nMůžete také použít klávesovou zkratku Akce + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Výborně!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Dokončili jste gesto pro přechod zpět."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Přejít na plochu"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Na plochu přejdete kdykoli přejetím třemi prsty ze spodní části obrazovky nahoru."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Skvělé!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Dokončili jste gesto pro přechod na plochu."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Zobrazit nedávné aplikace"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Přejeďte po touchpadu třemi prsty nahoru a podržte je."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Výborně!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Provedli jste gesto pro zobrazení nedávných aplikací."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Akční klávesa"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Přístup k aplikacím získáte stisknutím akční klávesy na klávesnici."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Gratulujeme!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Dokončili jste gesto akční klávesy.\n\nAkce + / zobrazí všechny dostupné zkratky."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podsvícení klávesnice"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Úroveň %1$d z %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Ovládání domácnosti"</string> @@ -1436,6 +1449,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Odstraněno"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"K zobrazení je potřeba zařízení odemknout"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontextová výuka"</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> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 1ac75260f58d..729473c9450f 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Til"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Til • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Fra"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Konfigurer"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Administrer i indstillingerne"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Ingen aktive tilstande}=1{{mode} er aktiv}one{# tilstand er aktiv}other{# tilstande er aktive}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Samtaler"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Ryd alle lydløse notifikationer"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifikationer er sat på pause af Forstyr ikke"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Ingen notifikationer}=1{Notifikationer er sat på pause af {mode}}=2{Notifikationer er sat på pause af {mode} og én anden tilstand}one{Notifikationer er sat på pause af {mode} og # anden tilstand}other{Notifikationer er sat på pause af {mode} og # andre tilstande}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Vis Demotilstand"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> er aktiveret"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Bliv klar til at foretage hurtigere og mere sikre køb med din telefon"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Vis alle"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Se bevægelser på touchpladen"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Naviger ved hjælp af dit tastatur og din touchplade"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Se bevægelser på touchpladen, tastaturgenveje m.m."</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Bevægelse for at gå tilbage"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Bevægelse for at gå til startskærm"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Se seneste apps"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Udfør"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gå tilbage"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Du kan gå tilbage ved at stryge mod venstre eller højre med tre fingre et vilkårligt sted på touchpladen.\n\nDu kan også bruge tastaturgenvejen Alt + Esc."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Flot!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Du har fuldført bevægelsen for Gå tilbage."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Gå til startskærmen"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Du kan til enhver tid stryge opad med tre fingre fra bunden af skærmen, hvis du vil gå til startskærmen."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Sådan!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Du har fuldført bevægelsen for Gå til startskærmen."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Se seneste apps"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Stryg opad, og hold tre fingre på touchpladen."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Godt klaret!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Du har udført bevægelsen for at se de seneste apps."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Handlingstast"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Du kan tilgå alle dine apps ved at trykke på handlingstasten på dit tastatur."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Tillykke!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Du har fuldført bevægelsen for handlingstasten.\n\nHandling + / viser alle de tilgængelige genveje."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastaturets baggrundslys"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d af %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Hjemmestyring"</string> @@ -1436,6 +1449,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Skjult"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Lås op for at se"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstbaseret uddannelse"</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> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 8f5a705bc196..655b7a2345ca 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"An"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"An • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Aus"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Einrichten"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"In den Einstellungen verwalten"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Keine aktiven Modi}=1{{mode} aktiv}other{# aktiv}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Unterhaltungen"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Alle lautlosen Benachrichtigungen löschen"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Benachrichtigungen durch „Bitte nicht stören“ pausiert"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Keine Benachrichtigungen}=1{Benachrichtigungen durch {mode} pausiert}=2{Benachrichtigungen durch {mode} und einen weiteren Modus pausiert}other{Benachrichtigungen durch {mode} und # weitere Modi pausiert}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Demomodus anzeigen"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Weckruf"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Füge eine Zahlungsmethode hinzu, um noch schneller und sicherer mit deinem Smartphone zu bezahlen"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Alle anzeigen"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Informationen zu Touchpad-Gesten"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigation mit Tastatur und Touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Informationen zu Touchpad-Gesten, Tastenkombinationen und mehr"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Touch-Geste „Zurück“"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Touch-Geste „Startbildschirm“"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Letzte Apps aufrufen"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fertig"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Zurück"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Wenn du zurückgehen möchtest, wische an einer beliebigen Stelle des Touchpads mit drei Fingern nach links oder rechts.\n\nDu kannst stattdessen auch die Tastenkombination „Aktion“ + „ESC“ verwenden."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Gut gemacht!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Du hast den Schritt für die „Zurück“-Geste abgeschlossen."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Startbildschirm"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Du kannst jederzeit zum Startbildschirm gehen, indem du mit drei Fingern vom unteren Displayrand nach oben wischst."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Sehr gut!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Du hast den Schritt für die „Startbildschirm“-Geste abgeschlossen."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Letzte Apps aufrufen"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Wische mit 3 Fingern nach oben und halte das Touchpad gedrückt."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Gut gemacht!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Du hast das Tutorial für die Touch-Geste zum Aufrufen der zuletzt verwendeten Apps abgeschlossen."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Aktionstaste"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Wenn du auf deine Apps zugreifen möchtest, drücke auf der Tastatur die Aktionstaste."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Glückwunsch!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Du hast den Schritt für die „Aktionstaste“-Geste abgeschlossen.\n\nAktion + / zeigt alle verfügbaren Tastenkombinationen."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastaturbeleuchtung"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d von %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Smart-Home-Steuerung"</string> @@ -1436,6 +1450,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Entfernt"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Zum Ansehen entsperren"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontextbezogene Informationen"</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> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 183249bc3e16..3c99fbb3ce09 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Ενεργό"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Ενεργή • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Ανενεργό"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Ρύθμιση"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Συζητήσεις"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Διαγραφή όλων των ειδοποιήσεων σε σίγαση"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Οι ειδοποιήσεις τέθηκαν σε παύση από τη λειτουργία \"Μην ενοχλείτε\""</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Δεν υπάρχουν ειδοποιήσεις}=1{Οι ειδοποιήσεις τέθηκαν σε παύση από τη λειτουργία {mode}}=2{Οι ειδοποιήσεις τέθηκαν σε παύση από τη λειτουργία {mode} και μία άλλη λειτουργία}other{Οι ειδοποιήσεις τέθηκαν σε παύση από τη λειτουργία {mode} και # άλλες λειτουργίες}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Εμφάνιση λειτουργίας επίδειξης"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Ξυπνητήρι"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Η λειτουργία <xliff:g id="MODENAME">%1$s</xliff:g> είναι ενεργή"</string> <string name="wallet_title" msgid="5369767670735827105">"Πορτοφόλι"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Ολοκληρώστε τη ρύθμιση για να κάνετε πιο γρήγορες και πιο ασφαλείς αγορές με το τηλέφωνό σας"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Εμφάνιση όλων"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Μάθετε κινήσεις επιφάνειας αφής"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Πλοήγηση με το πληκτρολόγιο και την επιφάνεια αφής"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Μάθετε κινήσεις επιφάνειας αφής, συντομεύσεις πληκτρολογίου και άλλα"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Κίνηση επιστροφής"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Κίνηση μετάβασης στην αρχική οθόνη"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Προβολή πρόσφατων εφαρμογών"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Τέλος"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Επιστροφή"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Για να επιστρέψετε, σύρετε προς τα αριστερά ή προς τα δεξιά χρησιμοποιώντας τρία δάχτυλα σε οποιοδήποτε σημείο της επιφάνειας αφής.\n\nΜπορείτε επίσης να χρησιμοποιήσετε τη συντόμευση πληκτρολογίου Action + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Μπράβο!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ολοκληρώσατε την κίνηση επιστροφής."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Αρχική"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Για μετάβαση στην αρχική οθόνη ανά πάσα στιγμή, σύρετε προς τα επάνω με τρία δάχτυλα από το κάτω μέρος της οθόνης."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Ωραία!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Ολοκληρώσατε την κίνηση μετάβασης στην αρχική οθόνη."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Προβολή πρόσφατων εφαρμογών"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Σύρετε προς τα πάνω με τρία δάχτυλα στην επιφάνεια αφής και μην τα σηκώσετε."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Μπράβο!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Ολοκληρώσατε την κίνηση για την προβολή πρόσφατων εφαρμογών."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Πλήκτρο ενέργειας"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Για να αποκτήσετε πρόσβαση στις εφαρμογές σας, πατήστε το πλήκτρο ενέργειας στο πληκτρολόγιό σας."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Συγχαρητήρια!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Ολοκληρώσατε την κίνηση του κουμπιού ενέργειας.\n\nΗ ενέργεια + / εμφανίζει όλες τις διαθέσιμες συντομεύσεις."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Οπίσθιος φωτισμός πληκτρολογίου"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Επίπεδο %1$d από %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Οικιακοί έλεγχοι"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Για να δείτε όλες τις εφαρμογές, πιέστε το πλήκτρο ενέργειας στο πληκτρολόγιό σας"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Αποκρύφτηκε"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Ξεκλείδωμα για προβολή"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Εκπαίδευση με βάση τα συμφραζόμενα"</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> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 9b7ae5da01ed..4570c0a35eff 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"On • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Set up"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversations"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Clear all silent notifications"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifications paused by Do Not Disturb"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{No notifications}=1{Notifications paused by {mode}}=2{Notifications paused by {mode} and one other mode}other{Notifications paused by {mode} and # other modes}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Show demo mode"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> is on"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Get set up to make faster, more secure purchases with your phone"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Show all"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Learn touchpad gestures"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigate using your keyboard and touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Learn touchpad gestures, keyboards shortcuts and more"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"View recent apps"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"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> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Great work!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"You completed the go back gesture."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"To go to your home screen at any time, swipe up with three fingers from the bottom of your screen."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Nice!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"You completed the go home gesture."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"View recent apps"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Swipe up and hold using three fingers on your touchpad."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Well done!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Action key"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"To access your apps, press the action key on your keyboard."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Congratulations!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"You completed the action key gesture.\n\nAction + / shows all the shortcuts that you have available."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Home controls"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redacted"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Unlock to view"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Contextual education"</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> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 4fcc7a4eb550..3d33fa0b8400 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -440,7 +440,7 @@ <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"On • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</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_set_up" msgid="8231201163894922821">"Not set"</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> @@ -705,6 +705,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Show demo mode"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> is on"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Get set up to make faster, more secure purchases with your phone"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Show all"</string> @@ -1404,26 +1405,26 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Learn touchpad gestures"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigate using your keyboard and touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Learn touchpad gestures, keyboards shortcuts, and more"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string> + <string name="touchpad_tutorial_back_gesture_button" msgid="3104716365403620315">"Go back"</string> + <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Go home"</string> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"View recent apps"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"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> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Great job!"</string> + <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Swipe left or right using three fingers on your touchpad"</string> + <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Nice!"</string> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"You completed the go back gesture."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"To go to your home screen at any time, swipe up with three fingers from the bottom of your screen."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Nice!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"You completed the go home gesture."</string> + <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Swipe up with three fingers on your touchpad"</string> + <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Great job!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"You completed the go home gesture"</string> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"View recent apps"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Swipe up and hold using three fingers on your touchpad."</string> + <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Swipe up and hold using three fingers on your touchpad"</string> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Great job!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Action key"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"To access your apps, press the action key on your keyboard."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Congratulations!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"You completed the action key gesture.\n\nAction + / shows all the shortcuts you have available."</string> + <string name="tutorial_action_key_title" msgid="8172535792469008169">"View all apps"</string> + <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Press the action key on your keyboard"</string> + <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Well done!"</string> + <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"You completed the view all apps gesture"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Home Controls"</string> @@ -1435,6 +1436,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redacted"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Unlock to view"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Contextual education"</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> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index cea405b7d18d..4570c0a35eff 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"On • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Set up"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -705,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Show demo mode"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> is on"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Get set up to make faster, more secure purchases with your phone"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Show all"</string> @@ -1404,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Learn touchpad gestures"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigate using your keyboard and touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Learn touchpad gestures, keyboards shortcuts and more"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"View recent apps"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"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> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Great work!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"You completed the go back gesture."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"To go to your home screen at any time, swipe up with three fingers from the bottom of your screen."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Nice!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"You completed the go home gesture."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"View recent apps"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Swipe up and hold using three fingers on your touchpad."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Well done!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Action key"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"To access your apps, press the action key on your keyboard."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Congratulations!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"You completed the action key gesture.\n\nAction + / shows all the shortcuts that you have available."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Home controls"</string> @@ -1435,8 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redacted"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Unlock to view"</string> - <!-- no translation found for contextual_education_dialog_title (4630392552837487324) --> - <skip /> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Contextual education"</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> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 9b7ae5da01ed..4570c0a35eff 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"On • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Set up"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversations"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Clear all silent notifications"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifications paused by Do Not Disturb"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{No notifications}=1{Notifications paused by {mode}}=2{Notifications paused by {mode} and one other mode}other{Notifications paused by {mode} and # other modes}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Show demo mode"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> is on"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Get set up to make faster, more secure purchases with your phone"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Show all"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Learn touchpad gestures"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigate using your keyboard and touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Learn touchpad gestures, keyboards shortcuts and more"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"View recent apps"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"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> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Great work!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"You completed the go back gesture."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"To go to your home screen at any time, swipe up with three fingers from the bottom of your screen."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Nice!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"You completed the go home gesture."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"View recent apps"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Swipe up and hold using three fingers on your touchpad."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Well done!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Action key"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"To access your apps, press the action key on your keyboard."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Congratulations!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"You completed the action key gesture.\n\nAction + / shows all the shortcuts that you have available."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Home controls"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redacted"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Unlock to view"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Contextual education"</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> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 3c22ed163d31..3d157c7b7648 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -440,7 +440,7 @@ <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"On • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</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_set_up" msgid="8231201163894922821">"Not set"</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> @@ -705,6 +705,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Show demo mode"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> is on"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Get set up to make faster, more secure purchases with your phone"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Show all"</string> @@ -1404,26 +1405,26 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Learn touchpad gestures"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigate using your keyboard and touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Learn touchpad gestures, keyboards shortcuts, and more"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string> + <string name="touchpad_tutorial_back_gesture_button" msgid="3104716365403620315">"Go back"</string> + <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Go home"</string> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"View recent apps"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"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> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Great job!"</string> + <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Swipe left or right using three fingers on your touchpad"</string> + <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Nice!"</string> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"You completed the go back gesture."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"To go to your home screen at any time, swipe up with three fingers from the bottom of your screen."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Nice!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"You completed the go home gesture."</string> + <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Swipe up with three fingers on your touchpad"</string> + <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Great job!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"You completed the go home gesture"</string> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"View recent apps"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Swipe up and hold using three fingers on your touchpad."</string> + <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Swipe up and hold using three fingers on your touchpad"</string> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Great job!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Action key"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"To access your apps, press the action key on your keyboard."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Congratulations!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"You completed the action key gesture.\n\nAction + / shows all the shortcuts you have available."</string> + <string name="tutorial_action_key_title" msgid="8172535792469008169">"View all apps"</string> + <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Press the action key on your keyboard"</string> + <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Well done!"</string> + <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"You completed the view all apps gesture"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Home Controls"</string> @@ -1435,6 +1436,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"To view all your apps, press the action key on your keyboard"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redacted"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Unlock to view"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Contextual education"</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> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 88cedcf8f1d1..6c80a2c81954 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Sí • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desactivado"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurar"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Administrar en configuración"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No hay modos activos}=1{{mode} está activo}many{# de modos están activos}other{# modos están activos}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversaciones"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Borrar todas las notificaciones silenciosas"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificaciones pausadas por el modo \"No interrumpir\""</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{No hay notificaciones}=1{{mode} pausó las notificaciones}=2{{mode} y un modo más pausaron las notificaciones}many{{mode} y # de modos más pausaron las notificaciones}other{{mode} y # modos más pausaron las notificaciones}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Ver en modo de demostración"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> activado"</string> <string name="wallet_title" msgid="5369767670735827105">"Billetera"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Prepárate para realizar compras rápidas y seguras con tu teléfono"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar todo"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Aprende los gestos del panel táctil"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navega con el teclado y el panel táctil"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Aprende sobre los gestos del panel táctil, las combinaciones de teclas y mucho más"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto atrás"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto para ir a la pantalla principal"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ver apps recientes"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Listo"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atrás"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para volver, desliza tres dedos hacia la derecha o la izquierda en cualquier lugar del panel táctil.\n\nPara completar esta acción, también puedes usar la combinación de teclas Action + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"¡Bien hecho!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Completaste el gesto para ir atrás."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir a la página principal"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para ir a la pantalla principal en cualquier momento, desliza hacia arriba desde la parte inferior de la pantalla con tres dedos."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"¡Muy bien!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Completaste el gesto para ir al inicio."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ver apps recientes"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Desliza hacia arriba con tres dedos en el panel táctil y mantenlos presionados."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"¡Bien hecho!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Completaste el gesto para ver las apps recientes."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tecla de acción"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Para acceder a las apps, presiona la tecla de acción en el teclado."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"¡Felicitaciones!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Completaste el gesto de la tecla de acción.\n\nSi presionas las teclas Acción + /, se muestran todas las combinaciones de teclas disponibles."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación del teclado"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivel %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Controles de la casa"</string> @@ -1436,6 +1449,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Oculto"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloquea el dispositivo para ver"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Educación contextual"</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> @@ -1445,7 +1459,7 @@ <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> <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"La atenuación extra ahora es parte del control deslizante de brillo"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Ahora puedes bajar el nivel del brillo de la pantalla para atenuarla aún más.\n\nComo esta función ahora es parte del control deslizante de brillo, se quitaron los accesos directos de atenuación extra."</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Ahora puedes bajar el nivel del brillo de la pantalla para atenuarla aún más.\n\nComo esta función ahora es parte del control deslizante de brillo, se quitaron los accesos directos a la atenuación extra."</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"Quitar accesos directos a la atenuación extra"</string> <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"Se quitaron los accesos directos a la atenuación extra"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Conectividad"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 63f4ae11a7f6..f77119e3b90a 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Activado • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desactivado"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurar"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gestionar en los ajustes"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{No hay modos activos}=1{{mode} está activo}many{Hay # modos activos}other{Hay # modos activos}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversaciones"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Borrar todas las notificaciones silenciosas"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificaciones pausadas por el modo No molestar"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{No hay notificaciones}=1{Notificaciones pausadas por {mode}}=2{Notificaciones pausadas por {mode} y un modo más}many{Notificaciones pausadas por {mode} y # modos más}other{Notificaciones pausadas por {mode} y # modos más}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Mostrar modo Demo"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> activado"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configura un método de pago para comprar de forma más rápida y segura con tu teléfono"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar todo"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Aprende gestos del panel táctil"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Desplázate con el teclado y el panel táctil"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Aprende gestos del panel táctil, combinaciones de teclas y más"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto para volver"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto para ir al inicio"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ver aplicaciones recientes"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hecho"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atrás"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para volver, desliza con tres dedos hacia la izquierda o la derecha en cualquier parte del panel táctil.\n\nTambién puedes hacerlo con la combinación de teclas asignada + Esc."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"¡Bien hecho!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Has completado el gesto para volver."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir a Inicio"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para ir a la pantalla de inicio en cualquier momento, desliza hacia arriba con tres dedos desde la parte inferior de la pantalla."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"¡Muy bien!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Has completado el gesto para ir a la pantalla de inicio."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ver aplicaciones recientes"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Desliza tres dedos hacia arriba y mantén pulsado en el panel táctil."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"¡Bien hecho!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Has completado el gesto para ver las aplicaciones recientes."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tecla de acción"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Para acceder a tus aplicaciones, pulsa la tecla de acción de tu teclado."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"¡Enhorabuena!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Has completado el gesto de la tecla de acción.\n\nLa combinación de teclas Acción + / muestra todas las combinaciones de teclas que tienes disponibles."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación del teclado"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivel %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Controles de la casa"</string> @@ -1436,6 +1449,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Oculta"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloquea para ver"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Educación contextual"</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> @@ -1445,7 +1459,7 @@ <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> <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"La atenuación extra ahora forma parte del control deslizante de brillo"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Ahora puedes atenuar aún más tu pantalla reduciendo el nivel de brillo incluso más todavía.\n\nComo esta función ahora forma parte del control deslizante de brillo, se van a quitar los accesos directos de atenuación extra."</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Ahora puedes atenuar aún más tu pantalla reduciendo el nivel de brillo.\n\nComo esta función ahora forma parte del control deslizante de brillo, se van a quitar los accesos directos de atenuación extra."</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"Eliminar accesos directos de atenuación extra"</string> <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"Accesos directos de atenuación extra eliminados"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Conectividad"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 35d40120c802..3323a3f157db 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Sees"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Sees • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Väljas"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Seadistamine"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Seadetes halamine"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Aktiivsed režiimid puuduvad}=1{{mode} on aktiivne}other{# režiimi on aktiivsed}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Vestlused"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Kustuta kõik hääletud märguanded"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Režiim Mitte segada peatas märguanded"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Märguandeid pole}=1{{mode} peatas märguanded}=2{{mode} ja veel üks režiim peatasid märguanded}other{{mode} ja veel # režiimi peatasid märguanded}}"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Alusta kohe"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Märguandeid pole"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Uusi märguandeid ei ole"</string> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Kuva demorežiim"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Äratus"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> on sisse lülitatud"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Seadistage kiirem ja turvalisem viis telefoniga ostmiseks"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Kuva kõik"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Õppige puuteplaadi liigutusi"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigeerige klaviatuuri ja puuteplaadi abil"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Õppige puuteplaadi liigutusi, klaviatuuri otseteid ja palju muud"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Tagasiliikumisliigutus"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Avakuvale liikumise liigutus"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Hiljutiste rakenduste vaatamine"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Valmis"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Tagasi"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Tagasiliikumiseks pühkige puuteplaadil kolme sõrmega vasakule või paremale.\n\nSamuti saate selle jaoks kasutada klaviatuuri otseteed toiminguklahv + paoklahv."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Väga hea!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Tegite tagasiliikumise liigutuse."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Avalehele"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Mis tahes ajal avakuvale liikumiseks pühkige kolme sõrmega ekraanikuva allosast üles."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Hästi tehtud!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Tegite avakuvale minemise liigutuse."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Hiljutiste rakenduste vaatamine"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Pühkige üles ja hoidke kolme sõrmega puuteplaadil."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Väga hea!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Lõpetasite hiljutiste rakenduste vaatamise liigutuse."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Toiminguklahv"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Rakendustele juurdepääsemiseks vajutage klaviatuuril toiminguklahvi."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Õnnitleme!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Tegite toiminguklahvi liigutuse.\n\nKombinatsiooni toiminguklahv + / vajutamisel kuvatakse kõik saadaolevad otseteed."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatuuri taustavalgustus"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Tase %1$d/%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kodu juhtelemendid"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Kõigi oma rakenduste kuvamiseks vajutage klaviatuuril toiminguklahvi"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Peidetud"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Vaatamiseks avage"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstipõhised õpetused"</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> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 7e0f203d0b0b..246c23085159 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Aktibatuta"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Aktibo • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desaktibatuta"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Konfiguratu"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Kudeatu ezarpenetan"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Ez dago modurik aktibo}=1{\"{mode}\" aktibo dago}other{# modu aktibo daude}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Elkarrizketak"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Garbitu soinurik gabeko jakinarazpen guztiak"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Ez molestatzeko moduak pausatu egin ditu jakinarazpenak"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Ez dago jakinarazpenik}=1{Modu honek jakinarazpenak pausatu ditu: {mode}}=2{Modu honek eta beste modu batek jakinarazpenak pausatu dituzte: {mode}}other{Modu honek eta beste # moduk jakinarazpenak pausatu dituzte: {mode}}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Erakutsi demo modua"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Diru-zorroa"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Konfiguratu erosketa bizkorrago eta seguruagoak egiteko telefonoarekin"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Erakutsi guztiak"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Ikasi ukipen-paneleko keinuak"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Nabigatu teklatua eta ukipen-panela erabilita"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Ikasi ukipen-paneleko keinuak, lasterbideak eta abar"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Atzera egiteko keinua"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Orri nagusira joateko keinua"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ikusi azkenaldiko aplikazioak"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Eginda"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Egin atzera"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Atzera egiteko, pasatu 3 hatz ezkerrera edo eskuinera ukipen-panelean.\n\nEkintza + Ihes lasterbidea ere erabil dezakezu horretarako."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Bikain!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ikasi duzu atzera egiteko keinua."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Joan orri nagusira"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Orri nagusira joateko, pasatu 3 hatz pantailaren behealdetik gora."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Ederki!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Ikasi duzu hasierako pantailara joateko keinua."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ikusi azkenaldiko aplikazioak"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Pasatu 3 hatz gora eta eduki sakatuta ukipen-panelean."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Bikain!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Osatu duzu azkenaldiko aplikazioak ikusteko keinua."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Ekintza-tekla"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Aplikazioak atzitzeko, sakatu teklatuko ekintza-tekla."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Zorionak!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Ekintza-teklaren keinua egin duzu.\n\nEkintza + / sakatuz gero, erabilgarri dituzun lasterbide guztiak ikusiko dituzu."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Teklatuaren hondoko argia"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d/%2$d maila"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Etxeko gailuen kontrola"</string> @@ -1436,6 +1450,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Aplikazio guztiak ikusteko, sakatu teklatuko ekintza-tekla"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Desitxuratuta"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desblokeatu ikusteko"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Testuinguruaren araberako hezkuntza"</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> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index e70d2bb1ba95..29a2739dd74f 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"روشن"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"روشن • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"خاموش"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"راهاندازی"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"مکالمهها"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"پاک کردن همه اعلانهای بیصدا"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"اعلانها توسط «مزاحم نشوید» موقتاً متوقف شدند"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{اعلانی موقتاً متوقف نشده است}=1{اعلانها را «{mode}» موقتاً متوقف کرده است}=2{اعلانها را «{mode}» و یک حالت دیگر موقتاً متوقف کرداند}one{اعلانها را «{mode}» و # حالت دیگر موقتاً متوقف کردهاند}other{اعلانها را «{mode}» و # حالت دیگر موقتاً متوقف کردهاند}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> روشن است"</string> <string name="wallet_title" msgid="5369767670735827105">"کیف پول"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"برای خرید سریعتر و امنتر با تلفن، راهاندازی کنید"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"نمایش همه"</string> @@ -1178,7 +1179,7 @@ <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"توقف پخش محتوا"</string> <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"دستگاههای دردسترس برای خروجی صوتی."</string> <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"میزان صدا"</string> - <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string> + <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"%%<xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string> <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"بلندگوها و نمایشگرها"</string> <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"دستگاههای پیشنهادی"</string> <string name="media_input_group_title" msgid="2057057473860783021">"ورودی"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"آشنایی با اشارههای صفحه لمسی"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"پیمایش کردن بااستفاده از صفحهکلید و صفحه لمسی"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"آشنایی با اشارههای صفحه لمسی، میانبرهای صفحهکلید، و موارد دیگر"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"اشاره برگشت"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"اشاره صفحه اصلی"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"مشاهده کردن برنامههای اخیر"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"تمام"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"برگشتن"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"برای برگشتن، در هر جایی از صفحه لمسی، با سه انگشت تند بهچپ یا راست بکشید.\n\nبرای این کار میتوانید از میانبر صفحهکلید «کنش + گریز» هم استفاده کنید."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"عالی بود!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"اشاره برگشت را تکمیل کردید."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"رفتن به صفحه اصلی"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"برای رفتن به صفحه اصلی در هرزمانی، با سه انگشت از پایین صفحهنمایش تند بهبالا بکشید."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"آفرین!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"اشاره رفتن به صفحه اصلی را تکمیل کردید."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"مشاهده کردن برنامههای اخیر"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"با سه انگشت روی صفحه لمسی تند بهبالا بکشید و نگه دارید."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"عالی است!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"اشاره مشاهده برنامههای اخیر را انجام دادید"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"دکمه کنش"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"برای دسترسی به برنامههایتان، دکمه کنش در صفحهکلید را فشار دهید."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"تبریک!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"اشاره دکمه کنش را تکمیل کردید.\n\n«کنش» + / همه میانبرهای دردسترس را نمایش میدهد."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"نور پسزمینه صفحهکلید"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"سطح %1$d از %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"کنترل خانه هوشمند"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"برای مشاهده همه برنامهها، دکمه کنش در صفحهکلید را فشار دهید"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"محوشده"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"برای مشاهده، قفل را باز کنید"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"آموزش زمینهای"</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> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index f6d43c1a91d1..e93ac1a51f72 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Päällä"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Päällä • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Pois päältä"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Ota käyttöön"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Muuta asetuksista"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Ei aktiivisia tiloja}=1{{mode} on aktiivinen}other{# tilaa on aktiivisena}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Keskustelut"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Tyhjennä kaikki hiljaiset ilmoitukset"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Älä häiritse ‑tila keskeytti ilmoitukset"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Ei ilmoituksia}=1{{mode} keskeytti ilmoitukset}=2{{mode} ja yksi muu tila keskeytti ilmoitukset}other{{mode} ja # muuta tilaa keskeytti ilmoitukset}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Näytä esittelytila"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Herätys"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> on päällä"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Lisää maksutapa, niin voit maksaa nopeasti ja turvallisesti puhelimella"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Näytä kaikki"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Opettele kosketuslevyn eleitä"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Siirry käyttämällä näppäimistöä ja kosketuslevyä"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Opettele kosketuslevyn eleitä, pikanäppäimiä ja muuta"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Takaisin-ele"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Etusivu-ele"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Katso viimeisimmät sovellukset"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Valmis"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Takaisin"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Jos haluat siirtyä takaisin, pyyhkäise kosketuslevyllä vasemmalle tai oikealle kolmella sormella.\n\nVoit myös käyttää pikanäppäinyhdistelmää toimintonäppäin + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Hienoa!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Olet oppinut Takaisin-eleen."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Siirry etusivulle"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Voit siirtyä aloitusnäytölle milloin tahansa pyyhkäisemällä ylös näytön alareunasta kolmella sormella."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Hienoa!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Olet oppinut aloitusnäytölle palaamiseleen."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Katso viimeisimmät sovellukset"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Pyyhkäise ylös ja pidä kosketuslevyä painettuna kolmella sormella."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Hienoa!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Olet oppinut Katso viimeisimmät sovellukset ‑eleen."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Toimintonäppäin"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Voit käyttää sovelluksia painamalla näppäimistön toimintonäppäintä."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Onnittelut!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Olet oppinut toimintonäppäineleen.\n\nToiminto + / tuo esiin kaikki käytettävissä olevat pikakomennot."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Näppämistön taustavalo"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Taso %1$d/%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kodin ohjaus"</string> @@ -1436,6 +1449,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Sensuroitu"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Avaa lukitus ja katso tiedot"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstuaalinen koulutus"</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> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 1f6de9f6a4b1..c58ad93b8f07 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Activé"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Activé • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Désactivé"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurer"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gérer dans les paramètres"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Aucun mode actif}=1{Le mode {mode} est actif}one{# mode est actif}many{# de modes sont actifs}other{# modes sont actifs}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversations"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Effacer toutes les notifications silencieuses"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Les notifications sont suspendues par le mode Ne pas déranger"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Aucune notification}=1{Notifications suspendues par {mode}}=2{Notifications suspendues par {mode} et un autre mode}one{Notifications suspendues par {mode} et # autre mode}many{Notifications suspendues par {mode} et # d\'autres modes}other{Notifications suspendues par {mode} et # autres modes}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Afficher le mode Démo"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Préparez-vous à faire des achats plus rapidement et de façon plus sûre avec votre téléphone"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Tout afficher"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Apprenez à utiliser les gestes du pavé tactile"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Naviguer à l\'aide de votre clavier et de votre pavé tactile"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Apprenez les gestes du pavé tactile, les raccourcis-clavier et bien plus encore"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Geste de retour"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Geste d\'accès à l\'écran d\'accueil"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Afficher les applis récentes"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"OK"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Retour"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Pour revenir en arrière, balayez vers la gauche ou la droite en utilisant trois doigts n\'importe où sur le pavé tactile.\n\nVous pouvez également utiliser le raccourci clavier Action+Échap."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Bon travail!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Vous avez appris le geste de retour en arrière."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Retour à la page d\'accueil"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Pour accéder à votre écran d\'accueil à tout moment, balayez l\'écran du bas vers le haut avec trois doigts."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Bien!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Vous avez appris le geste de retour à l\'écran d\'accueil."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Afficher les applis récentes"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Balayez l\'écran vers le haut avec trois doigts et maintenez-les en place sur votre pavé tactile."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Bon travail!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Vous avez effectué le geste pour afficher les applis récentes."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Touche d\'action"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Pour accéder à vos applis, appuyez sur la touche d\'action de votre clavier."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Félicitations!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Vous avez terminé le geste de la touche d\'action.\n\nAction + / affiche tous les raccourcis dont vous disposez."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Rétroéclairage du clavier"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Domotique"</string> @@ -1436,6 +1450,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Supprimé"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Déverrouiller pour afficher"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Enseignement contextuel"</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> @@ -1445,7 +1460,7 @@ <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> <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"La réduction supplémentaire de la luminosité fait désormais partie du curseur de luminosité"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Vous pouvez désormais réduire la luminosité de l\'écran encore plus.\n\nÉtant donné que cette fonctionnalité fait désormais partie du curseur de luminosité, les raccourcis de la réduction supplémentaire de la luminosité sont retirés."</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Vous pouvez désormais réduire la luminosité de l\'écran encore plus.\n\nÉtant donné que cette fonctionnalité fait maintenant partie du curseur de luminosité, les raccourcis de la réduction supplémentaire de la luminosité sont retirés."</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"Retirer les raccourcis de la réduction supplémentaire de la luminosité"</string> <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"Les raccourcis de la réduction supplémentaire de la luminosité ont été retirés"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Connectivité"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index fbf5a6c7aced..cf1cae9dad04 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -197,7 +197,7 @@ <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Authentifié"</string> <string name="biometric_dialog_cancel_authentication" msgid="981316588773442637">"Annuler l\'authentification"</string> <string name="biometric_dialog_content_view_more_options_button" msgid="2663810393874865475">"Plus d\'options"</string> - <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utiliser un code PIN"</string> + <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Utiliser un code"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utiliser un schéma"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Utiliser un mot de passe"</string> <string name="biometric_dialog_wrong_pin" msgid="1878539073972762803">"Code incorrect"</string> @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Activé"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Activé • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Désactivé"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurer"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gérer dans les paramètres"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Aucun mode actif}=1{{mode} est actif}one{# mode est actif}many{# de modes sont actifs}other{# modes sont actifs}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversations"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Effacer toutes les notifications silencieuses"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifications suspendues par le mode Ne pas déranger"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Aucune notification}=1{Notifications suspendues par le mode {mode}}=2{Notifications suspendues par le mode {mode} et un autre mode}one{Notifications suspendues par le mode {mode} et # autre mode}many{Notifications suspendues par le mode {mode} et # d\'autres modes}other{Notifications suspendues par le mode {mode} et # autres modes}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Afficher le mode de démonstration"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Mode <xliff:g id="MODENAME">%1$s</xliff:g> activé"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configurez un mode de paiement pour régler vos achats de façon sûre et rapide via votre téléphone"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Tout afficher"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Découvrir les gestes au pavé tactile"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Naviguer à l\'aide de votre clavier et de votre pavé tactile"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Découvrir les gestes au pavé tactile, les raccourcis clavier et plus encore"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Geste Retour"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Geste Accueil"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Afficher les applis récentes"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"OK"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Retour"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Pour revenir en arrière, balayez vers la gauche ou vers la droite avec trois doigts n\'importe où sur le pavé tactile.\n\nVous pouvez aussi utiliser le raccourci clavier Action+Échap pour cela."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Bravo !"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Vous avez appris le geste pour revenir en arrière."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Retour à l\'accueil"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Pour accéder à l\'écran d\'accueil à tout moment, balayez l\'écran du bas vers le haut avec trois doigts."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Bravo !"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Vous avez appris le geste pour revenir à l\'écran d\'accueil."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Afficher les applis récentes"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Avec trois doigts, balayez le pavé tactile vers le haut et maintenez la position."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Bravo !"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Vous avez appris le geste pour afficher les applis récentes"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Touche d\'action"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Pour accéder à vos applis, appuyez sur la touche d\'action de votre clavier."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Félicitations !"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Vous avez appris le geste permettant d\'utiliser la touche d\'action.\n\nAction+/ affiche tous les raccourcis disponibles."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Rétroéclairage du clavier"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d sur %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Contrôle de la maison"</string> @@ -1436,6 +1449,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Masqué"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Déverrouiller pour afficher"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Éducation contextuelle"</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> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index b9d0891b99fa..dc0f216ef4db 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Activo • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desactivado"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurar"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Xestionar na configuración"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Non hai ningún modo activo}=1{{mode} está activo}other{Hai # modos activos}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversas"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Borrar todas as notificacións silenciadas"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"O modo Non molestar puxo en pausa as notificacións"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Non hai ningunha notificación}=1{Notificacións postas en pausa polo modo {mode}}=2{Notificacións postas en pausa polo modo {mode} e un máis}other{Notificacións postas en pausa polo modo {mode} e # máis}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Mostrar modo de demostración"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarma"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> activado"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configura un método de pago para comprar de xeito máis rápido e seguro co teléfono"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Amosar todo"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Aprende a usar os xestos do panel táctil"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navega co teclado e o panel táctil"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Aprende a usar os xestos do panel táctil, atallos de teclado e moito máis"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Xesto para volver"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Xesto para ir ao inicio"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Consultar aplicacións recentes"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Feito"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Volver"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para retroceder, pasa tres dedos cara á esquerda ou cara á dereita en calquera parte do panel táctil.\n\nTamén podes usar o atallo de teclado Acción + Escape."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Moi ben!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Completaches o xesto de retroceso."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir ao inicio"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para ir á pantalla de inicio, pasa tres dedos cara arriba desde a parte inferior da pantalla."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Excelente!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Completaches o xesto de ir ao inicio."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Consultar aplicacións recentes"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Pasa tres dedos cara arriba e mantenos premidos no panel táctil."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Moi ben!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Completaches o titorial do xesto de consultar aplicacións recentes."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tecla de acción"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Para acceder ás aplicacións, preme a tecla de acción do teclado."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Parabéns!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Completaches o xesto da tecla de acción.\n\nAcción + / mostra todos os atallos que tes á túa disposición."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación do teclado"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivel %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Controis domóticos"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todas as aplicacións, preme a tecla de acción do teclado"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Contido ocultado"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloquea o dispositivo para ver o contido"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Información contextual"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Usa o panel táctil para volver"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Pasa tres dedos cara á esquerda ou cara á dereita. Toca para obter máis información sobre os xestos."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Usa o panel táctil para volver ao inicio"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index e9998e448595..866535e20489 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"ચાલુ"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"ચાલુ • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"બંધ"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"સેટઅપ કરો"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"વાતચીત"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"બધા સાઇલન્ટ નોટિફિકેશન સાફ કરો"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"ખલેલ પાડશો નહીં દ્વારા થોભાવેલ નોટિફિકેશન"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{કોઈ નોટિફિકેશન નથી}=1{{mode} દ્વારા નોટિફિકેશન થોભાવવામાં આવ્યા}=2{{mode} અને અન્ય એક મોડ દ્વારા નોટિફિકેશન થોભાવવામાં આવ્યા}one{{mode} અને અન્ય # મોડ દ્વારા નોટિફિકેશન થોભાવવામાં આવ્યા}other{{mode} અને અન્ય # મોડ દ્વારા નોટિફિકેશન થોભાવવામાં આવ્યા}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> ચાલુ છે"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"તમારા ફોન વડે વધુ ઝડપી તેમજ સુરક્ષિત ખરીદીઓ કરવાની રીત સેટઅપ કરી લો"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"બધું બતાવો"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"ટચપૅડના સંકેતો વિશે જાણો"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"તમારા કીબોર્ડ અને ટચપૅડ વડે નૅવિગેટ કરો"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"ટચપૅડના સંકેતો અને કીબોર્ડના શૉર્ટકટ જેવું બીજું ઘણું જાણો"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"પાછળ જવાનો સંકેત"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"હોમ સ્ક્રીન પર જવાનો સંકેત"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"તાજેતરની ઍપ જુઓ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"થઈ ગયું"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"પાછા જાઓ"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"પાછા જવા માટે, ટચપૅડ પર ગમે ત્યાં ત્રણ આંગળી વડે ડાબે અથવા જમણે સ્વાઇપ કરો.\n\nઆના માટે તમે કીબોર્ડ શૉર્ટકટ Action + ESCનો ઉપયોગ કરી શકો છો."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"ખૂબ સરસ કામ!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"તમે પાછા જવાનો સંકેત પૂર્ણ કર્યો છે."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"હોમ પર જાઓ"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"કોઈપણ સમયે તમારી હોમ સ્ક્રીન પર જવા માટે, ત્રણ આંગળી વડે તમારી સ્ક્રીનની સૌથી નીચેની બાજુએથી ઉપરની તરફ સ્વાઇપ કરો."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"સરસ!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"તમે હોમ સ્ક્રીન પર જવાનો સંકેત પૂર્ણ કર્યો છે."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"તાજેતરની ઍપ જુઓ"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"તમારા ટચપૅડ પર ત્રણ આંગળીઓનો ઉપયોગ કરીને ઉપર સ્વાઇપ કરો અને દબાવી રાખો."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ખૂબ સરસ કામ!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"તમે \"તાજેતરની ઍપ જુઓ\" સંકેત પૂર્ણ કર્યો."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"ઍક્શન કી"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"તમારી ઍપ ઍક્સેસ કરવા માટે, તમારા કીબોર્ડ પરની ઍક્શન કી દબાવો."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"અભિનંદન!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"તમે ઍક્શન કીનો સંકેત પૂર્ણ કર્યો છે.\n\nઍક્શન કી + /ને દબાવવાથી, તમારી પાસે ઉપલબ્ધ હોય તે બધા શૉર્ટકટ જોવા મળે છે."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"કીબોર્ડની બૅકલાઇટ"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dમાંથી %1$d લેવલ"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ઘરેલું સાધનોના નિયંત્રણો"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"તમારી બધી ઍપ જોવા માટે, તમારા કીબોર્ડ પર ઍક્શન કી દબાવો"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"બદલાવેલું"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"જોવા માટે અનલૉક કરો"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"સંદર્ભાત્મક શિક્ષણ"</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> @@ -1444,7 +1458,7 @@ <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> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"બ્રાઇટનેસ સ્લાઇડર હવે એક્સ્ટ્રા ડિમનો ભાગ છે"</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"એક્સ્ટ્રા ડિમ હવે બ્રાઇટનેસ સ્લાઇડરનો ભાગ છે"</string> <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"તમે હવે બ્રાઇટનેસ લેવલને હજી પણ ઘટાડીને સ્ક્રીનને એક્સ્ટ્રા ડિમ બનાવી શકો છો.\n\nઆ સુવિધા હવે બ્રાઇટનેસ સ્લાઇડરનો ભાગ હોવાથી એક્સ્ટ્રા ડિમ શૉર્ટકટને કાઢી નાખવામાં આવી રહ્યાં છે."</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"એક્સ્ટ્રા ડિમ શૉર્ટકટ કાઢી નાખો"</string> <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"એક્સ્ટ્રા ડિમ શૉર્ટકટ કાઢી નાખ્યા"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 534da68f0286..7a1bf83a101e 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"चालू है"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"<xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g> • पर"</string> <string name="zen_mode_off" msgid="1736604456618147306">"बंद है"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"सेट अप करें"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"बातचीत"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"बिना आवाज़ की सभी सूचनाएं हटाएं"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'परेशान न करें\' सुविधा के ज़रिए कुछ समय के लिए सूचनाएं दिखाना रोक दिया गया है"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{कोई सूचना नहीं है}=1{{mode} की वजह से सूचना नहीं दिख रही है}=2{{mode} और एक अन्य मोड की वजह से सूचना नहीं दिख रही है}one{{mode} और # अन्य मोड की वजह से सूचना नहीं दिख रही है}other{{mode} और # अन्य मोड के की वजह से सूचनाएं नहीं दिख रही है}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> चालू है"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"फ़ोन के ज़रिए तेज़ी से और सुरक्षित तरीके से खरीदारी करने के लिए सेट अप करें"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"सभी दिखाएं"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"टचपैड पर हाथ के जेस्चर के बारे में जानें"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"कीबोर्ड और टचपैड का इस्तेमाल करके नेविगेट करें"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"टचपैड पर हाथ के जेस्चर, कीबोर्ड शॉर्टकट वगैरह के बारे में जानें"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"पीछे जाने का जेस्चर"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"होम स्क्रीन पर जाने का जेस्चर"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन देखें"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"हो गया"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"वापस जाएं"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"वापस जाने के लिए, टचपैड पर कहीं भी तीन उंगलियों से दाईं या बाईं ओर स्वाइप करें.\n\nइसके अलावा, ऐसा करने के लिए Action + ESC बटन का भी इस्तेमाल किया जा सकता है."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"बहुत बढ़िया!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"अब आपने जान लिया है कि हाथ का जेस्चर इस्तेमाल करके, पिछली स्क्रीन पर वापस कैसे जाएं."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"होम स्क्रीन पर जाएं"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"किसी भी समय फ़ोन की होम स्क्रीन पर जाने के लिए, तीन उंगलियों से फ़ोन पर सबसे नीचे से ऊपर की ओर स्वाइप करें."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"बढ़िया!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"आपने जान लिया कि हाथ का जेस्चर इस्तेमाल करके, होम स्क्रीन पर कैसे जाएं."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन देखें"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"अपने टचपैड पर तीन उंगलियों से ऊपर की ओर स्वाइप करें और फिर होल्ड करें."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"बहुत बढ़िया!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"आपने हाल ही में इस्तेमाल किए गए ऐप्लिकेशन देखने के लिए, हाथ के जेस्चर के बारे में जान लिया है."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"ऐक्शन बटन"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"अपने ऐप्लिकेशन ऐक्सेस करने के लिए, कीबोर्ड पर ऐक्शन बटन दबाएं."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"बधाई हो!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"आपने ऐक्शन बटन का जेस्चर इस्तेमाल करने की प्रोसेस पूरी कर ली है.\n\nऐक्शन बटन और / को साथ में दबाने पर, आपके पास उपलब्ध सभी शॉर्टकट दिखते हैं."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"कीबोर्ड की बैकलाइट"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d में से %1$d लेवल"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"होम कंट्रोल"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"सभी ऐप्लिकेशन देखने के लिए, कीबोर्ड पर ऐक्शन बटन दबाएं"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"जानकारी छिपाने के लिए सूचना में बदलाव किया गया"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"देखने के लिए डिवाइस अनलॉक करें"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"कॉन्टेक्स्ट के हिसाब से जानकारी"</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> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 0d226b1db920..96071202926e 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Uklj. • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Isključeno"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Postavi"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Upravljajte u postavkama"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nema aktivnih načina}=1{Aktivno: {mode}}one{# način je aktivan}few{# načina su aktivna}other{# načina je aktivno}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Razgovori"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Izbriši sve bešumne obavijesti"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Značajka Ne uznemiravaj pauzirala je Obavijesti"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Nema obavijesti}=1{Obavijesti je pauzirao način {mode}}=2{Obavijesti su pauzirali način {mode} i još jedan način}one{Obavijesti su pauzirali način {mode} i još # način rada}few{Obavijesti su pauzirali način {mode} i još # načina rada}other{Obavijesti su pauzirali način {mode} i još # načina rada}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Prikaži demo način"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Uključen je način <xliff:g id="MODENAME">%1$s</xliff:g>"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Postavite aplikaciju za bržu i sigurniju kupnju telefonom"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Prikaži sve"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Saznajte više o pokretima za dodirnu podlogu"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Krećite se pomoću tipkovnice i dodirne podloge"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Saznajte više o pokretima za dodirnu podlogu, tipkovnim prečacima i ostalom"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Pokret za povratak"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pokret za otvaranje početnog zaslona"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Pregled nedavnih aplikacija"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Natrag"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Da biste se vratili natrag, s tri prsta prijeđite ulijevo ili udesno bilo gdje na dodirnoj podlozi.\n\nZa to možete upotrijebiti i tipku za radnju tipkovnog prečaca + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Sjajno!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Izvršili ste pokret za povratak."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Na početnu stranicu"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Da biste u bilo kojem trenutku otvorili početni zaslon, trima prstima prijeđite prema gore od dna zaslona."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Odlično!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Izvršili ste pokret za otvaranje početnog zaslona."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Pregled nedavnih aplikacija"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Prijeđite prema gore trima prstima na dodirnoj podlozi i zadržite pritisak."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Sjajno!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Izvršili ste pokret za prikaz nedavno korištenih aplikacija."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tipka za radnju"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Da biste pristupili svojim aplikacijama, pritisnite tipku za radnje na tipkovnici."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Čestitamo!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Izvršili ste pokret tipke za radnju.\n\nRadnja + / prikazuje sve prečace koji su vam dostupni."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvjetljenje tipkovnice"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Razina %1$d od %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Upravljanje uređajima"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Za prikaz svojih svih aplikacija pritisnite tipku za radnju na tipkovnici"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Redaktirano"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Otključajte za prikaz"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstualno obrazovanje"</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> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 6c26cd5f817e..3a9735bbf7fd 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Be"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Be • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Ki"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Beállítás"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"A Beállítások között kezelheti"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nincs aktív mód}=1{A(z) {mode} aktív}other{# mód aktív}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Beszélgetések"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Az összes néma értesítés törlése"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Ne zavarjanak funkcióval szüneteltetett értesítések"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Nincs értesítés}=1{A(z) {mode} szüneteltette az értesítéseket}=2{A(z) {mode} és egy másik mód szüneteltette az értesítéseket}other{A(z) {mode} és # másik mód szüneteltette az értesítéseket}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Demó mód megjelenítése"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Ébresztés"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"A(z) <xliff:g id="MODENAME">%1$s</xliff:g> aktív"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Végezze el a beállítást a telefonjával való gyorsabb és biztonságosabb vásárláshoz"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Összes mutatása"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Érintőpad-kézmozdulatok megismerése"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigálás a billentyűzet és az érintőpad használatával"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Érintőpad-kézmozdulatok, billentyűparancsok és egyebek megismerése"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Vissza kézmozdulat"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Kezdőképernyő kézmozdulat"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Legutóbbi alkalmazások megtekintése"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Kész"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Vissza"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"A visszalépéshez csúsztasson három ujjal balra vagy a jobbra az érintőpadon.\n\nEnnek végrehajtásához használhatja az Action + Esc billentyűparancsot is."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Kiváló!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Teljesítette a visszalépési kézmozdulatot."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ugrás a főoldalra"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Ha bármikor vissza szeretne térni a kezdőképernyőre, csúsztassa gyorsan felfelé három ujját a képernyő aljáról."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Remek!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Teljesítette a kezdőképernyőre lépés kézmozdulatát."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Legutóbbi alkalmazások megtekintése"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Csúsztasson felfelé három ujjal az érintőpadon, és tartsa lenyomva az ujjait."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Kiváló!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Teljesítette a legutóbbi alkalmazások megtekintésének kézmozdulatát."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Műveletbillentyű"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Az alkalmazásokhoz való hozzáféréshez nyomja meg a billentyűzet műveletbillentyűjét."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Gratulálunk!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Teljesítette a műveletbillentyű kézmozdulatát.\n\nA Művelet + / billentyűkombinációval megjelenítheti az összes használható billentyűparancsot."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"A billentyűzet háttérvilágítása"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Fényerő: %2$d/%1$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Otthon vezérlése"</string> @@ -1436,6 +1449,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Törölve"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Oldja fel a megtekintéshez"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontextusfüggő tájékoztató párbeszédpanel"</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> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index c0e7c309fef2..804550cb6319 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Միացված է"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Միաց․ • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Անջատված է"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Կարգավորել"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Զրույցներ"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Ջնջել բոլոր անձայն ծանուցումները"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Ծանուցումները չեն ցուցադրվի «Չանհանգստացնել» ռեժիմում"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Ծանուցումներ չկան}=1{Ծանուցումները դադարեցվել են «{mode}» ռեժիմի կողմից}=2{Ծանուցումները դադարեցվել են «{mode}» ու ևս մի ռեժիմի կողմից}one{Ծանուցումները դադարեցվել են «{mode}» ու ևս # ռեժիմի կողմից}other{Ծանուցումները դադարեցվել են «{mode}» ու ևս # ռեժիմի կողմից}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Ցուցադրական ռեժիմի ցուցադրում"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Զարթուցիչ"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"«<xliff:g id="MODENAME">%1$s</xliff:g>» ռեժիմը միացված է"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Վճարեք հեռախոսով՝ ավելի արագ և ապահով"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Ցույց տալ բոլորը"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Սովորեք օգտագործել հպահարթակի ժեստերը"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Կողմնորոշվեք ստեղնաշարի և հպահարթակի օգնությամբ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Սովորեք օգտագործել հպահարթակի ժեստերը, ստեղնային դյուրանցումները և ավելին"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"«Հետ» ժեստ"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Հիմնական էկրան անցնելու ժեստ"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Դիտել վերջին հավելվածները"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Պատրաստ է"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Հետ գնալ"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Հետ գնալու համար հպահարթակի վրա երեք մատով սահեցրեք ձախ կամ աջ։\n\nԻնչպես նաև կարող եք օգտագործել ստեղնային դյուրանցման գործողությունը + Esc։"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Կեցցե՛ք"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Դուք սովորեցիք հետ գնալու ժեստը։"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Անցում հիմնական էկրան"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Հիմնական էկրան վերադառնալու համար երեք մատը էկրանի ներքևից սահեցրեք վերև։"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Գերազանց է"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Դուք սովորեցիք հիմնական էկրան անցնելու ժեստը։"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Դիտել վերջին հավելվածները"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Երեք մատը սահեցրեք վերև և սեղմած պահեք հպահարթակին։"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Կեցցե՛ք։"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Դուք կատարեցիք վերջին օգտագործված հավելվածների դիտման ժեստը։"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Գործողության ստեղն"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Բոլոր հավելվածներն օգտագործելու համար սեղմեք գործողության ստեղնը ստեղնաշարի վրա"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Շնորհավո՛ր"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Դուք սովորեցիք գործողության ստեղնի ժեստը։\n\nԳործողություն + / ժեստը ցույց է տալիս ձեզ հասանելի բոլոր դյուրանցումները։"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Հետին լուսավորությամբ ստեղնաշար"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d՝ %2$d-ից"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Տան կառավարման տարրեր"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Բոլոր հավելվածները դիտելու համար սեղմեք գործողության ստեղնը ստեղնաշարի վրա"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Կոդավորված"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Ապակողպել դիտելու համար"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Համատեքստային ուսուցում"</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> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 906fde458d82..98bbf4f8ca5d 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Aktif"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Aktif • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Nonaktif"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Siapkan"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Kelola di setelan"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Tidak ada mode yang aktif}=1{{mode} aktif}other{# mode aktif}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Percakapan"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Hapus semua notifikasi senyap"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifikasi dijeda oleh mode Jangan Ganggu"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Tidak ada notifikasi}=1{Notifikasi dijeda oleh {mode}}=2{Notifikasi dijeda oleh {mode} dan satu mode lainnya}other{Notifikasi dijeda oleh {mode} dan # mode lainnya}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Tampilkan mode demo"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> aktif"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Siapkan metode pembayaran untuk melakukan pembelian dengan lebih cepat dan aman menggunakan ponsel Anda"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Tampilkan semua"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Pelajari gestur touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Menavigasi menggunakan keyboard dan touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Pelajari gestur touchpad, pintasan keyboard, dan lainnya"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gestur kembali"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gestur layar utama"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Lihat aplikasi terbaru"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Selesai"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kembali"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Untuk kembali, geser ke kiri atau kanan menggunakan tiga jari di touchpad.\n\nAnda juga dapat menggunakan pintasan keyboard Action + ECS untuk melakukannya."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Bagus!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Anda telah menyelesaikan gestur kembali."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Buka layar utama"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Untuk membuka layar utama kapan saja, geser ke atas menggunakan tiga jari dari bawah layar Anda."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Bagus!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Anda telah menyelesaikan gestur buka layar utama."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Lihat aplikasi terbaru"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Geser ke atas dan tahan menggunakan tiga jari di touchpad."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Bagus!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Anda telah menyelesaikan gestur untuk melihat aplikasi terbaru."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tombol tindakan"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Untuk mengakses aplikasi, tekan tombol tindakan di keyboard."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Selamat!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Anda telah menyelesaikan gestur tombol tindakan.\n\nTindakan + / akan menampilkan semua pintasan yang Anda miliki."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Lampu latar keyboard"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Tingkat %1$d dari %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrol Rumah"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Untuk melihat semua aplikasi, tekan tombol tindakan di keyboard"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Disamarkan"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Buka kunci untuk melihat"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Pendidikan kontekstual"</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> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 68f2c23e4a19..b12a475b9efd 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Kveikt"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Kveikt • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Slökkt"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Setja upp"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Stjórna í stillingum"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Engar virkar stillingar}=1{{mode} er virk}one{# stilling er virk}other{# stillingar eru virkar}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Samtöl"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Hreinsa allar þöglar tilkynningar"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Hlé gert á tilkynningum þar sem stillt er á „Ónáðið ekki“"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Engar tilkynningar}=1{Hlé gert á tilkynningum þar sem stillt er á {mode}}=2{Hlé gert á tilkynningum þar sem stillt er á {mode} og eina aðra stillingu}one{Hlé gert á tilkynningum þar sem stillt er á {mode} og # aðra stillingu}other{Hlé gert á tilkynningum þar sem stillt er á {mode} og # aðrar stillingar}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Sýna prufustillingu"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Vekjari"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Kveikt er á „<xliff:g id="MODENAME">%1$s</xliff:g>“"</string> <string name="wallet_title" msgid="5369767670735827105">"Veski"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Stilltu hlutina þannig að þú getir verslað með símanum á hraðari og öruggari hátt"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Sýna allt"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Nánar um bendingar á snertifleti"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Flettu með því að nota lyklaborðið og snertiflötinn"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Kynntu þér bendingar á snertifleti, flýtilykla og fleira"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Bending til að fara til baka"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Bending til að fara á upphafsskjá"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Sjá nýleg forrit"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Lokið"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Til baka"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Strjúktu til vinstri eða hægri með þremur fingrum hvar sem er á snertifletinum til að fara til baka.\n\nÞú getur einnig notað flýtileiðaraðgerðina + ESC til að gera þetta."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Vel gert!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Þú laukst við að kynna þér bendinguna „til baka“."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Heim"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Strjúktu upp frá neðri brún skjásins með þremur fingrum til að opna heimaskjáinn."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Flott!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Þú laukst við að kynna þér bendinguna „heim“."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Sjá nýleg forrit"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Strjúktu upp og haltu þremur fingrum inni á snertifletinum."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Vel gert!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Þú framkvæmdir bendinguna til að sjá nýleg forrit."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Aðgerðalykill"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Ýttu á aðgerðalykilinn á lyklaborðinu til að opna forritin þín."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Til hamingju!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Þú laukst við að kynna þér bendinguna „aðgerðalykill“.\n\nAðgerðalykill + / sýnir þér alla flýtilykla sem eru í boði."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Baklýsing lyklaborðs"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Stig %1$d af %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Heimastýringar"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ýttu á aðgerðalykilinn á lyklaborðinu til að sjá öll forritin þín"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Ritskoðað"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Taktu úr lás til að skoða"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Samhengismiðuð menntun"</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> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 4f8015ce31a2..4fdf01d7622f 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"On"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"On • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Off"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Configura"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversazioni"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Cancella tutte le notifiche silenziose"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notifiche messe in pausa in base alla modalità Non disturbare"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Nessuna notifica}=1{Notifica messa in pausa da {mode}}=2{Notifiche messe in pausa da {mode} e un\'altra modalità}many{Notifiche messe in pausa da {mode} e # di modalità}other{Notifiche messe in pausa da {mode} e altre # modalità}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Mostra modalità demo"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Sveglia"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Programmazione <xliff:g id="MODENAME">%1$s</xliff:g> attiva"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Imposta un metodo di pagamento per effettuare acquisti in modo più rapido e sicuro con il telefono"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Mostra tutto"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Impara i gesti con il touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Naviga usando la tastiera e il touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Scopri gesti con il touchpad, scorciatoie da tastiera e altro ancora"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto Indietro"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto Home"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Visualizza app recenti"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fine"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Indietro"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Per tornare indietro, scorri verso sinistra o verso destra utilizzando tre dita in un punto qualsiasi del touchpad.\n\nPuoi usare anche la scorciatoia da tastiera Action + Esc per farlo."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Ottimo lavoro."</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Hai completato il gesto Indietro."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Vai alla schermata Home"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Per andare alla schermata Home, scorri verso l\'alto con tre dita dalla parte inferiore dello schermo."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Bene!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Hai completato il gesto Vai alla schermata Home."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Visualizza app recenti"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Scorri verso l\'alto e tieni premuto con tre dita sul touchpad."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Ottimo lavoro."</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Hai completato il gesto Visualizza app recenti."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tasto azione"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Per accedere alle tue app, premi il tasto azione sulla tastiera."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Complimenti!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Hai completato il gesto del tasto azione.\n\nAzione + / mostra tutte le scorciatoie disponibili."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroilluminazione della tastiera"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Livello %1$d di %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Controlli della casa"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Per visualizzare tutte le tue app, premi il tasto azione sulla tastiera"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Oscurata"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Sblocca per visualizzare"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Istruzione contestuale"</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> @@ -1445,7 +1459,7 @@ <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> <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"Ora l\'attenuazione extra è nel cursore della luminosità"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Ora puoi usare l\'attenuazione extra per lo schermo abbassando il livello di luminosità ancora di più.\n\nDato che questa funzionalità ora fa parte del cursore della luminosità, le scorciatoie per l\'attenuazione extra vengono rimosse."</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Ora puoi usare l\'attenuazione extra per lo schermo abbassando ulteriormente il livello di luminosità.\n\nDato che questa funzionalità è ora integrata nel cursore della luminosità, le scorciatoie per l\'attenuazione extra vengono rimosse."</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"Rimuovi scorciatoie attenuazione extra"</string> <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"Scorciatoie attenuazione extra rimosse"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Connettività"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 3d7a25c0e3ea..78d60e575499 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"מצב מופעל"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"פועל • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"מצב מושבת"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"להגדרה"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"שינוי ב\'הגדרות\'"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{אין מצבים פעילים}=1{מצב פעיל אחד ({mode})}one{# מצבים פעילים}two{# מצבים פעילים}other{# מצבים פעילים}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"כדי לא להפריע לך, המכשיר לא ירטוט ולא ישמיע שום צליל, חוץ מהתראות, תזכורות, אירועים ושיחות ממתקשרים מסוימים לבחירתך. המצב הזה לא ישפיע על צלילים שהם חלק מתוכן שבחרת להפעיל, כמו מוזיקה, סרטונים ומשחקים."</string> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"שיחות"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"ניקוי כל ההתראות השקטות"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"התראות הושהו על ידי מצב \'נא לא להפריע\'"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{אין התראות}=1{ההתראות הושהו על ידי {mode}}=2{ההתראות הושהו על ידי {mode} ועל ידי מצב אחד נוסף}one{ההתראות הושהו על ידי {mode} ועל ידי # מצבים נוספים}other{ההתראות הושהו על ידי {mode} ועל ידי # מצבים נוספים}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"מצב <xliff:g id="MODENAME">%1$s</xliff:g> פועל"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"מגדירים אמצעי תשלום ונהנים מביצוע מהיר ומאובטח יותר של רכישות באמצעות הטלפון"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"הצגת הכול"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"מידע על התנועות בלוח המגע"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"ניווט באמצעות המקלדת ולוח המגע"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"מידע על התנועות בלוח המגע, מקשי קיצור ועוד"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"תנועת חזרה"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"תנועת חזרה למסך הבית"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"הצגת האפליקציות האחרונות"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"סיום"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"חזרה"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"כדי לחזור אחורה, מחליקים שמאלה או ימינה עם שלוש אצבעות בכל מקום על לוח המגע.\n\nאפשר לבצע את הפעולה הזו גם באמצעות קיצור הדרך לפעולה + מקש ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"מעולה!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"השלמת את התנועה \'הקודם\'."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"מעבר לדף הבית"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"כדי לעבור למסך הבית בכל שלב, צריך להחליק למעלה עם שלוש אצבעות מהחלק התחתון של המסך."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"איזה יופי!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"השלמת את תנועת המעבר למסך הבית."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"הצגת האפליקציות האחרונות"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"מחליקים למעלה ולוחצים לחיצה ארוכה עם שלוש אצבעות על לוח המגע."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"מעולה!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"השלמת את התנועה להצגת האפליקציות האחרונות."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"מקש הפעולה"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"כדי לגשת לאפליקציות, מקישים על מקש הפעולה במקלדת."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"כל הכבוד!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"השלמת את התנועה של מקש הפעולה.\n\nלחיצה על מקש הפעולה + מקש / מציגה את כל מקשי הקיצור הזמינים."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"התאורה האחורית במקלדת"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"רמה %1$d מתוך %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"שליטה במכשירים"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"כדי לראות את כל האפליקציות, מקישים על מקש הפעולה במקלדת"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"מצונזר"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"צריך לבטל את הנעילה כדי לראות"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"חינוך בהתאם להקשר"</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> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 3e29ed62fa7c..2a35e17cd259 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -440,7 +440,7 @@ <string name="zen_mode_on" msgid="9085304934016242591">"ON"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"ON • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"OFF"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"設定"</string> + <string name="zen_mode_set_up" msgid="8231201163894922821">"未設定"</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> @@ -573,8 +573,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"会話"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"サイレント通知がすべて消去されます"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"サイレント モードにより通知は一時停止中です"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{通知なし}=1{{mode} により通知は一時停止中です}=2{{mode} と他 1 個のモードにより通知は一時停止中です}other{{mode} と他 # 個のモードにより通知は一時停止中です}}"</string> <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> @@ -706,6 +705,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g>: ON"</string> <string name="wallet_title" msgid="5369767670735827105">"ウォレット"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"スマートフォンを使ってよりすばやく安全に購入できるように設定しましょう"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"すべて表示"</string> @@ -1405,26 +1405,26 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"タッチパッド操作の詳細"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"キーボードとタッチパッドを使用して移動する"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"タッチパッド操作やキーボード ショートカットなどの詳細"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"「戻る」ジェスチャー"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"「ホーム」ジェスチャー"</string> + <string name="touchpad_tutorial_back_gesture_button" msgid="3104716365403620315">"戻る"</string> + <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ホームに移動"</string> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"最近使ったアプリを表示する"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完了"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"戻る"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"戻るには、3 本の指でタッチパッドを左右にスワイプします。\n\nキーボード ショートカットのアクション + ESC キーを使用して、この操作を行うこともできます。"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"お疲れさまでした。"</string> + <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"タッチパッドを 3 本の指で左右にスワイプします"</string> + <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"その調子です!"</string> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"「戻る」操作を学習しました。"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ホームに移動"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"3 本の指で画面を下から上にスワイプすると、ホーム画面にいつでも移動できます。"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"お疲れさまでした。"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"「ホームに移動」操作を学習しました。"</string> + <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"タッチパッドを 3 本の指で上にスワイプします"</string> + <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"よくできました!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"「ホームに移動」操作を学習しました"</string> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"最近使ったアプリを表示する"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"タッチパッドを 3 本の指で上にスワイプして長押しします。"</string> + <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"タッチパッドを 3 本の指で上にスワイプして長押しします"</string> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"よくできました"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"「最近使ったアプリを表示する」操作を学習しました。"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"アクションキー"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"アプリにアクセスするには、キーボードのアクションキーを押します。"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"お疲れさまでした。"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"アクションキー操作を学習しました。\n\nアクションキーと + キーを同時に押すと、利用可能なショートカットがすべて表示されます。"</string> + <string name="tutorial_action_key_title" msgid="8172535792469008169">"すべてのアプリを表示"</string> + <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"キーボードのアクションキーを押します"</string> + <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"完了です!"</string> + <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"「すべてのアプリを表示する」操作を学習しました"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"キーボード バックライト"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"レベル %1$d/%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ホーム コントロール"</string> @@ -1436,6 +1436,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"すべてのアプリを表示するには、キーボードのアクションキーを押してください"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"削除済み"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"表示するにはロックを解除してください"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"コンテキスト メニューに関する説明"</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> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 539c186011e3..05a7e42a5937 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -440,7 +440,7 @@ <string name="zen_mode_on" msgid="9085304934016242591">"ჩართული"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"ჩართულია • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"გამორთული"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"დაყენება"</string> + <string name="zen_mode_set_up" msgid="8231201163894922821">"არ არის დაყენებული"</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> @@ -573,8 +573,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"საუბრები"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"ყველა ჩუმი შეტყობინების გასუფთავება"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"შეტყობინებები დაპაუზდა „არ შემაწუხოთ“ რეჟიმის მეშვეობით"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{შეტყობინებები არ არის}=1{შეტყობინებები შეჩერებულია {mode}-ის გამო}=2{შეტყობინებები შეჩერებულია {mode}-ის და ერთი სხვა რეჟიმის გამო}other{შეტყობინებები შეჩერებულია {mode}-ის და # სხვა რეჟიმის გამო}}"</string> <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> @@ -706,6 +705,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> ჩართულია"</string> <string name="wallet_title" msgid="5369767670735827105">"საფულე"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"დააყენეთ შესყიდვების თქვენი ტელეფონით უფრო სწრაფად და უსაფრთხოდ შესასრულებლად"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"ყველას ჩვენება"</string> @@ -1405,26 +1405,26 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"სენსორული პანელის ჟესტების სწავლა"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"ნავიგაცია კლავიატურის და სენსორული პანელის გამოყენებით"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"სენსორული პანელის ჟესტების, კლავიატურის მალსახმობების და სხვა ფუნქციების სწავლა"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"უკან დაბრუნების ჟესტი"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"მთავარ ეკრანზე გადასვლის ჟესტი"</string> + <string name="touchpad_tutorial_back_gesture_button" msgid="3104716365403620315">"უკან დაბრუნება"</string> + <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"მთავარ ეკრანზე გადასვლა"</string> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ბოლო აპების ნახვა"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"მზადაა"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"უკან დაბრუნება"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"უკან დასაბრუნებლად სენსორულ პანელზე გადაფურცლეთ მარცხნივ ან მარჯვნივ სამი თითის გამოყენებით ნებისმიერ ადგილას.\n\nამისთვის თქვენ ასევე შეგიძლიათ გამოიყენოთ კლავიატურის მალსახმობის მოქმედება + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"შესანიშნავია!"</string> + <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"თქვენს სენსორულ პანელზე სამი თითით გადაფურცლეთ მარცხნივ ან მარჯვნივ"</string> + <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"მშვენიერია!"</string> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"თქვენ შეასრულეთ უკან დაბრუნების ჟესტი."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"მთავარზე გადასვლა"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"თქვენს მთავარ ეკრანზე ნებისმიერ დროს გადასასვლელად გადაფურცლეთ ეკრანის ქვემოდან ზემოთ სამი თითით."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"მშვენიერია!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"თქვენ შეასრულეთ მთავარ ეკრანზე დაბრუნების ჟესტი."</string> + <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"თქვენს სენსორულ პანელზე სამი თითით გადაფურცლეთ ზევით"</string> + <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"შესანიშნავია!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"თქვენ შეასრულეთ მთავარ ეკრანზე გადასვლის ჟესტი"</string> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ბოლო აპების ნახვა"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"თქვენს სენსორულ პანელზე სამი თითით გადაფურცლეთ ზემოთ და მოიცადეთ."</string> + <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"თქვენს სენსორულ პანელზე სამი თითით გადაფურცლეთ ზევით და ხანგრძლივად დააჭირეთ"</string> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"შესანიშნავია!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"თქვენ დაასრულეთ ბოლო აპების ხედის ჟესტი."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"მოქმედების კლავიში"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"აპებზე წვდომისთვის დააჭირეთ მოქმედების კლავიშს თქვენს კლავიატურაზე."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"გილოცავთ!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"თქვენ შეასრულეთ მოქმედების კლავიშის ჟესტი.\n\nქმედება + / აჩვენებს თქვენთვის ხელმისაწვდომ ყველა მალსახმობს."</string> + <string name="tutorial_action_key_title" msgid="8172535792469008169">"ყველა აპის ნახვა"</string> + <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"დააჭირეთ მოქმედების კლავიშს თქვენს კლავიატურაზე"</string> + <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ყოჩაღ!"</string> + <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"თქვენ დაასრულეთ ყველა აპის ნახვის ჟესტი"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"კლავიატურის შენათება"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"დონე: %1$d %2$d-დან"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"სახლის კონტროლი"</string> @@ -1436,6 +1436,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ყველა აპის სანახავად დააჭირეთ მოქმედების კლავიშს თქვენს კლავიატურაზე"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ტექსტს ადევს ცენზურა"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"განბლოკვა სანახავად"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"კონტექსტური განათლება"</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> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 7343fa1440d6..328c82fba67f 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Қосулы"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Қосулы • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Өшірулі"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Реттеу"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Әңгімелер"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Барлық үнсіз хабарландыруларды өшіру"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Хабарландырулар Мазаламау режимінде кідіртілді"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Хабарландырулар жоқ.}=1{Хабарландыруларды {mode} режимі кідіртті.}=2{Хабарландыруларды {mode} және тағы бір режим кідіртті.}other{Хабарландыруларды {mode} және тағы # режим кідіртті.}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Демо режимін көрсету"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Оятқыш"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> қосулы."</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Телефоныңызбен бұрынғыдан да жылдам әрі қауіпсіз сатып алу үшін параметрлерді орнатыңыз."</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Барлығын көрсету"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Сенсорлық тақта қимылдарын үйреніңіз."</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Пернетақтамен және сенсорлық тақтамен жұмыс істеңіз"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Сенсорлық тақта қимылдарын, перне тіркесімдерін және т.б. үйреніңіз."</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Артқа қайтару қимылы"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Негізгі бетке қайтару қимылы"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Соңғы қолданбаларды көру"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Дайын"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Артқа"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Артқа қайту үшін сенсорлық тақтаның кез келген жерін үш саусақпен солға не оңға сырғытыңыз.\n\nСондай-ақ Action + ESC перне тіркесімін пайдалануға болады."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Жарайсыз!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Артқа қайту қимылын аяқтадыңыз."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Негізгі экранға өту"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Негізгі экранға кез келген уақытта өту үшін экранның төменгі жағынан жоғары қарай үш саусағыңызбен сырғытыңыз."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Жақсы нәтиже!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Негізгі экранға қайту қимылын аяқтадыңыз."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Соңғы қолданбаларды көру"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Сенсорлық тақтада үш саусақпен жоғары сырғытып, басып тұрыңыз."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Жарайсыз!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Соңғы қолданбаларды көру қимылын орындадыңыз."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Әрекет пернесі"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Қолданбаларыңызға кіру үшін пернетақтадағы әрекет пернесін басыңыз."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Құттықтаймыз!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Әрекет пернесі қимылын аяқтадыңыз.\n\n\"+ /\" әрекеті сіз үшін қолжетімді барлық таңбашаны көрсетеді."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Пернетақта жарығы"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Деңгей: %1$d/%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Үй басқару элементтері"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Пернетақтада әрекет пернесін басып, барлық қолданбаны көре аласыз."</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Жасырылған"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Көру үшін құлыпты ашыңыз."</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Контекстік білім"</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> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 117463564fd3..dce1adc32540 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"បើក"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"បើក • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"បិទ"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"រៀបចំ"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"ការសន្ទនា"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"សម្អាតការជូនដំណឹងស្ងាត់ទាំងអស់"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"ការជូនដំណឹងបានផ្អាកដោយមុខងារកុំរំខាន"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{គ្មានការជូនដំណឹង}=1{ការជូនដំណឹងត្រូវបានផ្អាកដោយ {mode}}=2{ការជូនដំណឹងត្រូវបានផ្អាកដោយ {mode} និងមុខងារមួយផ្សេងទៀត}other{ការជូនដំណឹងត្រូវបានផ្អាកដោយ {mode} និងមុខងារ # ផ្សេងទៀត}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> ត្រូវបានបើក"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"ធ្វើការរៀបចំ ដើម្បីធ្វើការទិញកាន់តែលឿនជាងមុន សុវត្ថិភាពជាងមុន ដោយប្រើទូរសព្ទរបស់អ្នក"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"បង្ហាញទាំងអស់"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"ស្វែងយល់អំពីចលនាផ្ទាំងប៉ះ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"រុករកដោយប្រើក្ដារចុច និងផ្ទាំងប៉ះរបស់អ្នក"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"ស្វែងយល់អំពីចលនាផ្ទាំងប៉ះ ផ្លូវកាត់ក្ដារចុច និងអ្វីៗជាច្រើនទៀត"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ចលនាថយក្រោយ"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ចលនាទៅទំព័រដើម"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"មើលកម្មវិធីថ្មីៗ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"រួចរាល់"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ថយក្រោយ"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ដើម្បីថយក្រោយ សូមអូសទៅឆ្វេង ឬស្ដាំដោយប្រើម្រាមដៃបីនៅត្រង់ណាក៏បានលើផ្ទាំងប៉ះ។\n\nអ្នកក៏អាចប្រើសកម្មភាពផ្លូវកាត់ក្ដារចុច + ESC សម្រាប់ការធ្វើបែបនេះ។"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"ធ្វើបានល្អ!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"អ្នកបានបញ្ចប់ចលនាថយក្រោយហើយ។"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ទៅទំព័រដើម"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ដើម្បីចូលទៅអេក្រង់ដើមរបស់អ្នកនៅពេលណាក៏បាន សូមអូសឡើងលើដោយប្រើម្រាមដៃបីពីផ្នែកខាងក្រោមនៃអេក្រង់របស់អ្នក។"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"ល្អ!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"អ្នកបានបញ្ចប់ចលនាចូលទៅកាន់ទំព័រដើមហើយ។"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"មើលកម្មវិធីថ្មីៗ"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"អូសឡើងលើ ហើយសង្កត់ឱ្យជាប់ដោយប្រើម្រាមដៃបីលើផ្ទាំងប៉ះរបស់អ្នក។"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ធ្វើបានល្អ!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"អ្នកបានបញ្ចប់ការមើលចលនាកម្មវិធីថ្មីៗ។"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"គ្រាប់ចុចសកម្មភាព"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"ដើម្បីចូលប្រើប្រាស់កម្មវិធីរបស់អ្នក សូមចុចគ្រាប់ចុចសកម្មភាពនៅលើក្ដារចុចរបស់អ្នក។"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"សូមអបអរសាទរ!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"អ្នកបានបញ្ចប់មេរៀនអំពីចលនាសម្រាប់គ្រាប់ចុចសកម្មភាព។\n\nគ្រាប់ចុចសកម្មភាព + / បង្ហាញផ្លូវកាត់ទាំងអស់ដែលអ្នកអាចប្រើបាន។"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ពន្លឺក្រោយក្ដារចុច"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"កម្រិតទី %1$d នៃ %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ការគ្រប់គ្រងផ្ទះ"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ដើម្បីមើលកម្មវិធីទាំងអស់របស់អ្នក សូមចុចគ្រាប់ចុចសកម្មភាពនៅលើក្ដារចុចរបស់អ្នក"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"បានកែលម្អពាក្យពេចន៍"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ដោះសោដើម្បីមើល"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"ការអប់រំតាមបរិបទ"</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> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 52daecb89c63..5ac910256f04 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"ಆನ್ ಆಗಿದೆ"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"<xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g> • ನಲ್ಲಿ"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ಆಫ್ ಆಗಿದೆ"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"ಸೆಟಪ್ ಮಾಡಿ"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"ಸಂಭಾಷಣೆಗಳು"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"ಎಲ್ಲಾ ನಿಶ್ಶಬ್ಧ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೆರವುಗೊಳಿಸಿ"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಎನ್ನುವ ಮೂಲಕ ಅಧಿಸೂಚನೆಗಳನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{ಯಾವುದೇ ನೋಟಿಫಿಕೇಶನ್ಗಳು ಇಲ್ಲ}=1{ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು {mode} ವಿರಾಮಗೊಳಿಸಿದೆ}=2{ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು {mode} ಹಾಗೂ ಇತರ ಒಂದು ಮೋಡ್ ವಿರಾಮಗೊಳಿಸಿವೆ}one{ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು {mode} ಹಾಗೂ ಇತರ # ಮೋಡ್ಗಳು ವಿರಾಮಗೊಳಿಸಿವೆ}other{ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು {mode} ಹಾಗೂ ಇತರ # ಮೋಡ್ಗಳು ವಿರಾಮಗೊಳಿಸಿವೆ}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> ಆನ್ ಆಗಿದೆ"</string> <string name="wallet_title" msgid="5369767670735827105">"ವಾಲೆಟ್"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"ನಿಮ್ಮ ಫೋನ್ ಮೂಲಕ ವೇಗವಾದ, ಹೆಚ್ಚು ಸುರಕ್ಷಿತ ಖರೀದಿಗಳನ್ನು ಮಾಡಲು ಸೆಟಪ್ ಮಾಡಿಕೊಳ್ಳಿ"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"ಎಲ್ಲವನ್ನೂ ತೋರಿಸಿ"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"ಟಚ್ಪ್ಯಾಡ್ ಗೆಸ್ಚರ್ಗಳನ್ನು ಕಲಿಯಿರಿ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"ನಿಮ್ಮ ಕೀಬೋರ್ಡ್ ಮತ್ತು ಟಚ್ಪ್ಯಾಡ್ ಬಳಸಿ ನ್ಯಾವಿಗೇಟ್ ಮಾಡಿ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"ಟಚ್ಪ್ಯಾಡ್ ಗೆಸ್ಚರ್ಗಳು, ಕೀಬೋರ್ಡ್ಗಳ ಶಾರ್ಟ್ಕಟ್ಗಳು ಮತ್ತು ಹೆಚ್ಚಿನದನ್ನು ತಿಳಿಯಿರಿ"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ಹಿಂಬದಿ ಗೆಸ್ಚರ್"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ಹೋಮ್ ಗೆಸ್ಚರ್"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ಇತ್ತೀಚಿನ ಆ್ಯಪ್ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ಮುಗಿದಿದೆ"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ಹಿಂತಿರುಗಿ"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ಹಿಂತಿರುಗಲು, ಟಚ್ಪ್ಯಾಡ್ನಲ್ಲಿ ಎಲ್ಲಿಯಾದರೂ ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಎಡ ಅಥವಾ ಬಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ.\n\nಇದಕ್ಕಾಗಿ ನೀವು ಕೀಬೋರ್ಡ್ ಶಾರ್ಟ್ಕಟ್ Action + ESC ಅನ್ನು ಸಹ ಬಳಸಬಹುದು."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"ಭೇಷ್!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ನೀವು ಗೋ ಬ್ಯಾಕ್ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ಮುಖಪುಟಕ್ಕೆ ಹೋಗಿ"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್ಗೆ ಹೋಗಲು, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಕೆಳಗಿನಿಂದ ಮೂರು ಬೆರಳುಗಳಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"ಭೇಷ್!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"ನೀವು ಗೋ ಹೋಮ್ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ಇತ್ತೀಚಿನ ಆ್ಯಪ್ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"ನಿಮ್ಮ ಟಚ್ಪ್ಯಾಡ್ನಲ್ಲಿ ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ಭೇಷ್!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ನೀವು ಇತ್ತೀಚಿನ ಆ್ಯಪ್ಗಳ ಗೆಸ್ಚರ್ ವೀಕ್ಷಣೆಯನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"ಆ್ಯಕ್ಷನ್ ಕೀ"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"ನಿಮ್ಮ ಆ್ಯಪ್ಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು, ನಿಮ್ಮ ಕೀಬೋರ್ಡ್ನಲ್ಲಿರುವ ಆ್ಯಕ್ಷನ್ ಕೀಯನ್ನು ಒತ್ತಿರಿ."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"ಅಭಿನಂದನೆಗಳು!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"ನೀವು ಆ್ಯಕ್ಷನ್ ಕೀ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ.\n\nನಿಮಗೆ ಲಭ್ಯವಿರುವ ಎಲ್ಲಾ ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಆ್ಯಕ್ಷನ್ + / ತೋರಿಸುತ್ತದೆ."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ಕೀಬೋರ್ಡ್ ಬ್ಯಾಕ್ಲೈಟ್"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d ರಲ್ಲಿ %1$d ಮಟ್ಟ"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ಮನೆ ನಿಯಂತ್ರಣಗಳು"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ನಿಮ್ಮ ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳನ್ನು ವೀಕ್ಷಿಸಲು, ನಿಮ್ಮ ಕೀಬೋರ್ಡ್ನಲ್ಲಿರುವ ಆ್ಯಕ್ಷನ್ ಕೀಯನ್ನು ಒತ್ತಿರಿ"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ಅರ್ಥಬದ್ಧವಾಗಿಸಲಾಗಿದೆ"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ನೋಡಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"ಸಂದರ್ಭೋಚಿತ ಶಿಕ್ಷಣ"</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> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 9a9f3ebe71a8..b7d81b41ac87 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"사용"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"켜짐 • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"사용 안함"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"설정"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"대화"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"무음 알림 모두 삭제"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"방해 금지 모드로 알림이 일시중지됨"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{알림 없음}=1{{mode} 모드로 인해 알림이 일시중지되었습니다.}=2{{mode} 및 다른 모드로 인해 알림이 일시중지되었습니다.}other{{mode} 및 다른 모드 #개로 인해 알림이 일시중지되었습니다.}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> 사용 중"</string> <string name="wallet_title" msgid="5369767670735827105">"월렛"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"설정하여 휴대전화로 더욱 빠르고 안전하게 구매하세요."</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"모두 표시"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"터치패드 동작 알아보기"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"키보드와 터치패드를 사용하여 이동"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"터치패드 동작, 단축키 등 알아보기"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"뒤로 동작"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"홈 동작"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"최근 앱 보기"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"완료"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"뒤로"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"돌아가려면 세 손가락을 사용해 터치패드의 아무 곳이나 왼쪽 또는 오른쪽으로 스와이프합니다.\n\n키보드 단축키 Action + ESC를 사용할 수도 있습니다."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"아주 좋습니다"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"돌아가기 동작을 완료했습니다."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"홈으로 이동"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"언제든지 홈 화면으로 이동하려면 세 손가락으로 화면 하단에서 위로 스와이프하세요."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"좋습니다"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"홈으로 이동 동작을 완료했습니다."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"최근 앱 보기"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"터치패드에서 세 손가락을 사용해 위로 스와이프한 후 잠시 기다리세요."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"아주 좋습니다"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"최근 앱 보기 동작을 완료했습니다."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"작업 키"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"앱에 액세스하려면 키보드의 작업 키를 누르세요."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"축하합니다"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"작업 키 동작을 완료했습니다.\n\n작업 키 + /를 누르면 사용 가능한 모든 단축키가 표시됩니다."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"키보드 백라이트"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d단계 중 %1$d단계"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"홈 컨트롤"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"모든 앱을 보려면 키보드의 작업 키를 누르세요"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"수정됨"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"잠금 해제하여 보기"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"컨텍스트 교육"</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> @@ -1444,8 +1458,8 @@ <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> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"이제 \'더 어둡게\' 기능이 밝기 슬라이더에 추가되었습니다"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"이제 밝기 수준을 더 낮춰 화면을 더 어둡게 만들 수 있습니다.\n\n이 기능은 이제 밝기 슬라이더에 포함되므로 \'더 어둡게\' 단축키가 삭제됩니다."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"\'더 어둡게\' 기능이 밝기 슬라이더에 추가되었습니다"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"이제 밝기 수준을 더 낮춰 화면을 더 어둡게 만들 수 있습니다.\n\n밝기 슬라이더에서 이 기능을 이용할 수 있으므로 \'더 어둡게\' 단축키가 삭제됩니다."</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"\'더 어둡게\' 단축키 삭제"</string> <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"\'더 어둡게\' 단축키가 삭제되었습니다."</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"연결"</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 33ebf6df3c11..da4d4c38a57a 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Күйүк"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Күйүк • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Өчүк"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Тууралоо"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Сүйлөшүүлөр"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Бардык үнсүз билдирмелерди өчүрүү"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\"Тынчымды алба\" режиминде билдирмелер тындырылды"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Билдирмелер жок}=1{{mode} режими билдирмелерди тындырды}=2{{mode} жана дагы бир режим билдирмелерди тындырды}other{{mode} жана дагы # режим билдирмелерди тындырды}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Демо режимин көрсөтүү"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Ойготкуч"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> күйүк"</string> <string name="wallet_title" msgid="5369767670735827105">"Капчык"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Телефонуңуз менен тез жана коопсуз сатып алуу үчүн жөндөңүз"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Баарын көрсөтүү"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Сенсордук тактадагы жаңсоолорду үйрөнүп алыңыз"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Нерселерге баскычтоп жана сенсордук такта аркылуу өтүңүз"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Сенсордук тактадагы жаңсоолор, ыкчам баскычтар жана башкалар жөнүндө билип алыңыз"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Артка кайтуу жаңсоосу"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Башкы бетке өтүү жаңсоосу"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Акыркы колдонмолорду көрүү"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Бүттү"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Артка кайтуу"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Кайтуу үчүн сенсордук тактанын каалаган жерин үч манжаңыз менен солго же оңго сүрүңүз.\n\nОшондой эле Action + ESC баскычтарынын айкалышын колдоно аласыз."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Азаматсыз!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"\"Артка\" жаңсоосу боюнча үйрөткүчтү бүтүрдүңүз."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Башкы бетке өтүү"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Каалаган убакта башкы экранга өтүү үчүн экранды үч манжаңыз менен ылдыйдан жогору карай сүрүңүз."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Сонун!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"\"Башкы бетке өтүү\" жаңсоосун үйрөндүңүз."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Акыркы колдонмолорду көрүү"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Сенсордук тактаны үч манжаңыз менен өйдө сүрүп, кармап туруңуз."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Азаматсыз!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Акыркы колдонмолорду көрүү жаңсоосун аткардыңыз."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Аракет баскычы"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Бардык колдонмолоруңузду көрүү үчүн баскычтобуңуздагы аракет баскычын басыңыз"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Куттуктайбыз!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Аракет баскычынын жаңсоосун аткардыңыз.\n\n+ / аракети бардык жеткиликтүү ыкчам баскычтарды көрсөтөт."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Баскычтоптун жарыгы"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d ичинен %1$d-деңгээл"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Үйдөгү түзмөктөрдү тескөө"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Бардык колдонмолоруңузду көрүү үчүн баскычтобуңуздагы аракет баскычын басыңыз"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Жашырылды"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Көрүү үчүн кулпусун ачыңыз"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Контексттик билим берүү"</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> @@ -1445,7 +1459,7 @@ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Бардык колдонмолорду көрүү үчүн баскычтобуңузду колдонуңуз"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Каалаганда аракет баскычын басыңыз. Башка жаңсоолорду үйрөнүү үчүн таптаңыз."</string> <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"Кошумча караңгылатуу эми жарыктык сыдырмасында жайгашкан"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Эми экрандын жарыктыктыгынын деңгээлин азайтып, экранды кошумча караңгылата аласыз.\n\nБул функция эми жарыктык сыдырмасынын бир бөлүгү болуп калгандыктан, кошумча караңгылатуунун ыкчам баскычтары өтүрүлөт."</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Эми экрандын жарыктыктыгынын деңгээлин азайтып, аны кошумча караңгылата аласыз.\n\nБул функция эми жарыктык сыдырмасынын бир бөлүгү болуп калгандыктан, кошумча караңгылатуунун ыкчам баскычтары өчүрүлөт."</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"Кошумча караңгылатуу ыкчам баскычтарын өчүрүү"</string> <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"Кошумча караңгылатуу ыкчам баскычтары өчүрүлдү"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Байланыш"</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 410f7d5a506f..92b39745ab73 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -440,7 +440,7 @@ <string name="zen_mode_on" msgid="9085304934016242591">"ເປີດ"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"ເປີດ • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ປິດ"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"ຕັ້ງຄ່າ"</string> + <string name="zen_mode_set_up" msgid="8231201163894922821">"ຍັງບໍ່ໄດ້ຕັ້ງ"</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> @@ -573,8 +573,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"ການສົນທະນາ"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"ລຶບລ້າງການແຈ້ງເຕືອນແບບງຽບທັງໝົດ"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"ຢຸດການແຈ້ງເຕືອນໂດຍໂໝດຫ້າມລົບກວນແລ້ວ"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{ບໍ່ມີການແຈ້ງເຕືອນ}=1{{mode} ຢຸດການແຈ້ງເຕືອນໄວ້ຊົ່ວຄາວ}=2{{mode} ແລະ ອີກ 1 ໂໝດຢຸດການແຈ້ງເຕືອນໄວ້ຊົ່ວຄາວ}other{{mode} ແລະ ອີກ # ໂໝດຢຸດການແຈ້ງເຕືອນໄວ້ຊົ່ວຄາວ}}"</string> <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> @@ -706,6 +705,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> ເປີດຢູ່"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"ຕັ້ງຄ່າເພື່ອຊື້ດ້ວຍໂທລະສັບຂອງທ່ານໄດ້ໄວຂຶ້ນ ແລະ ປອດໄພຂຶ້ນ"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"ສະແດງທັງໝົດ"</string> @@ -1405,26 +1405,26 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"ສຶກສາທ່າທາງຂອງແຜ່ນສຳຜັດ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"ນຳທາງໂດຍໃຊ້ແປ້ນພິມ ແລະ ແຜ່ນສຳຜັດຂອງທ່ານ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"ສຶກສາທ່າທາງຂອງແຜ່ນສຳຜັດ, ຄີລັດ ແລະ ອື່ນໆ"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ທ່າທາງສຳລັບກັບຄືນ"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ທ່າທາງສຳລັບໜ້າຫຼັກ"</string> + <string name="touchpad_tutorial_back_gesture_button" msgid="3104716365403620315">"ກັບຄືນ"</string> + <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ໄປຫາໜ້າຫຼັກ"</string> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ເບິ່ງແອັບຫຼ້າສຸດ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ແລ້ວໆ"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ກັບຄືນ"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ເພື່ອກັບຄືນ, ໃຫ້ໃຊ້ 3 ນິ້ວປັດຊ້າຍ ຫຼື ຂວາບ່ອນໃດກໍໄດ້ເທິງແຜ່ນສຳຜັດ.\n\nທ່ານຍັງສາມາດໃຊ້ຄຳສັ່ງຄີລັດ + ESC ສຳລັບການດຳເນີນການນີ້ໄດ້ນຳ."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"ເກັ່ງຫຼາຍ!"</string> + <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"ປັດຊ້າຍ ຫຼື ຂວາໂດຍໃຊ້ມືສາມນິ້ວຢູ່ແຜ່ນສໍາຜັດຂອງທ່ານ"</string> + <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"ດີ!"</string> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ທ່ານໃຊ້ທ່າທາງກັບຄືນສຳເລັດແລ້ວ."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ໄປຫາໜ້າຫຼັກ"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ເພື່ອໄປຫາໜ້າຫຼັກຂອງທ່ານຕອນໃດກໍໄດ້, ໃຫ້ປັດຂຶ້ນດ້ວຍສາມນິ້ວຈາກລຸ່ມສຸດຂອງໜ້າຈໍຂອງທ່ານ."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"ດີຫຼາຍ!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"ທ່ານໃຊ້ທ່າທາງໄປໜ້າຫຼັກສຳເລັດແລ້ວ."</string> + <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"ປັດຂຶ້ນໂດຍໃຊ້ມືສາມນິ້ວຢູ່ແຜ່ນສໍາຜັດຂອງທ່ານ"</string> + <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"ດີຫຼາຍ!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"ທ່ານໃຊ້ທ່າທາງໄປໜ້າຫຼັກສຳເລັດແລ້ວ"</string> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ເບິ່ງແອັບຫຼ້າສຸດ"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"ໃຊ້ 3 ນິ້ວປັດຂຶ້ນແລ້ວຄ້າງໄວ້ຢູ່ແຜ່ນສໍາຜັດຂອງທ່ານ."</string> + <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"ປັດຂຶ້ນໂດຍໃຊ້ມືສາມນິ້ວແລ້ວຄ້າງໄວ້ຢູ່ແຜ່ນສໍາຜັດຂອງທ່ານ"</string> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ດີຫຼາຍ!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ທ່ານເບິ່ງທ່າທາງຂອງແອັບຫຼ້າສຸດສຳເລັດແລ້ວ."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"ປຸ່ມຄຳສັ່ງ"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"ເພື່ອເຂົ້າເຖິງແອັບ, ໃຫ້ກົດປຸ່ມຄຳສັ່ງຢູ່ແປ້ນພິມຂອງທ່ານ."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"ຂໍສະແດງຄວາມຍິນດີ!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"ທ່ານໃຊ້ທ່າທາງປຸ່ມຄຳສັ່ງສໍາເລັດແລ້ວ.\n\nຄໍາສັ່ງ + / ຈະສະແດງທາງລັດທັງໝົດທີ່ທ່ານມີ."</string> + <string name="tutorial_action_key_title" msgid="8172535792469008169">"ເບິ່ງແອັບທັງໝົດ"</string> + <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ກົດປຸ່ມຄຳສັ່ງຢູ່ແປ້ນພິມຂອງທ່ານ"</string> + <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ດີຫຼາຍ!"</string> + <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"ທ່ານເບິ່ງທ່າທາງຂອງແອັບທັງໝົດສຳເລັດແລ້ວ"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ໄຟປຸ່ມແປ້ນພິມ"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"ລະດັບທີ %1$d ຈາກ %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ການຄວບຄຸມເຮືອນ"</string> @@ -1436,6 +1436,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ເພື່ອເບິ່ງແອັບທັງໝົດຂອງທ່ານ, ໃຫ້ກົດປຸ່ມຄຳສັ່ງຢູ່ແປ້ນພິມຂອງທ່ານ"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ປົກປິດໄວ້ແລ້ວ"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ປົດລັອກເພື່ອເບິ່ງ"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"ການສຶກສາຕາມບໍລິບົດ"</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> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 67ead2399a38..a5e325e28fad 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Įjungta"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Įjungta • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Išjungta"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Nustatyti"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Tvarkyti skiltyje „Nustatymai“"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nėra aktyvių režimų}=1{Aktyvus režimas „{mode}“}one{# aktyvus režimas}few{# aktyvūs režimai}many{# aktyvaus režimo}other{# aktyvių režimų}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Pokalbiai"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Išvalyti visus tylius pranešimus"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Pranešimai pristabdyti naudojant netrukdymo režimą"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Nėra pranešimų}=1{Pranešimai pristabdyti naudojant režimą „{mode}“}=2{Pranešimai pristabdyti naudojant režimą „{mode}“ ir dar vieną režimą}one{Pranešimai pristabdyti naudojant režimą „{mode}“ ir dar # režimą}few{Pranešimai pristabdyti naudojant režimą „{mode}“ ir dar # režimus}many{Pranešimai pristabdyti naudojant režimą „{mode}“ ir dar # režimo}other{Pranešimai pristabdyti naudojant režimą „{mode}“ ir dar # režimų}}"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Pradėti dabar"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nėra įspėjimų"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Naujų pranešimų nėra"</string> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Rodyti demonstraciniu režimu"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Eternetas"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Signalas"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Tvarkaraštis „<xliff:g id="MODENAME">%1$s</xliff:g>“ įjungtas"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Nustatykite, kad galėtumėte greičiau ir saugiau pirkti telefonu"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Rodyti viską"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Sužinokite jutiklinės dalies gestus"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Naršykite naudodamiesi klaviatūra ir jutikline dalimi"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Sužinokite jutiklinės dalies gestus, sparčiuosius klavišus ir kt."</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Grįžimo atgal gestas"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pagrindinio ekrano gestas"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Peržiūrėti naujausias programas"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Atlikta"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Grįžti"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Jei norite grįžti, perbraukite kairėn arba dešinėn trimis pirštais bet kurioje jutiklinės dalies vietoje.\n\nTaip pat galite naudoti šį spartųjį klavišą: veiksmų klavišas + klavišas „Esc“."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Puiku!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Atlikote grįžimo atgal gestą."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Eikite į pagrindinį ekraną"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Jei norite bet kada pasiekti pagrindinį ekraną, perbraukite aukštyn trim pirštais iš ekrano apačios."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Šaunu!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Atlikote perėjimo į pagrindinį ekraną gestą."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Peržiūrėti naujausias programas"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Jutiklinėje dalyje perbraukite aukštyn trimis pirštais ir palaikykite."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Puiku!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Atlikote naujausių programų peržiūros gestą."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Veiksmų klavišas"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Jei norite pasiekti programas, paspauskite klaviatūros veiksmų klavišą."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Sveikiname!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Atlikote veiksmų klavišo gestą.\n\nVeiksmas + / rodo visus pasiekiamus sparčiuosius klavišus."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatūros foninis apšvietimas"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d lygis iš %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Namų sistemos valdymas"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Jei norite peržiūrėti visas programas, paspauskite klaviatūros veiksmų klavišą"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Paslėpta"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Atrakinkite, kad peržiūrėtumėte"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstinis švietimas"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Naudokite klaviatūrą, kad grįžtumėte atgal"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Perbraukite į kairę ar dešinę trimis pirštais. Palieskite, kad sužinotumėte daugiau gestų."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Naudokite jutiklinę dalį, jei norite eiti į pagrindinį ekraną"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 53e0baabcd28..b570ad6f700f 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Ieslēgts"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Ieslēgts • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Izslēgts"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Iestatīt"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Pārvaldīt iestatījumos"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nav aktīvu režīmu}=1{Režīms “{mode}” ir aktīvs}zero{# režīmi ir aktīvi}one{# režīms ir aktīvs}other{# režīmi ir aktīvi}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Sarunas"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Notīrīt visus klusos paziņojumus"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Paziņojumi pārtraukti, izmantojot iestatījumu “Netraucēt”"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Nav paziņojumu}=1{Paziņojumu rādīšana ir pārtraukta režīma “{mode}” dēļ}=2{Paziņojumu rādīšana ir pārtraukta režīma “{mode}” un vēl viena režīma dēļ}zero{Paziņojumu rādīšana ir pārtraukta režīma “{mode}” un vēl # režīmu dēļ}one{Paziņojumu rādīšana ir pārtraukta režīma “{mode}” un vēl # režīma dēļ}other{Paziņojumu rādīšana ir pārtraukta režīma “{mode}” un vēl # režīmu dēļ}}"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Sākt tūlīt"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Nav paziņojumu"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nav jaunu paziņojumu"</string> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Rādīt demonstrācijas režīmu"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Tīkls Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Signāls"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Maks"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Iestatiet, lai ātrāk un drošāk veiktu pirkumus, izmantojot tālruni"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Rādīt visu"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Apgūstiet skārienpaliktņa žestus."</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Pārvietošanās, izmantojot tastatūru un skārienpaliktni"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Uzziniet par skārienpaliktņa žestiem, īsinājumtaustiņiem un citām iespējām."</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Žests pāriešanai atpakaļ"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Žests pāriešanai uz sākumu"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Skatīt nesen izmantotās lietotnes"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gatavs"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atpakaļ"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Lai atgrieztos, ar trīs pirkstiem velciet pa kreisi vai pa labi jebkurā vietā uz skārienpaliktņa.\n\nVarat arī izmantot šim nolūkam īsinājumtaustiņus: darbību taustiņu + Esc."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Lieliski!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Jūs sekmīgi veicāt atgriešanās žestu."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Pāreja uz sākuma ekrānu"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Lai jebkurā brīdī pārietu uz sākuma ekrānu, ar trim pirkstiem velciet augšup no ekrāna apakšdaļas."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Lieliski!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Jūs sekmīgi veicāt sākuma ekrāna atvēršanas žestu."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Nesen izmantoto lietotņu skatīšana"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Skārienpaliktnī ar trīs pirkstiem velciet augšup un turiet."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Lieliski!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Jūs sekmīgi veicāt nesen izmantoto lietotņu skatīšanas žestu."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Darbību taustiņš"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Lai piekļūtu savām lietotnēm, tastatūrā nospiediet darbību taustiņu."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Apsveicam!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Jūs pabeidzāt darbību taustiņa žesta apmācību.\n\nNospiežot darbību taustiņu un taustiņu “/”, tiks parādīti visi pieejamie īsinājumtaustiņi."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastatūras fona apgaismojums"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Līmenis numur %1$d, kopā ir %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Mājas kontrolierīces"</string> @@ -1436,6 +1450,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Rediģēts"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Lai skatītu, atbloķējiet"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstuāla pamācība"</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> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 86c93acada52..708135dbc006 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Вклучено"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Вклучено: <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Исклучено"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Поставете"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Разговори"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Избриши ги сите бесчујни известувања"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Известувањата се паузирани од „Не вознемирувај“"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Нема известувања}=1{Известувањата ги паузираше {mode}}=2{Известувањата ги паузираа {mode} и уште еден режим}one{Известувањата ги паузираа {mode} и уште # режим}other{Известувањата ги паузираа {mode} и уште # режими}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Прикажи демо-режим"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Етернет"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Аларм"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Поставете за да купувате побрзо и побезбедно преку вашиот телефон"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Прикажи ги сите"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Научете движења за допирната подлога"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Движете се со користење на тастатурата и допирната подлога"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Научете движења за допирната подлога, кратенки од тастатурата и друго"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Движење за назад"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Движење за почетен екран"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Прегледајте ги неодамнешните апликации"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"За да се вратите назад, повлечете налево или надесно со три прста каде било на допирната подлога.\n\nЗа ова може да ја користите и кратенката од тастатурата Action + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Одлично сторено!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Го научивте движењето за враќање назад."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Одете на почетниот екран"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"За да одите на вашиот почетен екран кога сакате, повлечете нагоре со три прсти од дното на екранот."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Одлично!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Го научивте движењето за враќање на почетниот екран."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Прегледајте ги неодамнешните апликации"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Повлечете нагоре и задржете со три прста на допирната подлога."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Одлично!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Го завршивте движењето за прегледување на неодамнешните апликации."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Копче за дејство"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"За да пристапите до апликациите, притиснете го копчето за дејство на тастатурата."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Честитки!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Го научивте движењето со копчето за дејство.\n\nДејство + / ги прикажува сите кратенки што ги имате на располагање."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Осветлување на тастатура"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Ниво %1$d од %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Контроли за домот"</string> @@ -1436,6 +1450,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Притиснете го копчето за дејство на тастатурата за да ги видите сите апликации"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Редактирано"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Отклучете за приказ"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Контекстуално образование"</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> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 6958679712e6..28fd77d5ac0b 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"ഓണാണ്"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"ഓണാണ് • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ഓഫാണ്"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"സജ്ജീകരിക്കുക"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"സംഭാഷണങ്ങൾ"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"എല്ലാ നിശബ്ദ അറിയിപ്പുകളും മായ്ക്കുക"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'ശല്യപ്പെടുത്തരുത്\' വഴി അറിയിപ്പുകൾ താൽക്കാലികമായി നിർത്തി"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{അറിയിപ്പുകൾ ഒന്നുമില്ല}=1{{mode}, അറിയിപ്പുകൾ താൽക്കാലികമായി നിർത്തിയിരിക്കുന്നു}=2{{mode} എന്നതും മറ്റൊരു മോഡും, അറിയിപ്പുകൾ താൽക്കാലികമായി നിർത്തിയിരിക്കുന്നു}other{{mode} എന്നതും മറ്റ് # മോഡുകളും, അറിയിപ്പുകൾ താൽക്കാലികമായി നിർത്തിയിരിക്കുന്നു}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> ഓണാണ്"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"നിങ്ങളുടെ ഫോൺ ഉപയോഗിച്ച് വാങ്ങലുകൾ വേഗത്തിലും സുരക്ഷിതമായും നടത്താനുള്ള സജ്ജീകരണം നടത്തുക"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"എല്ലാം കാണിക്കുക"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"ടച്ച്പാഡ് ജെസ്ച്ചറുകൾ മനസ്സിലാക്കുക"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"നിങ്ങളുടെ കീപാഡ്, ടച്ച്പാഡ് എന്നിവ ഉപയോഗിച്ച് നാവിഗേറ്റ് ചെയ്യുക"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"ടച്ച്പാഡ് ജെസ്ച്ചറുകൾ, കീബോർഡ് കുറുക്കുവഴികൾ എന്നിവയും മറ്റും മനസ്സിലാക്കുക"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"\'മടങ്ങുക\' ജെസ്ച്ചർ"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ഹോം ജെസ്ച്ചർ"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"അടുത്തിടെയുള്ള ആപ്പുകൾ കാണുക"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"പൂർത്തിയായി"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"മടങ്ങുക"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"തിരികെ പോകാൻ, ടച്ച്പാഡിൽ എവിടെയെങ്കിലും മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് ഇടത്തേക്കോ വലത്തേക്കോ സ്വൈപ്പ് ചെയ്യുക.\n\nഇതിന് Action + ESC കീബോഡ് കുറുക്കുവഴികളും നിങ്ങൾക്ക് ഉപയോഗിക്കാം."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"കൊള്ളാം!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"മടങ്ങുക ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ഹോമിലേക്ക് പോകൂ"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ഏതുസമയത്തും ഹോം സ്ക്രീനിലേക്ക് പോകാൻ, മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് സ്ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യൂ."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"കൊള്ളാം!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"ഹോമിലേക്ക് പോകുക ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"അടുത്തിടെയുള്ള ആപ്പുകൾ കാണുക"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"നിങ്ങളുടെ ടച്ച്പാഡിൽ മൂന്ന് വിരലുകൾ കൊണ്ട് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്ത് പിടിക്കുക."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"കൊള്ളാം!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"അടുത്തിടെയുള്ള ആപ്പുകൾ കാണുക എന്ന ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Action കീ"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"നിങ്ങളുടെ ആപ്പുകൾ ആക്സസ് ചെയ്യാൻ, നിങ്ങളുടെ കീബോർഡിലെ Action കീ അമർത്തുക."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"അഭിനന്ദനങ്ങൾ!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"നിങ്ങൾ Action കീ ജെസ്ച്ചർ പൂർത്തിയാക്കി.\n\nനിങ്ങൾക്ക് ലഭ്യമാകുന്ന എല്ലാ കുറുക്കുവഴികളും Action + / കാണിക്കുന്നു."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"കീബോഡ് ബാക്ക്ലൈറ്റ്"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d-ൽ %1$d-ാമത്തെ ലെവൽ"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ഹോം കൺട്രോളുകൾ"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"എല്ലാ ആപ്പുകളും കാണാൻ, നിങ്ങളുടെ കീബോർഡിലെ ആക്ഷൻ കീ അമർത്തുക"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"മറച്ചത്"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"കാണാൻ, അൺലോക്ക് ചെയ്യുക"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"സന്ദർഭോചിത വിദ്യാഭ്യാസം"</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> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 95ff970ed0f4..dfd239838f54 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Асаалттай"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Асаасан • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Унтраалттай"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Тохируулах"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Харилцан яриа"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Бүх чимээгүй мэдэгдлийг арилгах"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Бүү саад бол горимын түр зогсоосон мэдэгдэл"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Мэдэгдэл байхгүй}=1{Мэдэгдлийг {mode} түр зогсоосон}=2{Мэдэгдлийг {mode} болон өөр нэг горим түр зогсоосон}other{Мэдэгдлийг {mode} болон өөр # горим түр зогсоосон}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> асаалттай байна"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Утсаараа илүү хурдан, аюулгүй худалдан авалт хийхийн тулд тохируулгыг авна уу"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Бүгдийг харуулах"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Мэдрэгч самбарын зангааг мэдэж аваарай"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Гар эсвэл мэдрэгч самбараа ашиглан шилжээрэй"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Мэдрэгч самбарын зангаа, товчлуурын шууд холбоос болон бусад зүйлийг мэдэж аваарай"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Буцах зангаа"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Үндсэн нүүрний зангаа"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Саяхны аппуудыг харах"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Болсон"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Буцах"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Буцахын тулд мэдрэгч самбар дээр гурван хуруугаар хүссэн газраа зүүн эсвэл баруун тийш шударна уу.\n\nТа мөн үүнийг хийхэд Action + ESC товчлуурын шууд холбоосыг ашиглах боломжтой."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Үнэхээр сайн ажиллалаа!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Та буцах зангааг гүйцэтгэлээ."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Үндсэн нүүр лүү очих"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Үндсэн нүүр лүүгээ хүссэн үедээ очихын тулд дэлгэцийнхээ доод талаас гурван хуруугаараа дээш шударна уу."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Янзтай!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Та үндсэн нүүр лүү очих зангааг гүйцэтгэлээ."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Саяхны аппуудыг харах"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Мэдрэгч самбар дээрээ гурван хуруугаа ашиглан дээш шудраад, удаан дарна уу."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Сайн байна!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Та саяхны аппуудыг харах зангааг гүйцэтгэсэн."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Тусгай товчлуур"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Аппууддаа хандахын тулд гар дээр тань байх тусгай товчлуурыг дарна уу."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Баяр хүргэе!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Та тусгай товчлуурын зангааг гүйцэтгэлээ.\n\nТусгай товчлуур болох + / нь танд боломжтой бүх товчлолыг харуулна."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Гарын арын гэрэл"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d-с %1$d-р түвшин"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Гэрийн удирдлага"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Бүх аппаа харахын тулд гар дээр тань байх тусгай товчлуурыг дарна уу"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Хассан"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Харахын тулд түгжээг тайлна уу"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Хам сэдэвт боловсрол"</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> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 14739299f2ff..db2ed93da0a9 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"सुरू आहे"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"सुरू • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"बंद आहे"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"सेट करा"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"संभाषणे"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"सर्व सायलंट सूचना साफ करा"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"व्यत्यय आणून नकाद्वारे सूचना थांबवल्या"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{कोणतेही नोटिफिकेशन नाही}=1{{mode} द्वारे नोटिफिकेशन थांबवली आहेत}=2{{mode} द्वारे आणि आणखी एका मोडद्वारे नोटिफिकेशन थांबवली आहेत}other{{mode} द्वारे आणि आणखी # मोडद्वारे नोटिफिकेशन थांबवली आहेत}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> हे सुरू आहे"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"तुमचा फोन वापरून जलदरीत्या, अधिक सुरक्षित खरेदी करण्यासाठी सेट करा"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"सर्व दाखवा"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"टचपॅड जेश्चर जाणून घ्या"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"तुमचा कीबोर्ड आणि टचपॅड वापरून नेव्हिगेट करा"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"टचपॅड जेश्चर, कीबोर्ड शॉर्टकट आणि आणखी बरेच काही जाणून घ्या"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"मागे जा जेश्चर"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"होम जेश्चर"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"अलीकडील अॅप्स पहा"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"पूर्ण झाले"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"मागे जा"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"मागे जाण्यासाठी, तीन बोटांनी टचपॅडवर कुठेही डावीकडे किंवा उजवीकडे स्वाइप करा.\n\nतुम्ही यासाठी Action + ESC हा कीबोर्ड शॉर्टकटदेखील वापरू शकता."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"उत्तम कामगिरी!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"तुम्ही गो बॅक जेश्चर पूर्ण केले."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"होमवर जा"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"कधीही तुमच्या होम स्क्रीनवर जाण्यासाठी, तीन बोटांनी तुमच्या स्क्रीनच्या तळापासून स्वाइप करा."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"छान!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"तुम्ही गो होम जेश्चर पूर्ण केले आहे."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"अलीकडील अॅप्स पहा"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"तुमच्या टचपॅडवर तीन बोटांनी वरती आणि खाली स्वाइप करा."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"उत्तम कामगिरी!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"तुम्ही अलीकडील ॲप्स पाहण्याचे जेश्चर पूर्ण केले आहे."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"अॅक्शन की"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"तुमची ॲप्स अॅक्सेस करण्यासाठी, तुमच्या कीबोर्डवरील अॅक्शन की प्रेस करा."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"अभिनंदन!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"तुम्ही अॅक्शन की जेश्चर पूर्ण केले आहे.\n\nकृती + / हे तुमच्याकडे उपलब्ध असलेले सर्व शॉर्टकट दाखवते."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"कीबोर्ड बॅकलाइट"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d पैकी %1$d पातळी"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"होम कंट्रोल"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"तुमची सर्व ॲप्स पाहण्यासाठी, तुमच्या कीबोर्डवरील अॅक्शन की प्रेस करा"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"रिडॅक्ट केलेले"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"पाहण्यासाठी अनलॉक करा"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"संदर्भीय शिक्षण"</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> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index ed3a0bc3d737..abdb32fceebc 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -440,7 +440,7 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Hidup"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Pada • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Mati"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Sediakan"</string> + <string name="zen_mode_set_up" msgid="8231201163894922821">"Tidak ditetapkan"</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> @@ -573,8 +573,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Perbualan"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Kosongkan semua pemberitahuan senyap"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Pemberitahuan dijeda oleh Jangan Ganggu"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Tiada pemberitahuan}=1{Pemberitahuan dijeda oleh {mode}}=2{Pemberitahuan dijeda oleh {mode} dan satu lagi mod yang lain}other{Pemberitahuan dijeda oleh {mode} dan # mod yang lain}}"</string> <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> @@ -706,6 +705,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Tunjukkan mod tunjuk cara"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Penggera"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> dihidupkan"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Buat persediaan untuk membuat pembelian yang lebih pantas dan selamat dengan telefon anda"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Tunjukkan semua"</string> @@ -1405,26 +1405,26 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Ketahui gerak isyarat pad sentuh"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigasi menggunakan papan kekunci dan pad sentuh anda"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Ketahui gerak isyarat pad sentuh, pintasan papan kekunci dan pelbagai lagi"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gerak isyarat kembali"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gerak isyarat pergi ke laman utama"</string> + <string name="touchpad_tutorial_back_gesture_button" msgid="3104716365403620315">"Kembali"</string> + <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Akses laman utama"</string> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Lihat apl terbaharu"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Selesai"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kembali"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Untuk kembali, leret ke kiri atau ke kanan menggunakan tiga jari di mana-mana sahaja pada pad sentuh.\n\nAnda juga boleh menggunakan pintasan papan kekunci Action + ESC untuk kembali."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Syabas!"</string> + <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Leret ke kiri atau kanan menggunakan tiga jari pada pad sentuh anda"</string> + <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Bagus!"</string> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Anda telah melengkapkan gerak isyarat undur."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Akses laman utama"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Untuk mengakses skrin utama anda pada bila-bila masa, leret ke atas menggunakan tiga jari daripada bahagian bawah skrin anda."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Bagus!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Anda telah melengkapkan gerak isyarat akses laman utama."</string> + <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Leret ke atas dengan tiga jari pada pad sentuh anda"</string> + <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Bagus!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Anda telah melengkapkan gerak isyarat akses laman utama"</string> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Lihat apl terbaharu"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Leret ke atas dan tahan menggunakan tiga jari pada pad sentuh anda."</string> + <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Leret ke atas dan tahan menggunakan tiga jari pada pad sentuh anda"</string> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Syabas!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Anda melengkapkan gerak isyarat lihat apl terbaharu."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Kekunci tindakan"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Untuk mengakses semua apl anda, tekan kekunci tindakan pada papan kekunci anda."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Tahniah!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Anda telah melengkapkan gerak isyarat kekunci tindakan.\n\nTindakan + / menunjukkan semua pintasan anda yang tersedia."</string> + <string name="tutorial_action_key_title" msgid="8172535792469008169">"Lihat semua apl"</string> + <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Tekan kekunci tindakan pada papan kekunci anda"</string> + <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Syabas!"</string> + <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Anda telah melengkapkan gerak isyarat lihat semua apl"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Cahaya latar papan kekunci"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Tahap %1$d daripada %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kawalan Rumah"</string> @@ -1436,6 +1436,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Untuk melihat semua apl anda, tekan kekunci tindakan pada papan kekunci anda"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Disunting"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Buka kunci untuk melihat"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Pendidikan kontekstual"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Gunakan pad sentuh anda untuk kembali"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Leret ke kiri atau ke kanan dengan tiga jari. Ketik dan ketahui lebih lanjut tentang gerak isyarat."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Gunakan pad sentuh untuk mengakses laman utama"</string> @@ -1444,8 +1445,8 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Leret ke atas, tahan dengan tiga jari. Ketik untuk mengetahui lebih lanjut tentang gerak isyarat."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gunakan papan kekunci anda untuk melihat semua apl"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tekan kekunci tindakan pada bila-bila masa. Ketik dan ketahui lebih lanjut tentang gerak isyarat."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"Kini ciri amat malap merupakan sebahagian daripada peluncur kecerahan"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Kini anda boleh menjadikan skrin amat malap dengan merendahkan lebih lagi tahap kecerahan.\n\nMemandangkan ciri ini kini merupakan sebahagian daripada peluncur kecerahan, pintasan amat malap dialih keluar."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"Ciri amat malap kini bergabung dengan peluncur kecerahan"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Skrin boleh dijadikan amat malap dengan menurunkan lagi tahap kecerahannya.\n\nOleh sebab ciri ini telah bergabung dengan peluncur kecerahan, pintasan amat malap dialih keluar."</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"Alih keluar pintasan amat malap"</string> <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"Pintasan amat malap dialih keluar"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Kesambungan"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index ea10ec267512..f4f337b05dee 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"ဖွင့်"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"ဖွင့် • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ပိတ်"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"စနစ်ထည့်သွင်းရန်"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"စကားဝိုင်းများ"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"အသံတိတ် အကြောင်းကြားချက်များအားလုံးကို ရှင်းလင်းရန်"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"အကြောင်းကြားချက်များကို \'မနှောင့်ယှက်ရ\' က ခေတ္တရပ်ထားသည်"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{အကြောင်းကြားချက် မရှိပါ}=1{{mode} က ခဏရပ်ထားသော အကြောင်းကြားချက်များ}=2{{mode} နှင့် အခြားမုဒ်တစ်ခုက ခဏရပ်ထားသော အကြောင်းကြားချက်များ}other{{mode} နှင့် အခြားမုဒ် # ခုက ခဏရပ်ထားသော အကြောင်းကြားချက်များ}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> ဖွင့်ထားသည်"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"သင့်ဖုန်းဖြင့် ပိုမိုမြန်ဆန်၊ ပိုမိုစိတ်ချရသော ဝယ်ယူမှုများ ပြုလုပ်ရန် စတင်သတ်မှတ်ပါ"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"အားလုံးပြရန်"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"တာ့ချ်ပက်လက်ဟန်များကို လေ့လာပါ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"သင်၏ ကီးဘုတ်နှင့် တာ့ချ်ပက်တို့ကိုသုံး၍ လမ်းညွှန်ခြင်း"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"တာ့ချ်ပက်လက်ဟန်များ၊ လက်ကွက်ဖြတ်လမ်းများ စသည်တို့ကို လေ့လာပါ"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"နောက်သို့ လက်ဟန်"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ပင်မစာမျက်နှာ လက်ဟန်"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"မကြာသေးမီကအက်ပ်များကို ကြည့်ရန်"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ပြီးပြီ"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ပြန်သွားရန်"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"နောက်ပြန်သွားရန် တာ့ချ်ပက်ပေါ်ရှိ မည်သည့်နေရာ၌မဆို လက်သုံးချောင်းဖြင့် ဘယ် (သို့) ညာသို့ ပွတ်ဆွဲပါ။\n\n၎င်းအတွက် လက်ကွက်ဖြတ်လမ်း Action + ESC ကိုလည်း သုံးနိုင်သည်။"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"တော်ပါပေသည်။"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"နောက်သို့လက်ဟန် အပြီးသတ်လိုက်ပါပြီ"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ပင်မစာမျက်နှာသို့ သွားရန်"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ပင်မစာမျက်နှာသို့ အချိန်မရွေးသွားရန် စခရင်အောက်ခြေမှ အပေါ်သို့ လက်သုံးချောင်းဖြင့် ပွတ်ဆွဲပါ။"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"ကောင်းသည်။"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"ပင်မစာမျက်နှာသို့သွားသည့် လက်ဟန် အပြီးသတ်လိုက်ပါပြီ။"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"မကြာသေးမီကအက်ပ်များကို ကြည့်ခြင်း"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"သင့်တာ့ချ်ပက်တွင် လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပြီး ဖိထားပါ။"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"တော်ပါပေသည်။"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"မကြာသေးမီကအက်ပ်များကို ကြည့်ခြင်းလက်ဟန် သင်ခန်းစာပြီးပါပြီ။"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"လုပ်ဆောင်ချက်ကီး"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"သင့်အက်ပ်များသုံးရန် ကီးဘုတ်ပေါ်ရှိ လုပ်ဆောင်ချက်ကီးကို နှိပ်ပါ။"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"ဂုဏ်ယူပါသည်။"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"လုပ်ဆောင်ချက်ကီး လက်ဟန် အပြီးသတ်လိုက်ပါပြီ။\n\nလုပ်ဆောင်ချက် + / သည် ရရှိနိုင်သော ဖြတ်လမ်းအားလုံးကို ပြသည်။"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ကီးဘုတ်နောက်မီး"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"အဆင့် %2$d အနက် %1$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"အိမ်ထိန်းချုပ်မှုများ"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"သင့်အက်ပ်အားလုံးကြည့်ရန် ကီးဘုတ်ပေါ်ရှိ လုပ်ဆောင်ချက်ကီးကို နှိပ်ပါ"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"အစားထိုးထားသည်"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ကြည့်ရန် ဖွင့်ပါ"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"အကြောင်းအရာအလိုက် ပညာရေး"</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> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 6ce048e4b673..f98799aade14 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"På"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"På • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Av"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Konfigurer"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Administrer i innstillingene"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Ingen aktive moduser}=1{{mode} er aktiv}other{# moduser er aktive}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Samtaler"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Fjern alle lydløse varsler"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Varsler er satt på pause av «Ikke forstyrr»"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Ingen varsler}=1{Varsler er satt på pause av {mode}}=2{Varsler er satt på pause av {mode} og én modus til}other{Varsler er satt på pause av {mode} og # moduser til}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Vis demo-modus"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Legg til en betalingsmåte for å gjennomføre kjøp raskere og sikrere med telefonen"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Vis alle"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Lær deg styreflatebevegelser"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Naviger med tastaturet og styreflaten"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Lær deg styreflatebevegelser, hurtigtaster med mer"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Tilbakebevegelse"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Startskjermbevegelse"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Se nylige apper"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Ferdig"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gå tilbake"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"For å gå tilbake, sveip mot høyre eller venstre med tre fingre hvor som helst på styreflaten.\n\nDu kan også gjøre dette med hurtigtasten Action + Esc."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Bra jobbet!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Du har fullført bevegelsen for å gå tilbake."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Gå til startsiden"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"For å gå til startskjermen, sveip opp med tre fingre fra bunnen av skjermen når som helst."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Bra!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Du har fullført bevegelsen for å gå til startskjermen."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Se nylige apper"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Sveip opp og hold med tre fingre på styreflaten."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Bra jobbet!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Du har fullført bevegelsen for å se nylige apper."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Handlingstast"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"For å åpne appene dine, trykk på handlingstasten på tastaturet."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Gratulerer!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Du har fullført bevegelsen for handlingstasten.\n\nHandling + / viser alle tilgjengelige snarveier."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Bakgrunnslys for tastatur"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivå %1$d av %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Hjemkontroller"</string> @@ -1436,6 +1450,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"For å se alle appene dine, trykk på handlingstasten på tastaturet"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Fjernet"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Lås opp for å se"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstuell opplæring"</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> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 01419b45a82e..2c8778f8cec6 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"अन छ"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"अन छ • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"अफ छ"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"सेटअप गर्नुहोस्"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"वार्तालापहरू"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"सबै मौन सूचनाहरू हटाउनुहोस्"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"बाधा नपुऱ्याउनुहोस् नामक मोडमार्फत पज पारिएका सूचनाहरू"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{कुनै पनि नोटिफिकेसन छैन}=1{{mode} ले गर्दा नोटिफिकेसनहरू पज गरिएका छन्}=2{{mode} र अन्य एक मोडले गर्दा नोटिफिकेसनहरू पज गरिएका छन्}other{{mode} र अन्य # वटा मोडले गर्दा नोटिफिकेसनहरू पज गरिएका छन्}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> अन छ"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"फोनमार्फत अझ छिटो र थप सुरक्षित तरिकाले खरिद गर्न भुक्तानी विधि सेटअप गर्नुहोस्"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"सबै देखाउनुहोस्"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"टचप्याड जेस्चर प्रयोग गर्न सिक्नुहोस्"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"किबोर्ड र टचप्याड प्रयोग गरी नेभिगेट गर्नुहोस्"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"टचप्याड जेस्चर, किबोर्डका सर्टकट र अन्य कुरा प्रयोग गर्न सिक्नुहोस्"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ब्याक जेस्चर"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"होम जेस्चर"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"हालसालै चलाइएका एपहरू हेर्नुहोस्"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"सम्पन्न भयो"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"पछाडि जानुहोस्"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"पछाडि जान तीन वटा औँलाले टचप्याडमा कतै छोएर बायाँ वा दायाँतिर स्वाइप गर्नुहोस्।\n\nतपाईं यसका लागि किबोर्डको सर्टकट \"Action + ESC\" पनि प्रयोग गर्न सक्नुहुन्छ।"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"अद्भुत!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"तपाईंले \'पछाडि जानुहोस्\' नामक इसारा प्रयोग गर्ने तरिका सिक्नुभयो।"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"होमपेजमा जानुहोस्"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"जुनसुकै बेला आफ्नो होम स्क्रिनमा जान स्क्रिनको फेदबाट तीन वटा औँलाले माथितिर स्वाइप गर्नुहोस्।"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"राम्रो!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"तपाईंले \"होम स्क्रिनमा जानुहोस्\" नामक जेस्चर प्रयोग गर्ने तरिका सिक्नुभयो।"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"हालसालै चलाइएका एपहरू हेर्नुहोस्"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"तीन वटा औँला प्रयोग गरी टचप्याडमा माथितिर स्वाइप गर्नुहोस् र होल्ड गर्नुहोस्।"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"अद्भुत!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"तपाईंले हालसालै चलाइएका एपहरू हेर्ने जेस्चर पूरा गर्नुभएको छ।"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"एक्सन की"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"आफ्ना एपहरू एक्सेस गर्न आफ्नो किबोर्डमा भएको एक्सन की थिच्नुहोस्।"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"बधाई छ!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"तपाईंले एक्सन की थिचेर गरिने जेस्चर प्रयोग गर्ने तरिका सिक्नुभयो।\n\nएक्सन + / थिच्नुभयो भने उपलब्ध सबै सर्टकटहरू देखिन्छन्।"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"किबोर्ड ब्याकलाइट"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d मध्ये %1$d औँ स्तर"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"होम कन्ट्रोलहरू"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"आफ्ना सबै एपहरू हेर्न आफ्नो किबोर्डमा भएको एक्सन की थिच्नुहोस्"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"जानकारी लुकाउन सम्पादन गरिएको"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"हेर्नका लागि अनलक गर्नुहोस्"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"सान्दर्भिक शिक्षा"</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> diff --git a/packages/SystemUI/res/values-night/styles.xml b/packages/SystemUI/res/values-night/styles.xml index 7bd4ca8b940b..17ba2e5c10c4 100644 --- a/packages/SystemUI/res/values-night/styles.xml +++ b/packages/SystemUI/res/values-night/styles.xml @@ -63,10 +63,4 @@ <style name="ShortcutHelperTheme" parent="@style/ShortcutHelperThemeCommon"> <item name="android:windowLightNavigationBar">false</item> </style> - - <style name="ContextualEduDialog" parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar"> - <!-- To make the dialog wrap to content when the education text is short --> - <item name="windowMinWidthMajor">0%</item> - <item name="windowMinWidthMinor">0%</item> - </style> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 325e361686c5..cd20a29329d7 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Aan"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Aan • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Uit"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Instellen"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Beheren via instellingen"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Geen actieve modi}=1{{mode} is actief}other{# modi zijn actief}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Gesprekken"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Alle stille meldingen wissen"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Meldingen onderbroken door \'Niet storen\'"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Geen meldingen}=1{Meldingen onderbroken door {mode}}=2{Meldingen onderbroken door {mode} en 1 andere modus}other{Meldingen onderbroken door {mode} en # andere modi}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Demomodus tonen"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Wekker"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> staat aan"</string> <string name="wallet_title" msgid="5369767670735827105">"Portemonnee"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Zorg dat je sneller en beter beveiligd aankopen kunt doen met je telefoon"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Alles tonen"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Leer touchpadgebaren die je kunt gebruiken"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigeren met je toetsenbord en touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Leer meer over onder andere touchpadgebaren en sneltoetsen"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gebaar voor terug"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gebaar voor startscherm"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Recente apps bekijken"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klaar"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Terug"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Als je wilt teruggaan, swipe je met 3 vingers naar links of rechts op de touchpad.\n\nJe kunt hiervoor ook de sneltoets Actie + ESC gebruiken."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Goed bezig!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Je weet nu hoe je het gebaar voor terug maakt."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Naar startscherm"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Swipe met 3 vingers omhoog vanaf de onderkant van het scherm om naar het startscherm te gaan."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Mooi zo!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Je weet nu hoe je het gebaar Naar startscherm maakt."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Recente apps bekijken"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Swipe met 3 vingers omhoog en houd vast op je touchpad."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Goed werk!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Je weet nu hoe je het gebaar Recente apps bekijken maakt."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Actietoets"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Als je toegang tot je apps wilt krijgen, druk je op de actietoets op je toetsenbord."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Gefeliciteerd!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Je hebt het gebaar voor de actietoets uitgevoerd.\n\nActie + / toont alle beschikbare sneltoetsen."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Achtergrondverlichting van toetsenbord"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d van %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Bediening voor in huis"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Als je alle apps wilt bekijken, druk je op de actietoets op je toetsenbord"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Verborgen"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Ontgrendelen om te bekijken"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Contextuele educatie"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Je touchpad gebruiken om terug te gaan"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Swipe met 3 vingers naar links of rechts. Tik voor meer gebaren."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Je touchpad gebruiken om naar het startscherm te gaan"</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index e0349999acde..59e64621cbae 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"ଚାଲୁ ଅଛି"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"ଚାଲୁ ଅଛି • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ବନ୍ଦ ଅଛି"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"ସେଟ ଅପ କରନ୍ତୁ"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"ସମସ୍ତ ନୀରବ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଖାଲି କରନ୍ତୁ"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ବିକଳ୍ପ ଦ୍ୱାରା ବିଜ୍ଞପ୍ତି ପଜ୍ ହୋଇଛି"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ}=1{{mode} ଦ୍ୱାରା ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ବିରତ କରାଯାଇଛି}=2{{mode} ଏବଂ ଅନ୍ୟ ଏକ ମୋଡ ଦ୍ୱାରା ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ବିରତ କରାଯାଇଛି}other{{mode} ଏବଂ ଅନ୍ୟ # ମୋଡ ଦ୍ୱାରା ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ବିରତ କରାଯାଇଛି}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"ଡେମୋ ମୋଡ୍ ଦେଖାନ୍ତୁ"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"ଇଥରନେଟ୍"</string> <string name="status_bar_alarm" msgid="87160847643623352">"ଆଲାରାମ"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"ୱାଲେଟ୍"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"ଆପଣଙ୍କ ଫୋନ୍ ମାଧ୍ୟମରେ ଆହୁରି ଶୀଘ୍ର, ଅଧିକ ସୁରକ୍ଷିତ କ୍ରୟ କରିବା ପାଇଁ ସେଟ୍ ଅପ୍ କରନ୍ତୁ"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"ସବୁ ଦେଖାନ୍ତୁ"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"ଟଚପେଡର ଜେଶ୍ଚରଗୁଡ଼ିକ ବିଷୟରେ ଜାଣନ୍ତୁ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"ଆପଣଙ୍କ କୀବୋର୍ଡ ଏବଂ ଟଚପେଡ ବ୍ୟବହାର କରି ନାଭିଗେଟ କରନ୍ତୁ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"ଟଚପେଡ ଜେଶ୍ଚର, କୀବୋର୍ଡ ସର୍ଟକଟ ଏବଂ ଆହୁରି ଅନେକ କିଛି ବିଷୟରେ ଜାଣନ୍ତୁ"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ବେକ ଜେଶ୍ଚର"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ହୋମ ଜେଶ୍ଚର"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ବର୍ତ୍ତମାନର ଆପ୍ସ ଭ୍ୟୁ କରନ୍ତୁ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ହୋଇଗଲା"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ପଛକୁ ଫେରନ୍ତୁ"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ପଛକୁ ଫେରିବା ପାଇଁ ଯେ କୌଣସି ସ୍ଥାନରେ ତିନି ଆଙ୍ଗୁଠି ବ୍ୟବହାର କରି ବାମ କିମ୍ବା ଡାହାଣକୁ ସ୍ୱାଇପ କରନ୍ତୁ।\n\nଏଥିପାଇଁ ଆପଣ କୀବୋର୍ଡ ସର୍ଟକଟ ଆକ୍ସନ + ESC ମଧ୍ୟ ବ୍ୟବହାର କରିପାରିବେ।"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"ବଢ଼ିଆ କାମ!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ଆପଣ \'ପଛକୁ ଫେରନ୍ତୁ\' ଜେଶ୍ଚର ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ହୋମକୁ ଯାଆନ୍ତୁ"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ଯେ କୌଣସି ସମୟରେ ଆପଣଙ୍କ ହୋମ ସ୍କ୍ରିନକୁ ଯିବା ପାଇଁ ଆପଣଙ୍କ ସ୍କିନର ତଳୁ ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ।"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"ବଢ଼ିଆ!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"ଆପଣ \'ହୋମକୁ ଯାଆନ୍ତୁ\' ଜେଶ୍ଚର ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ବର୍ତ୍ତମାନର ଆପ୍ସ ଭ୍ୟୁ କରନ୍ତୁ"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"ଆପଣଙ୍କ ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠିକୁ ବ୍ୟବହାର କରି ଉପରକୁ ସ୍ୱାଇପ କରି ଧରି ରଖନ୍ତୁ।"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ବଢ଼ିଆ କାମ!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ଆପଣ ବର୍ତ୍ତମାନର ଆପ୍ସ ଜେଶ୍ଚରକୁ ଭ୍ୟୁ କରିବା ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"ଆକ୍ସନ କୀ"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"ଆପଣଙ୍କ ଆପ୍ସ ଆକ୍ସେସ କରିବା ପାଇଁ ଆପଣଙ୍କର କୀବୋର୍ଡରେ ଆକ୍ସନ କୀ\'କୁ ଦବାନ୍ତୁ।"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"ଅଭିନନ୍ଦନ!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"ଆପଣ ଆକ୍ସନ କୀ ଜେଶ୍ଚରକୁ ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।\n\nଆକ୍ସନ + / ଆପଣଙ୍କ ପାଖରେ ଉପଲବ୍ଧ ଥିବା ସମସ୍ତ ସଟକର୍ଟକୁ ଦେଖାଇଥାଏ।"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"କୀବୋର୍ଡ ବେକଲାଇଟ"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dରୁ %1$d ନମ୍ବର ଲେଭେଲ"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ହୋମ କଣ୍ଟ୍ରୋଲ୍ସ"</string> @@ -1436,6 +1450,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ଆପଣଙ୍କ ସମସ୍ତ ଆପ୍ସ ଭ୍ୟୁ କରିବା ପାଇଁ ଆପଣଙ୍କ କୀବୋର୍ଡରେ ଆକ୍ସନ କୀ\'କୁ ଦବାନ୍ତୁ"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ଲୁଚା ଯାଇଥିବା"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ଭ୍ୟୁ କରିବାକୁ ଅନଲକ କରନ୍ତୁ"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"ପ୍ରାସଙ୍ଗିକ ଶିକ୍ଷା"</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> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 9659930f23c9..4c6697d39f81 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"ਚਾਲੂ"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"<xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g> • \'ਤੇ"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ਬੰਦ"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"ਸੈੱਟਅੱਪ ਕਰੋ"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"ਗੱਲਾਂਬਾਤਾਂ"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"ਸਾਰੀਆਂ ਸ਼ਾਂਤ ਸੂਚਨਾਵਾਂ ਕਲੀਅਰ ਕਰੋ"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਵੱਲੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਰੋਕਿਆ ਗਿਆ"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{ਕੋਈ ਸੂਚਨਾ ਨਹੀਂ ਹੈ}=1{{mode} ਵੱਲੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ}=2{{mode} ਅਤੇ ਇੱਕ ਹੋਰ ਮੋਡ ਵੱਲੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ}other{{mode} ਅਤੇ # ਹੋਰ ਮੋਡਾਂ ਵੱਲੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> ਚਾਲੂ ਹੈ"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"ਆਪਣੇ ਫ਼ੋਨ ਨਾਲ ਜ਼ਿਆਦਾ ਤੇਜ਼ ਅਤੇ ਜ਼ਿਆਦਾ ਸੁਰੱਖਿਅਤ ਖਰੀਦਾਂ ਕਰਨ ਲਈ ਸੈੱਟਅੱਪ ਕਰੋ"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"ਸਭ ਦਿਖਾਓ"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"ਟੱਚਪੈਡ ਇਸ਼ਾਰਿਆਂ ਬਾਰੇ ਜਾਣੋ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"ਆਪਣੇ ਕੀ-ਬੋਰਡ ਅਤੇ ਟੱਚਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਨੈਵੀਗੇਟ ਕਰੋ"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"ਟੱਚਪੈਡ ਇਸ਼ਾਰੇ, ਕੀ-ਬੋਰਡ ਸ਼ਾਰਟਕੱਟ ਅਤੇ ਹੋਰ ਬਹੁਤ ਕੁਝ ਬਾਰੇ ਜਾਣੋ"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ਪਿੱਛੇ ਜਾਣ ਦਾ ਇਸ਼ਾਰਾ"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ਹੋਮ \'ਤੇ ਜਾਣ ਦਾ ਇਸ਼ਾਰਾ"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ਹਾਲੀਆ ਐਪਾਂ ਦੇਖੋ"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ਹੋ ਗਿਆ"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ਵਾਪਸ ਜਾਓ"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ਵਾਪਸ ਜਾਣ ਲਈ, ਟੱਚਪੈਡ \'ਤੇ ਕਿਤੇ ਵੀ ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ।\n\nਤੁਸੀਂ ਇਸ ਲਈ ਕੀ-ਬੋਰਡ ਸ਼ਾਰਟਕੱਟ Action + ESC ਦੀ ਵਰਤੋਂ ਵੀ ਕਰ ਸਕਦੇ ਹੋ।"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"ਬਹੁਤ ਵਧੀਆ!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ਤੁਸੀਂ \'ਵਾਪਸ ਜਾਓ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ।"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ਹੋਮ \'ਤੇ ਜਾਓ"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ਕਿਸੇ ਵੀ ਸਮੇਂ ਆਪਣੀ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਜਾਣ ਲਈ, ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ।"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"ਵਧੀਆ!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"ਤੁਸੀਂ \'ਹੋਮ \'ਤੇ ਜਾਓ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ।"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ਹਾਲੀਆ ਐਪਾਂ ਦੇਖੋ"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"ਆਪਣੇ ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ।"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ਬਹੁਤ ਵਧੀਆ!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ਤੁਸੀਂ \'ਹਾਲੀਆ ਐਪਾਂ ਦੇਖੋ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ ਹੈ।"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"ਕਾਰਵਾਈ ਕੁੰਜੀ"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"ਆਪਣੀਆਂ ਐਪਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਲਈ, ਆਪਣੇ ਕੀ-ਬੋਰਡ \'ਤੇ ਕਾਰਵਾਈ ਕੁੰਜੀ ਨੂੰ ਦਬਾਓ।"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"ਵਧਾਈਆਂ!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"ਤੁਸੀਂ \'ਕਾਰਵਾਈ ਕੁੰਜੀ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ।\n\nਕਾਰਵਾਈ ਬਟਨ ਅਤੇ / ਨੂੰ ਇਕੱਠੇ ਦਬਾਉਣ \'ਤੇ, ਤੁਹਾਡੇ ਕੋਲ ਉਪਲਬਧ ਸਾਰੇ ਸ਼ਾਰਟਕੱਟ ਦਿਖਦੇ ਹਨ।"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ਕੀ-ਬੋਰਡ ਬੈਕਲਾਈਟ"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d ਵਿੱਚੋਂ %1$d ਪੱਧਰ"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ਹੋਮ ਕੰਟਰੋਲ"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ਆਪਣੀਆਂ ਸਾਰੀਆਂ ਐਪਾਂ ਨੂੰ ਦੇਖਣ ਲਈ, ਆਪਣੇ ਕੀ-ਬੋਰਡ \'ਤੇ ਕਾਰਵਾਈ ਕੁੰਜੀ ਨੂੰ ਦਬਾਓ"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ਅਸਪਸ਼ਟ ਬਣਾਇਆ ਗਿਆ"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ਦੇਖਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"ਸੰਦਰਭੀ ਸਿੱਖਿਆ"</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> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 9c97423fccc7..f4efe0b5a985 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Wł."</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Włączone • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Wył."</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Skonfiguruj"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Zarządzaj w ustawieniach"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Brak aktywnych trybów}=1{Tryb {mode} jest aktywny}few{# tryby są aktywne}many{# trybów jest aktywnych}other{# trybu jest aktywne}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Rozmowy"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Usuń wszystkie ciche powiadomienia"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Powiadomienia wstrzymane przez tryb Nie przeszkadzać"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Brak powiadomień}=1{Powiadomienia są wstrzymane przez tryb {mode}}=2{Powiadomienia są wstrzymane przez tryb {mode} i 1 inny tryb}few{Powiadomienia są wstrzymane przez tryb {mode} i # inne tryby}many{Powiadomienia są wstrzymane przez tryb {mode} i # innych trybów}other{Powiadomienia są wstrzymane przez tryb {mode} i # innego trybu}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Pokaż tryb demonstracyjny"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Aplikacja <xliff:g id="MODENAME">%1$s</xliff:g> jest włączona"</string> <string name="wallet_title" msgid="5369767670735827105">"Portfel"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Skonfiguruj formę płatności, aby szybciej i bezpieczniej płacić telefonem za zakupy"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Pokaż wszystko"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Poznaj gesty na touchpada"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Nawiguj za pomocą klawiatury i touchpada"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Poznaj gesty na touchpada, skróty klawiszowe i inne funkcje"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gest przejścia wstecz"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gest przejścia na ekran główny"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Wyświetlanie ostatnich aplikacji"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotowe"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Wróć"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Aby przejść wstecz, przesuń 3 palcami w lewo lub w prawo w dowolnym miejscu touchpada.\n\nMożesz też użyć do tego skrótu klawiszowego Action + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Brawo!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Gest przejścia wstecz został opanowany."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Otwórz stronę główną"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Aby w dowolnym momencie wyświetlić ekran główny, przesuń od dołu ekranu w górę 3 palcami."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Super!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Gest przechodzenia na ekran główny został opanowany."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Wyświetlanie ostatnich aplikacji"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Przesuń w górę za pomocą 3 palców na touchpadzie i przytrzymaj."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Brawo!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Znasz już gest wyświetlania ostatnio używanych aplikacji."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Klawisz działania"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Aby uzyskać dostęp do aplikacji, naciśnij klawisz działania na klawiaturze."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Gratulacje!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Gest klawisza działania został opanowany.\n\nKlawisz działania + / pokazuje wszystkie dostępne skróty."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podświetlenie klawiatury"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Poziom %1$d z %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Sterowanie domem"</string> @@ -1436,6 +1449,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Usunięto"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Odblokuj, aby zobaczyć"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Edukacja kontekstowa"</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> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 399523e1aba2..b27242248da2 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Ativado • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desativado"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurar"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gerenciar nas configurações"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nenhum modo ativo}=1{{mode} está ativo}one{# modo está ativo}many{# de modos estão ativos}other{# modos estão ativos}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversas"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Apagar todas as notificações silenciosas"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificações pausadas pelo modo \"Não perturbe\""</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Sem notificações}=1{Notificações pausadas pelo modo {mode}}=2{Notificações pausadas por {mode} e mais um modo}one{Notificações pausadas por {mode} e mais # modo}many{Notificações pausadas por {mode} e mais # de modos}other{Notificações pausadas por {mode} e mais # modos}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Mostrar modo de demonstração"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Carteira"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Prepare tudo para fazer compras mais rápidas e seguras com seu smartphone"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar tudo"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Aprenda gestos do touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navegue usando o teclado e o touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Aprenda gestos do touchpad, atalhos do teclado e muito mais"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto de volta"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto de início"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ver os apps recentes"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluído"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para voltar, deslize para a esquerda ou direita usando 3 dedos em qualquer lugar do touchpad.\n\nVocê também pode usar o atalho de teclado Ação + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Muito bem!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Você concluiu o gesto para voltar."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir para a página inicial"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para acessar sua tela inicial a qualquer momento, deslize de baixo para cima na tela com três dedos."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Legal!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Você concluiu o gesto para acessar a tela inicial."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ver os apps recentes"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Deslize para cima e pressione com 3 dedos no touchpad."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Muito bem!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Você concluiu o gesto para ver os apps recentes."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tecla de ação"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Para acessar os apps, pressione a tecla de ação no teclado."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Parabéns!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Você concluiu o gesto da tecla de ação.\n\nA tecla de ação + / mostra todos os atalhos disponíveis."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Automação residencial"</string> @@ -1436,8 +1450,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Encoberto"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloquear para visualizar"</string> - <!-- no translation found for contextual_education_dialog_title (4630392552837487324) --> - <skip /> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Educação contextual"</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> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index e87564d915fc..cca6d7234a21 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Ativado • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desativado"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurar"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gerir nas definições"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nenhum modo ativo}=1{{mode} está ativo}many{# modos estão ativos}other{# modos estão ativos}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversas"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Limpar todas as notificações silenciosas"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificações colocadas em pausa pelo modo Não incomodar."</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Sem notificações}=1{Notificações pausadas pelo modo {mode}}=2{Notificações pausadas pelo modo {mode} e mais um modo}many{Notificações pausadas pelo modo {mode} e mais # modos}other{Notificações pausadas pelo modo {mode} e mais # modos}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Mostrar modo de demonstração"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"O modo <xliff:g id="MODENAME">%1$s</xliff:g> está ativado"</string> <string name="wallet_title" msgid="5369767670735827105">"Carteira"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configure para efetuar pagamentos mais rápidos e seguros com o seu telemóvel"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar tudo"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Aprenda gestos do touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navegue com o teclado e o touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Aprenda gestos do touchpad, atalhos de teclado e muito mais"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto para retroceder"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto para aceder ao ecrã principal"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ver apps recentes"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluir"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para retroceder, deslize rapidamente para a esquerda ou direita com 3 dedos em qualquer parte do touchpad.\n\nPara o fazer, também pode usar o atalho de teclado Ação + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Muito bem!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Concluiu o gesto para retroceder."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Aceder ao ecrã principal"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para aceder ao ecrã principal em qualquer altura, deslize rapidamente com 3 dedos de baixo para cima no ecrã."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Boa!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Concluiu o gesto para aceder ao ecrã principal."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ver apps recentes"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Deslize rapidamente para cima e mantenha premido com 3 dedos no touchpad."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Muito bem!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Concluiu o gesto para ver as apps recentes."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tecla de ação"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Para aceder às suas apps, prima a tecla de ação no teclado."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Parabéns!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Concluiu o gesto da tecla de ação.\n\nA ação + / mostra todos os atalhos que tem disponíveis."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz do teclado"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Controlos domésticos"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Para ver todas as suas apps, prima a tecla de ação no teclado"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Revisto"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloqueie para ver"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Educação contextual"</string> <string name="back_edu_notification_title" msgid="5624780717751357278">"Use o touchpad para retroceder"</string> <string name="back_edu_notification_content" msgid="2497557451540954068">"Deslize rapidamente para a esquerda ou direita com 3 dedos. Toque para aprender mais gestos."</string> <string name="home_edu_notification_title" msgid="6097902076909654045">"Use o touchpad para aceder ao ecrã principal"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 5c9679d73d41..b27242248da2 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Ativado • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Desativado"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurar"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gerenciar nas configurações"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nenhum modo ativo}=1{{mode} está ativo}one{# modo está ativo}many{# de modos estão ativos}other{# modos estão ativos}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversas"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Apagar todas as notificações silenciosas"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificações pausadas pelo modo \"Não perturbe\""</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Sem notificações}=1{Notificações pausadas pelo modo {mode}}=2{Notificações pausadas por {mode} e mais um modo}one{Notificações pausadas por {mode} e mais # modo}many{Notificações pausadas por {mode} e mais # de modos}other{Notificações pausadas por {mode} e mais # modos}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Mostrar modo de demonstração"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarme"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Carteira"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Prepare tudo para fazer compras mais rápidas e seguras com seu smartphone"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Mostrar tudo"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Aprenda gestos do touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navegue usando o teclado e o touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Aprenda gestos do touchpad, atalhos do teclado e muito mais"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto de volta"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto de início"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ver os apps recentes"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluído"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para voltar, deslize para a esquerda ou direita usando 3 dedos em qualquer lugar do touchpad.\n\nVocê também pode usar o atalho de teclado Ação + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Muito bem!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Você concluiu o gesto para voltar."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir para a página inicial"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para acessar sua tela inicial a qualquer momento, deslize de baixo para cima na tela com três dedos."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Legal!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Você concluiu o gesto para acessar a tela inicial."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ver os apps recentes"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Deslize para cima e pressione com 3 dedos no touchpad."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Muito bem!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Você concluiu o gesto para ver os apps recentes."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tecla de ação"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Para acessar os apps, pressione a tecla de ação no teclado."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Parabéns!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Você concluiu o gesto da tecla de ação.\n\nA tecla de ação + / mostra todos os atalhos disponíveis."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Automação residencial"</string> @@ -1436,6 +1450,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Encoberto"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Desbloquear para visualizar"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Educação contextual"</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> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 8c764910f638..4222b3d9542a 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Activat"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Activat • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Dezactivat"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Configurează"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Gestionează în setări"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Niciun mod activ}=1{{mode} este activ}few{# moduri sunt active}other{# de moduri sunt active}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Conversații"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Șterge toate notificările silențioase"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Notificări întrerupte prin „Nu deranja”"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Nicio notificare}=1{Notificările au fost întrerupte de {mode}}=2{Notificările au fost întrerupte de {mode} și de un alt mod}few{Notificările au fost întrerupte de {mode} și de alte # moduri}other{Notificările au fost întrerupte de {mode} și de alte # de moduri}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Afișează modul demonstrativ"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarmă"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> este activ"</string> <string name="wallet_title" msgid="5369767670735827105">"Portofel"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Configurează pentru a face achiziții mai rapide și mai sigure cu telefonul"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Afișează-le pe toate"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Învață gesturi pentru touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navighează folosind tastatura și touchpadul"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Învață gesturi pentru touchpad, comenzi rapide de la tastatură și altele"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gestul Înapoi"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gestul Ecran de pornire"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Vezi aplicațiile recente"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gata"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Înapoi"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Pentru a reveni, glisează spre stânga sau spre dreapta cu trei degete oriunde pe touchpad.\n\nPoți folosi și comanda rapidă de la tastatură Action + ESC pentru aceasta."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Excelent!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ai finalizat gestul Înapoi."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Înapoi la pagina de pornire"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Pentru a accesa oricând ecranul de pornire, glisează în sus cu trei degete din partea de jos a ecranului"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Bravo!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Ai finalizat gestul „accesează ecranul de pornire”."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Vezi aplicațiile recente"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Glisează în sus și ține apăsat cu trei degete pe touchpad."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Excelent!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Ai finalizat gestul pentru afișarea aplicațiilor recente."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tasta de acțiuni"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Pentru a accesa aplicațiile, apasă tasta de acțiuni de pe tastatură."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Felicitări!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Ai finalizat gestul cu tasta de acțiuni.\n\nAcțiune + / afișează toate comenzile rapide disponibile."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Iluminarea din spate a tastaturii"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivelul %1$d din %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Comenzi pentru locuință"</string> @@ -1436,6 +1449,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Ascunsă"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Deblochează pentru a afișa"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Educație contextuală"</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> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index c5b6479a9b15..0340a1e563f9 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Включено"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Вкл. • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Отключено"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Настроить"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Открыть настройки"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Включено 0 режимов}=1{Включен режим \"{mode}\"}one{Включен # режим}few{Включено # режима}many{Включено # режимов}other{Включено # режима}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Вас не будут отвлекать звуки и вибрация, за исключением сигналов будильника, напоминаний, уведомлений о мероприятиях и звонков от помеченных контактов. Вы по-прежнему будете слышать включенную вами музыку, видео, игры и т. д."</string> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Разговоры"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Отклонить все беззвучные уведомления"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"В режиме \"Не беспокоить\" уведомления заблокированы"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Уведомлений нет}=1{Режим \"{mode}\" приостанавливает уведомления}=2{Режим \"{mode}\" и ещё один режим приостанавливают уведомления}one{Режим \"{mode}\" и ещё # режим приостанавливают уведомления}few{Режим \"{mode}\" и ещё # режима приостанавливают уведомления}many{Режим \"{mode}\" и ещё # режимов приостанавливают уведомления}other{Режим \"{mode}\" и ещё # режима приостанавливают уведомления}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Перейти в демонстрационный режим"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Будильник"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g>: включено"</string> <string name="wallet_title" msgid="5369767670735827105">"Кошелек"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Расплачивайтесь через телефон быстро и безопасно."</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Показать все"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Узнайте о жестах на сенсорной панели."</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Навигация с помощью клавиатуры и сенсорной панели"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Узнайте о жестах на сенсорной панели, сочетаниях клавиш и многом другом."</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Жест \"назад\""</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жест \"на главный экран\""</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Жест \"Просмотр недавних приложений\""</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Чтобы вернуться назад, проведите по сенсорной панели тремя пальцами влево или вправо.\n\nВы также можете нажать клавишу действия + Esc."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Отлично!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Вы выполнили жест для перехода назад."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"На главный экран"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Чтобы перейти на главный экран, проведите снизу вверх тремя пальцами."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Неплохо!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Вы выполнили жест для перехода на главный экран."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Просмотр недавних приложений"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Проведите вверх по сенсорной панели тремя пальцами и удерживайте."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Отлично!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Вы выполнили жест для просмотра недавних приложений."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Клавиша действия"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Чтобы перейти к приложениям, нажмите клавишу действия на клавиатуре."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Готово!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Вы выполнили жест с клавишей действия.\n\nЧтобы посмотреть доступные сочетания, нажмите клавишу действия и \"/\"."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Подсветка клавиатуры"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Уровень %1$d из %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Управление домом"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Чтобы открыть список всех своих приложений, нажмите клавишу действия."</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Скрыто"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Разблокируйте экран, чтобы посмотреть."</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Контекстные подсказки"</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> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index ff0c28dbbf26..93f72584eb2e 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"ක්රියාත්මකයි"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"ක්රියාත්මකයි • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ක්රියාවිරහිතයි"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"පිහිටුවන්න"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"සංවාද"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"සියලු නිහඬ දැනුම්දීම් හිස් කරන්න"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"බාධා නොකරන්න මගින් විරාම කරන ලද දැනුම්දීම්"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{දැනුම්දීම් නැත}=1{{mode} මගින් දැනුම්දීම් විරාම කරන ලදි}=2{{mode} සහ තව එක ප්රකාරයක් මගින් දැනුම්දීම් විරාම කරන ලදි}one{{mode} සහ තව ප්රකාර #ක් මගින් දැනුම්දීම් විරාම කරන ලදි}other{{mode} සහ තව ප්රකාර #ක් මගින් දැනුම්දීම් විරාම කරන ලදි}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"ආදර්ශන ප්රකාරය පෙන්වන්න"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"එලාමය"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"ඔබගේ දුරකථනය සමඟ වඩා වේගවත්, වඩා සුරක්ෂිත මිලදී ගැනීම් සිදු කිරීමට සූදානම් වන්න"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"සියල්ල පෙන්වන්න"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"ස්පර්ශක පුවරු අභිනයන් ඉගෙන ගන්න"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"ඔබේ යතුරු පුවරුව සහ ස්පර්ශ පෑඩ් භාවිතයෙන් සංචාලනය කරන්න"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"ස්පර්ශ පෑඩ් අභිනයන්, යතුරුපුවරු කෙටිමං සහ තවත් දේ ඉගෙන ගන්න"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ආපසු අභිනය"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"නිවෙස් අභිනය"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"මෑත යෙදුම් බලන්න"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"නිමයි"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ආපස්සට යන්න"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"ආපසු යාමට, ස්පර්ශ පුවරුවවේ ඕනෑම තැනක ඇඟිලි තුනක් භාවිතයෙන් වමට හෝ දකුණට ස්වයිප් කරන්න.\n\nඔබට මේ සඳහා යතුරු පුවරු කෙටිමං ක්රියාව + ESC ද භාවිත කළ හැක."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"අනර්ඝ වැඩක්!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ඔබ ආපසු යාමේ ඉංගිතය සම්පූර්ණ කරන ලදි."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"මුල් පිටුවට යන්න"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ඕනෑම වේලාවක ඔබේ මුල් තිරයට යාමට, ඔබේ තිරයේ පහළ සිට ඇඟිලි තුනකින් ඉහළට ස්වයිප් කරන්න."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"කදිමයි!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"ඔබ මුල් පිටුවට යාමේ ඉංගිතය සම්පූර්ණ කළා."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"මෑත යෙදුම් බලන්න"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"ඉහළට ස්වයිප් කර ඔබේ ස්පර්ශ පුවරුව මත ඇඟිලි තුනක් භාවිතා කර සිටින්න."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"අනර්ඝ වැඩක්!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ඔබ මෑත යෙදුම් ඉංගිත බැලීම සම්පූර්ණ කර ඇත."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"ක්රියා යතුර"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"ඔබේ යෙදුම් වෙත ප්රවේශ වීමට, ඔබේ යතුරු පුවරුවෙහි ක්රියා යතුර ඔබන්න."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"සුබ පැතුම්!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"ඔබ ක්රියා යතුරු අභිනය සම්පූර්ණ කළා.\n\nක්රියාව + / ඔබට ලබා ගත හැකි සියලු කෙටිමං පෙන්වයි."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"යතුරු පුවරු පසු ආලෝකය"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dන් %1$d වැනි මට්ටම"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"නිවෙස් පාලන"</string> @@ -1436,6 +1450,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"ඔබේ සියලුම යෙදුම් බැලීමට, ඔබේ යතුරුපුවරුවේ ක්රියාකාරී යතුර ඔබන්න"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"නැවත සකස් කරන ලද"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"බැලීමට අගුළු හරින්න"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"සන්දර්භීය අධ්යාපනය"</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> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 16af11a26b94..e7c92634670f 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Zapnuté"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Zapnuté • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Vypnuté"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Nastaviť"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Správa v nastaveniach"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Žiadne aktívne režimy}=1{{mode} je aktívny}few{# režimy sú aktívne}many{# modes are active}other{# režimov je aktívnych}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzácie"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Vymazať všetky tiché upozornenia"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Upozornenia sú pozastavené režimom bez vyrušení"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Žiadne upozornenia}=1{Upozornenia boli pozastavené režimom {mode}}=2{Upozornenia boli pozastavené režimom {mode} a jedným ďalším}few{Upozornenia boli pozastavené režimom {mode} a # ďalšími}many{Notifications paused by {mode} and # other modes}other{Upozornenia boli pozastavené režimom {mode} a # ďalšími}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Zobraziť režim ukážky"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Budík"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Režim <xliff:g id="MODENAME">%1$s</xliff:g> je zapnutý"</string> <string name="wallet_title" msgid="5369767670735827105">"Peňaženka"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Nastavte si všetko potrebné na rýchlejšie a bezpečnejšie nákupy telefónom"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Zobraziť všetko"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Naučte sa gestá touchpadu"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Prechádzajte pomocou klávesnice a touchpadu"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Naučte sa gestá touchpadu, klávesové skratky a ďalšie funkcie"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto prechodu späť"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto prechodu domov"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Zobrazenie nedávnych aplikácií"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hotovo"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Prejsť späť"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Ak chcete prejsť späť, potiahnite kdekoľvek na touchpade troma prstami doľava alebo doprava.\n\nMôžete použiť aj klávesovú skratku, teda akčný kláves + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Skvelé!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Dokončili ste gesto na prechod späť."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Prechod na plochu"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Na plochu môžete kedykoľvek prejsť potiahnutím troma prstami zdola obrazovky."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Výborne!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Dokončili ste gesto na prechod na plochu."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Zobrazenie nedávnych aplikácií"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Potiahnite troma prstami na touchpade nahor a pridržte ich."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Skvelé!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Dokončili ste gesto na zobrazenie nedávnych aplikácií."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Akčný kláves"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Ak chcete získať prístup k aplikáciám, stlačte na klávesnici akčný kláves."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Blahoželáme!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Dokončili ste gesto akčného klávesa.\n\nStlačením kombinácie akčný kláves + / zobrazíte všetky skratky, ktoré máte k dispozícii"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podsvietenie klávesnice"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. úroveň z %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Ovládanie domácnosti"</string> @@ -1436,6 +1449,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Zamaskované"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Zobrazíte odomknutím"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontextová náuka"</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> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index e664810b82c0..701cdd1f1bfe 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -440,7 +440,7 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Vklopljeno"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Vklopljeno • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Izklopljeno"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Nastavitev"</string> + <string name="zen_mode_set_up" msgid="8231201163894922821">"Ni nastavljeno"</string> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Upravljanje v nastavitvah"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Ni aktivnih načinov}=1{Način {mode} je aktiven}one{# način je aktiven}two{# načina sta aktivna}few{# načini so aktivni}other{# načinov je aktivnih}}"</string> <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> @@ -573,8 +573,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Pogovori"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Brisanje vseh tihih obvestil"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Prikazovanje obvestil je začasno zaustavljeno z načinom »ne moti«"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Ni obvestil}=1{Prikazovanje obvestil je začasno zaustavljeno z načinom {mode}}=2{Prikazovanje obvestil je začasno zaustavljeno z načinom {mode} in še enim drugim načinom}one{Prikazovanje obvestil je začasno zaustavljeno z načinom {mode} in še # drugim načinom}two{Prikazovanje obvestil je začasno zaustavljeno z načinom {mode} in še # drugima načinoma}few{Prikazovanje obvestil je začasno zaustavljeno z načinom {mode} in še # drugimi načini}other{Prikazovanje obvestil je začasno zaustavljeno z načinom {mode} in še # drugimi načini}}"</string> <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> @@ -706,6 +705,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Prikaz predstavitvenega načina"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g>: Vklopljeno"</string> <string name="wallet_title" msgid="5369767670735827105">"Denarnica"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Nastavite možnost hitrejšega in varnejšega plačevanja s telefonom."</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Prikaži vse"</string> @@ -1405,26 +1405,26 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Učenje potez na sledilni ploščici"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Krmarjenje s tipkovnico in sledilno ploščico"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Učenje potez na sledilni ploščici, bližnjičnih tipk in drugega"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Poteza za pomik nazaj"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Poteza za začetni zaslon"</string> + <string name="touchpad_tutorial_back_gesture_button" msgid="3104716365403620315">"Nazaj"</string> + <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Pojdi na začetni zaslon"</string> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ogled nedavnih aplikacij"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Končano"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazaj"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Za pomik nazaj povlecite levo ali desno s tremi prsti kjer koli na sledilni ploščici.\n\nUporabite lahko tudi bližnjični tipki Action + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Odlično!"</string> + <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Na sledilni ploščici s tremi prsti povlecite levo ali desno"</string> + <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Odlično!"</string> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Izvedli ste potezo za pomik nazaj."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Pomik na začetni zaslon"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Za pomik na začetni zaslon lahko kadar koli s tremi prsti povlečete navzgor z dna zaslona."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Odlično!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Izvedli ste potezo za pomik na začetni zaslon."</string> + <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Na sledilni ploščici s tremi prsti povlecite navzgor"</string> + <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Odlično!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Izvedli ste potezo za pomik na začetni zaslon"</string> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ogled nedavnih aplikacij"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Na sledilni ploščici s tremi prsti povlecite navzgor in pridržite."</string> + <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Na sledilni ploščici s tremi prsti povlecite navzgor in pridržite"</string> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Odlično!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Izvedli ste potezo za ogled nedavnih aplikacij."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tipka za dejanja"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Za dostop do aplikacij pritisnite tipko za dejanja na tipkovnici."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Čestitamo!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Izvedli ste potezo za tipko za dejanja.\n\nČe hkrati pritisnete tipko za dejanja in poševnico naprej »/«, bodo prikazane vse razpoložljive bližnjice."</string> + <string name="tutorial_action_key_title" msgid="8172535792469008169">"Ogled vseh aplikacij"</string> + <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pritisnite tipko za dejanja na tipkovnici"</string> + <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Odlično!"</string> + <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Izvedli ste potezo za ogled vseh aplikacij"</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Osvetlitev tipkovnice"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Stopnja %1$d od %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrolniki za dom"</string> @@ -1436,6 +1436,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Za ogled vseh aplikacij pritisnite tipko za dejanja na tipkovnici"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Zakrito"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Odklenite za ogled"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstualno izobraževanje"</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> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index e70629f20cc9..20f7e822a139 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Aktiv"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Aktiv • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Joaktiv"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Konfiguro"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Menaxho te cilësimet"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Nuk ka modalitete aktive}=1{\"{mode}\" është aktiv}other{# modalitete janë aktive}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Bisedat"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Pastro të gjitha njoftimet në heshtje"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Njoftimet janë vendosur në pauzë nga modaliteti \"Mos shqetëso\""</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Asnjë njoftim}=1{Njoftimet u vendosën në pauzë nga {mode}}=2{Njoftimet u vendosën në pauzë nga {mode} dhe një modalitet tjetër}other{Njoftimet u vendosën në pauzë nga {mode} dhe # modalitete të tjera}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Shfaq modalitetin e demonstrimit"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Eternet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarmi"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Portofoli"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Konfiguro për të kryer pagesa më të shpejta dhe më të sigurta përmes telefonit"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Shfaqi të gjitha"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Mëso gjestet e bllokut me prekje"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigo duke përdorur tastierën dhe bllokun me prekje"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Mëso gjestet e bllokut me prekje, shkurtoret e tastierës etj."</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gjesti i kthimit prapa"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gjesti për të shkuar tek ekrani bazë"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Shiko aplikacionet e fundit"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"U krye"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kthehu prapa"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Për t\'u kthyer, rrëshqit shpejt majtas ose djathtas duke përdorur tri gishta kudo në bllokun me prekje.\n\nPër ta bërë këtë, mund të përdorësh gjithashtu shkurtoren e tastierës \"Action + ESC\"."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Punë e shkëlqyer!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"E ke përfunduar gjestin e kthimit prapa."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Shko tek ekrani bazë"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Për të shkuar tek ekrani bazë në çdo kohë, rrëshqit shpejt lart me tre gishta nga fundi i ekranit."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Bukur!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"E ke përfunduar gjestin e kalimit tek ekrani bazë."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Shiko aplikacionet e fundit"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Rrëshqit shpejt lart dhe mbaj shtypur me tre gishta në bllokun me prekje."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Punë e shkëlqyer!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Përfundove gjestin për shikimin e aplikacioneve të fundit."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Tasti i veprimit"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Për t\'u qasur në aplikacionet e tua, shtyp tastin e veprimit në tastierë."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Urime!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Ke përfunduar gjestin e tastit të veprimit.\n\nVeprimi + / shfaq të gjitha shkurtoret që janë të disponueshme për ty."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Drita e sfondit e tastierës"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveli: %1$d nga %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Kontrollet e shtëpisë"</string> @@ -1436,6 +1450,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Redaktuar"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Shkyçe për ta parë"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Edukimi kontekstual"</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> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 164b4aa246a9..f757cdcf1a6d 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Укључено"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Укљ. • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Искључено"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Подеси"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Управљајте у подешавањима"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Нема активних режима}=1{Активан је {mode} режим}one{Активан је # режим}few{Активна су # режима}other{Активно је # режима}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Неће вас узнемиравати звукови и вибрације осим за аларме, подсетнике, догађаје и позиваоце које наведете. И даље ћете чути све што одаберете да пустите, укључујући музику, видео снимке и игре."</string> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Конверзације"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Обришите сва нечујна обавештења"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Обавештења су паузирана режимом Не узнемиравај"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Нема обавештења}=1{Обавештења је паузирао {mode}}=2{Обавештења су паузирали {mode} и још један режим}one{Обавештења су паузирали {mode} и још # режим}few{Обавештења су паузирали {mode} и још # режима}other{Обавештења су паузирали {mode} и још # режима}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g>: укључено"</string> <string name="wallet_title" msgid="5369767670735827105">"Новчаник"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Обавите конфигурисање да бисте могли брже и сигурније да купујете помоћу телефона"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Прикажи све"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Научите покрете за тачпед"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Крећите се помоћу тастатуре и тачпeда"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Научите покрете за тачпед, тастерске пречице и друго"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Покрет за враћање"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Покрет за почетну страницу"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Прикажи недавно коришћене апликације"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Да бисте се вратили, превуците улево са три прста било где на тачпеду.\n\nМожете да користите и тастерску пречицу Alt + ESC за ово."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Одлично!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Довршили сте покрет за повратак."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Иди на почетни екран"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Да бисте отишли на почетни екран у било ком тренутку, превуците нагоре од дна екрана помоћу три прста."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Свака част!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Довршили сте покрет за повратак на почетну страницу."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Прикажи недавно коришћене апликације"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Превуците нагоре и задржите помоћу три прста на тачпеду."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Одлично!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Довршили сте покрет за приказивање недавно коришћених апликација."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Тастер радњи"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Да бисте приступили апликацијама, притисните тастер радњи на тастатури."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Честитамо!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Довршили сте покрет помоћу тастера радњи.\n\nРадња + / приказује све пречице које су вам доступне."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Позадинско осветљење тастатуре"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. ниво од %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Контроле за дом"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Да бисте погледали све апликације, притисните тастер радњи на тастатури"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Редиговано"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Откључајте за приказ"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Контекстуално образовање"</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> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 3016e83464fd..c8ece1313c49 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -440,7 +440,7 @@ <string name="zen_mode_on" msgid="9085304934016242591">"På"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"På • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Av"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Ställ in"</string> + <string name="zen_mode_set_up" msgid="8231201163894922821">"Inte angivet"</string> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Hantera i inställningarna"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Inga aktiva lägen}=1{{mode} är aktivt}other{# lägen är aktiva}}"</string> <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> @@ -573,8 +573,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Konversationer"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Rensa alla ljudlösa aviseringar"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Aviseringar har pausats via Stör ej"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Inga aviseringar}=1{Aviseringar har pausats av {mode}}=2{Aviseringar har pausats av {mode} och ett annat läge}other{Aviseringar har pausats av {mode} och # andra lägen}}"</string> <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> @@ -706,6 +705,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Visa demoläge"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> är på"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Lägg till en betalningsmetod för att betala snabbare och säkrare med telefonen"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Visa alla"</string> @@ -1405,26 +1405,26 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Lär dig rörelser för styrplattan"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigera med tangentbordet och styrplattan"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Lär dig rörelser för styrplattan, kortkommandon med mera"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Tillbaka-rörelse"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Rörelse för att öppna startskärmen"</string> + <string name="touchpad_tutorial_back_gesture_button" msgid="3104716365403620315">"Tillbaka"</string> + <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Återvänd till startsidan"</string> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Se de senaste apparna"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klar"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Tillbaka"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Gå tillbaka genom att svepa åt vänster eller höger med tre fingrar var som helst på styrplattan.\n\nDu kan även använda kortkommandot Åtgärd + Esc."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Bra jobbat!"</string> + <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Svep åt vänster eller höger med tre fingrar på styrplattan"</string> + <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Bra!"</string> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Du är klar med rörelsen för att gå tillbaka."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Återvänd till startskärmen"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Öppna startskärmen när som helst genom att svepa uppåt med tre fingrar från skärmens nederkant."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Bra!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Du är klar med rörelsen för att öppna startskärmen."</string> + <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Svep uppåt med tre fingrar på styrplattan"</string> + <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Bra jobbat!"</string> + <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Du är klar med rörelsen för att öppna startskärmen"</string> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Se de senaste apparna"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Svep uppåt med tre fingrar på styrplattan och håll kvar."</string> + <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Svep uppåt med tre fingrar på styrplattan och håll kvar"</string> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Bra jobbat!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Du är klar med rörelsen för att se de senaste apparna."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Åtgärdstangent"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Tryck på åtgärdstangenten på tangentbordet för att komma åt dina appar."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Grattis!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Du är klar med rörelsen med åtgärdstangenten.\n\nÅtgärd + / visar alla tillgängliga genvägar."</string> + <string name="tutorial_action_key_title" msgid="8172535792469008169">"Visa alla appar"</string> + <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Tryck på åtgärdstangenten på tangentbordet"</string> + <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Bra gjort!"</string> + <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Du är klar med rörelsen för att se alla apparna."</string> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Bakgrundsbelysning för tangentbord"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivå %1$d av %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Hemstyrning"</string> @@ -1436,6 +1436,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Tryck på åtgärdstangenten på tangentbordet för att se alla appar"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Anonymiserad"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Lås upp för att visa"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontextuell utbildning"</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> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 45095dfcc0bc..17a88239b135 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Imewashwa"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Imewashwa • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Imezimwa"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Ratibu"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Dhibiti katika mipangilio"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Hakuna hali zinazotumika}=1{Unatumia {mode}}other{Unatumia hali #}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Mazungumzo"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Futa arifa zote zisizo na sauti"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Kipengele cha Usinisumbue kimesitisha arifa"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Hakuna arifa}=1{Arifa zimesitishwa na {mode}}=2{Arifa zimesitishwa na {mode} na hali nyingine moja}other{Arifa zimesitishwa na {mode} na hali nyingine #}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Onyesha hali ya onyesho"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethaneti"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Kengele"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Umewasha <xliff:g id="MODENAME">%1$s</xliff:g>"</string> <string name="wallet_title" msgid="5369767670735827105">"Pochi"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Weka njia ya kulipa ili uweze kununua kwa njia salama na haraka zaidi ukitumia simu yako"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Onyesha zote"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Jifunze kuhusu miguso ya padi ya kugusa"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Kusogeza kwa kutumia kibodi na padi yako ya kugusa"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Jifunze kuhusu miguso ya padi ya kugusa, mikato ya kibodi na mengineyo"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Ishara ya kurudi nyuma"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Mguso wa kurudi kwenye skrini ya kwanza"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Angalia programu za hivi majuzi"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Nimemaliza"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Rudi nyuma"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Telezesha vidole vitatu kushoto au kulia mahali popote kwenye padi ya kugusa ili urudi nyuma.\n\nUnaweza pia kutumia mikato ya kibodi ya Kitendo pamoja na ESC kutekeleza kitendo hiki."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Kazi nzuri!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Umekamilisha ishara ya kurudi nyuma."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Nenda kwenye skrini ya kwanza"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Ili uende kwenye skrini ya kwanza wakati wowote, telezesha vidole vitatu juu kutoka sehemu ya chini ya skrini yako."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Safi!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Umeweka ishara ya kwenda kwenye skrini ya kwanza."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Angalia programu za hivi majuzi"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Telezesha vidole vitatu juu kisha ushikilie kwenye padi yako ya kugusa."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Kazi nzuri!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Umekamilisha mafunzo ya mguso wa kuangalia programu za hivi majuzi."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Kitufe cha vitendo"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Bonyeza kitufe cha vitendo kwenye kibodi yako ili ufikie programu zako."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Hongera!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Umekamilisha ishara ya kitufe cha vitendo.\n\nKitendo + / huonyesha njia zote za mkato zinazopatikana."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Mwanga chini ya kibodi"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Kiwango cha %1$d kati ya %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Dhibiti Vifaa Nyumbani"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Bonyeza kitufe cha vitendo kwenye kibodi yako ili uangalie programu zako zote"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Maandishi yameondolewa"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Fungua ili uone"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Elimu inayolingana na muktadha"</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> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 3dd0c73170fd..2381e1b5cc0b 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"இயக்கப்பட்டுள்ளது"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"ஆன் • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"முடக்கப்பட்டுள்ளது"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"அமையுங்கள்"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"உரையாடல்கள்"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"சைலன்ட் அறிவிப்புகள் அனைத்தையும் அழிக்கும்"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'தொந்தரவு செய்ய வேண்டாம்\' அம்சத்தின் மூலம் அறிவிப்புகள் இடைநிறுத்தப்பட்டுள்ளன"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{அறிவிப்புகள் இல்லை}=1{{mode} பயன்முறையால் அறிவிப்புகள் இடைநிறுத்தப்பட்டுள்ளன}=2{{mode} மற்றும் வேறொரு பயன்முறையால் அறிவிப்புகள் இடைநிறுத்தப்பட்டுள்ளன}other{{mode} மற்றும் வேறு # பயன்முறைகளால் அறிவிப்புகள் இடைநிறுத்தப்பட்டுள்ளன}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> இயக்கப்பட்டுள்ளது"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"மொபைல் மூலம் விரைவாகவும் பாதுகாப்பாகவும் பர்ச்சேஸ்கள் செய்ய பேமெண்ட் முறையை அமைக்கவும்"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"அனைத்தையும் காட்டு"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"டச்பேட் சைகைள் குறித்துத் தெரிந்துகொள்ளுங்கள்"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"உங்கள் டச்பேட் மற்றும் கீபோர்டைப் பயன்படுத்திச் செல்லுதல்"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"டச்பேட் சைகைகள், கீபோர்டு ஷார்ட்கட்கள் மற்றும் பலவற்றைத் தெரிந்துகொள்ளுங்கள்"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"பின்செல்வதற்கான சைகை"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"முகப்பிற்குச் செல்வதற்கான சைகை"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"சமீபத்திய ஆப்ஸைக் காட்டுதல்"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"முடிந்தது"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"பின்செல்"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"பின்செல்ல, உங்கள் டச்பேடில் எங்கு வேண்டுமானாலும் இடது அல்லது வலதுபுறமாக மூன்று விரல்களால் ஸ்வைப் செய்யவும்.\n\nஇதற்கு நீங்கள் கீபோர்டு ஷார்ட்கட் செயல்பாடுகள் + Esc பட்டனையும் பயன்படுத்தலாம்."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"அருமை!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"பின்செல்வதற்கான சைகையை நிறைவுசெய்துவிட்டீர்கள்."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"முகப்பிற்குச் செல்"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"எப்போது வேண்டுமானாலும் உங்கள் முகப்புத் திரைக்குச் செல்ல, மூன்று விரல்களால் திரையின் கீழிருந்து மேல்நோக்கி ஸ்வைப் செய்யவும்."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"அற்புதம்!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"முகப்புக்குச் செல்வதற்கான சைகையை நிறைவுசெய்துவிட்டீர்கள்."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"சமீபத்திய ஆப்ஸைக் காட்டுதல்"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"உங்கள் டச்பேடில் மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்து பிடிக்கவும்."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"அருமை!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"சமீபத்தில் பயன்படுத்திய ஆப்ஸுக்கான சைகை பயிற்சியை நிறைவுசெய்துவிட்டீர்கள்."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"ஆக்ஷன் பட்டன்"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"ஆப்ஸை அணுக உங்கள் கீபோர்டில் உள்ள ஆக்ஷன் பட்டனை அழுத்துங்கள்."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"வாழ்த்துகள்!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"ஆக்ஷன் பட்டன் சைகையை நிறைவுசெய்துவிட்டீர்கள்.\n\nAction + / உங்களுக்குக் கிடைக்கக்கூடிய எல்லா ஷார்ட்கட்களையும் காட்டும்."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"கீபோர்டு பேக்லைட்"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"நிலை, %2$d இல் %1$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ஹோம் கன்ட்ரோல்கள்"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"அனைத்து ஆப்ஸையும் பார்க்க, உங்கள் கீபோர்டில் உள்ள ஆக்ஷன் பட்டனை அழுத்தவும்"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"அர்த்தம் புரியாதபடி திருத்தப்பட்டது"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"பார்ப்பதற்கு அன்லாக் செய்யவும்"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"சூழல் சார்ந்த கல்வி"</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> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 65de840488f6..fcc344bc84c6 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -21,7 +21,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4811759950673118541">"సిస్టమ్ UI"</string> <string name="battery_low_title" msgid="5319680173344341779">"బ్యాటరీ సేవర్ను ఆన్ చేయాలా?"</string> - <string name="battery_low_description" msgid="3282977755476423966">"మీకు <xliff:g id="PERCENTAGE">%s</xliff:g> బ్యాటరీ మిగిలి ఉంది. బ్యాటరీ సేవర్ ముదురు రంగు రూపాన్ని ఆన్ చేస్తుంది, బ్యాక్గ్రౌండ్ యాక్టివిటీని పరిమితం చేస్తుంది, అలాగే నోటిఫికేషన్లను ఆలస్యంగా పంపిస్తుంది."</string> + <string name="battery_low_description" msgid="3282977755476423966">"బ్యాటరీ <xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది. \"బ్యాటరీ సేవర్\" వల్ల డార్క్ థీమ్ ఆన్ అవుతుంది, బ్యాక్గ్రౌండ్ యాక్టివిటీ పరిమితం అవుతుంది, అలాగే నోటిఫికేషన్లు ఆలస్యంగా వస్తాయి."</string> <string name="battery_low_intro" msgid="5148725009653088790">"బ్యాటరీ సేవర్ ముదురు రంగు రూపాన్ని ఆన్ చేస్తుంది, బ్యాక్గ్రౌండ్ యాక్టివిటీని పరిమితం చేస్తుంది, అలాగే నోటిఫికేషన్లను ఆలస్యంగా పంపిస్తుంది."</string> <string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> మిగిలి ఉంది"</string> <string name="invalid_charger_title" msgid="938685362320735167">"USB ద్వారా ఛార్జ్ చేయలేరు"</string> @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"ఆన్లో ఉంది"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"ఆన్ • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ఆఫ్లో ఉంది"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"సెటప్ చేయండి"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"సంభాషణలు"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"అన్ని నిశ్శబ్ద నోటిఫికేషన్లను క్లియర్ చేస్తుంది"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"అంతరాయం కలిగించవద్దు ద్వారా నోటిఫికేషన్లు పాజ్ చేయబడ్డాయి"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{నోటిఫికేషన్లు ఏవీ లేవు}=1{{mode} ద్వారా నోటిఫికేషన్లు పాజ్ చేయబడ్డాయి}=2{నోటిఫికేషన్లు, {mode}, మరో ఒక మోడ్ ద్వారా పాజ్ చేయబడ్డాయి}other{నోటిఫికేషన్లు, {mode}, మరో # మోడ్ల ద్వారా పాజ్ చేయబడ్డాయి}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> ఆన్లో ఉంది"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"మీ ఫోన్తో మరింత వేగంగా, సురక్షితంగా కొనుగోళ్లు చేయడానికి సెటప్ చేయండి"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"అన్నింటినీ చూపు"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"టచ్ప్యాడ్ సంజ్ఞ గురించి తెలుసుకోండి"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"మీ కీబోర్డ్, టచ్ప్యాడ్ను ఉపయోగించి నావిగేట్ చేయండి"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"టచ్ప్యాడ్ సంజ్ఞలు, కీబోర్డ్ షార్ట్కట్లు, అలాగే మరిన్నింటిని గురించి తెలుసుకోండి"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"వెనుకకు పంపే సంజ్ఞ"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"హోమ్కు పంపే సంజ్ఞ"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ఇటీవలి యాప్లను చూడండి"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"పూర్తయింది"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"వెనుకకు"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"వెనుకకు వెళ్లడానికి, టచ్ప్యాడ్లో ఎక్కడైనా మూడు వేళ్లను ఉపయోగించి ఎడమ లేదా కుడి వైపునకు స్వైప్ చేయండి.\n\nమీరు దీని కోసం + ESC కీబోర్డ్ షార్ట్కట్ యాక్షన్ను కూడా ఉపయోగించవచ్చు."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"చక్కగా పూర్తి చేశారు!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"తిరిగి వెనుకకు వెళ్ళడానికి ఉపయోగించే సంజ్ఞకు సంబంధించిన ట్యుటోరియల్ను మీరు పూర్తి చేశారు."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"మొదటి ట్యాబ్కు వెళ్లండి"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ఏ సమయంలోనైనా మీ మొదటి స్క్రీన్కు వెళ్లడానికి, మీ స్క్రీన్ కింది నుండి మూడు వేళ్లతో పైకి స్వైప్ చేయండి."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"సూపర్!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"మొదటి స్క్రీన్కు వెళ్ళడానికి ఉపయోగించే సంజ్ఞకు సంబంధించిన ట్యుటోరియల్ను మీరు పూర్తి చేశారు."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ఇటీవలి యాప్లను చూడండి"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"మీ టచ్ప్యాడ్లో మూడు వేళ్లను ఉపయోగించి పైకి స్వైప్ చేసి, హోల్డ్ చేయండి."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"పనితీరు అద్భుతంగా ఉంది!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"మీరు ఇటీవలి యాప్ల వీక్షణ సంజ్ఞను పూర్తి చేశారు."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"యాక్షన్ కీ"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"మీ యాప్లను యాక్సెస్ చేయడానికి, మీ కీబోర్డ్లో యాక్షన్ కీని నొక్కండి."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"అభినందనలు!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"మీరు \'యాక్షన్ కీ\' సంజ్ఞను పూర్తి చేశారు.\n\nAction + / నొక్కితే, మీకు అందుబాటులో ఉండే షార్ట్కట్లన్నీ కనిపిస్తాయి."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"కీబోర్డ్ బ్యాక్లైట్"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dలో %1$dవ స్థాయి"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"హోమ్ కంట్రోల్స్"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"మీ యాప్లన్నింటినీ చూడటానికి, మీ కీబోర్డ్లో యాక్షన్ కీని నొక్కండి"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"దాచిపెట్టినది"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"చూడటానికి అన్లాక్ చేయండి"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"సందర్భోచిత విద్య"</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> @@ -1445,7 +1459,7 @@ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"యాప్లన్నింటినీ చూడటానికి మీ కీబోర్డ్ను ఉపయోగించండి"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ఏ సమయంలోనైనా యాక్షన్ కీని నొక్కండి. మరిన్ని సంజ్ఞల గురించి తెలుసుకోవడానికి ట్యాప్ చేయండి."</string> <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"కాంతిని మరింత డిమ్ చేసే ఫీచర్ ఇప్పుడు బ్రైట్నెస్ స్లయిడర్లో ఒక భాగం"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"మీరు ఇప్పుడు బ్రైట్నెస్ స్థాయిని మరింత తగ్గించడం ద్వారా స్క్రీన్ను కాంతిని మరింత డిమ్ చేయవచ్చు.\n\nఈ ఫీచర్ ఇప్పుడు బ్రైట్నెస్ స్లయిడర్లో భాగం కాబట్టి, కాంతిని మరింత డిమ్ చేసే షార్ట్కట్లు తీసివేయబడుతున్నాయి."</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"మీరు ఇప్పుడు బ్రైట్నెస్ స్థాయిని మరింత తగ్గించడం ద్వారా స్క్రీన్ కాంతిని మరింత డిమ్ చేయవచ్చు.\n\nఈ ఫీచర్ ఇప్పుడు బ్రైట్నెస్ స్లయిడర్లో భాగం కాబట్టి, కాంతిని మరింత డిమ్ చేసే షార్ట్కట్లు తీసివేయబడుతున్నాయి."</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"కాంతిని మరింత డిమ్ చేసే షార్ట్కట్లను తీసివేయండి"</string> <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"కాంతిని మరింత డిమ్ చేసే షార్ట్కట్లు తీసివేయబడ్డాయి"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"కనెక్టివిటీ"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index b8a385a12fec..06c26619bb86 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"เปิด"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"เปิด • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ปิด"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"ตั้งค่า"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"การสนทนา"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"ล้างการแจ้งเตือนแบบไม่มีเสียงทั้งหมด"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"หยุดการแจ้งเตือนชั่วคราวโดย \"ห้ามรบกวน\""</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{ไม่มีการแจ้งเตือน}=1{หยุดการแจ้งเตือนชั่วคราวโดย {mode}}=2{หยุดการแจ้งเตือนชั่วคราวโดย {mode} และโหมดอื่นอีก 1 โหมด}other{หยุดการแจ้งเตือนชั่วคราวโดย {mode} และโหมดอื่นอีก # โหมด}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> เปิดอยู่"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"ตั้งค่าเพื่อซื้อสินค้าและบริการด้วยโทรศัพท์ได้อย่างรวดเร็วและปลอดภัยยิ่งขึ้น"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"แสดงทั้งหมด"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"ดูข้อมูลเกี่ยวกับท่าทางสัมผัสของทัชแพด"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"ไปยังส่วนต่างๆ โดยใช้แป้นพิมพ์และทัชแพด"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"ดูข้อมูลเกี่ยวกับท่าทางสัมผัสของทัชแพด แป้นพิมพ์ลัด และอื่นๆ"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ท่าทางสัมผัสสำหรับย้อนกลับ"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ท่าทางสัมผัสสำหรับหน้าแรก"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ดูแอปล่าสุด"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"เสร็จสิ้น"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ย้อนกลับ"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"หากต้องการย้อนกลับ ให้ใช้ 3 นิ้วปัดไปทางซ้ายหรือขวาที่ใดก็ได้บนทัชแพด\n\nหรือใช้การดำเนินการแป้นพิมพ์ลัด + ESC ได้เช่นเดียวกัน"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"เก่งมาก"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"คุณทำท่าทางสัมผัสเพื่อย้อนกลับเสร็จแล้ว"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ไปที่หน้าแรก"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"ใช้ 3 นิ้วปัดขึ้นจากด้านล่างของหน้าจอเพื่อไปที่หน้าจอหลักได้ทุกเมื่อ"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"ดีมาก"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"คุณทำท่าทางสัมผัสเพื่อไปที่หน้าแรกเสร็จแล้ว"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ดูแอปล่าสุด"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"ใช้ 3 นิ้วปัดขึ้นแล้วค้างไว้บนทัชแพด"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"เยี่ยมมาก"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"คุณทำท่าทางสัมผัสเพื่อดูแอปล่าสุดสำเร็จแล้ว"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"ปุ่มดำเนินการ"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"หากต้องการเข้าถึงแอป ให้กดปุ่มดำเนินการบนแป้นพิมพ์"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"ยินดีด้วย"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"คุณทำท่าทางสัมผัสสำหรับปุ่มดำเนินการเสร็จแล้ว\n\nการดำเนินการ + / จะแสดงแป้นพิมพ์ลัดทั้งหมดที่คุณมี"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ไฟแบ็กไลต์ของแป้นพิมพ์"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"ระดับที่ %1$d จาก %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ระบบควบคุมอุปกรณ์สมาร์ทโฮม"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"หากต้องการดูแอปทั้งหมด ให้กดปุ่มดำเนินการบนแป้นพิมพ์"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"ปกปิดไว้"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"ปลดล็อกเพื่อดู"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"การศึกษาตามบริบท"</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> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index f2cecf97b7b1..8241b723ae3c 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Naka-on"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Naka-on • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Naka-off"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"I-set up"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Pamahalaan sa mga setting"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Walang aktibong mode}=1{Aktibo ang {mode}}one{# mode ang aktibo}other{# na mode ang aktibo}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Mga Pag-uusap"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"I-clear ang lahat ng silent na notification"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Mga notification na na-pause ng Huwag Istorbohin"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Walang notification}=1{Na-pause ng {mode} ang mga notification}=2{Na-pause ng {mode} at isa pang mode ang mga notification}one{Na-pause ng {mode} at # pang mode ang mga notification}other{Na-pause ng {mode} at # pang mode ang mga notification}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Ipakita ang demo mode"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"Naka-on ang <xliff:g id="MODENAME">%1$s</xliff:g>"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"I-set up para makapagsagawa ng mas mabibilis, mas secure na pagbili gamit ang telepono mo"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Ipakita lahat"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Matuto ng mga galaw sa touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Mag-navigate gamit ang iyong keyboard at touchpad"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Matuto ng mga galaw sa touchpad, keyboard shortcut, at higit pa"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Galaw para bumalik"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Galaw para sa Home"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Tingnan ang mga kamakailang app"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Tapos na"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Bumalik"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Para bumalik, mag-swipe pakaliwa o pakanan gamit ang tatlong daliri saanman sa touchpad.\n\nPuwede mo ring gamitin ang keyboard shortcut na Action + ESC para dito."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Magaling!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Nakumpleto mo na ang galaw para bumalik."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Pumunta sa home"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Para pumunta sa iyong home screen anumang oras, mag-swipe pataas gamit ang tatlong daliri mula sa ibaba ng screen. mo."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Magaling!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Nakumpleto mo na ang galaw para pumunta sa home."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Tingnan ang mga kamakailang app"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Mag-swipe pataas at i-hold gamit ang tatlong daliri sa iyong touchpad."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Magaling!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Nakumpleto mo ang galaw sa pag-view ng mga kamakailang app."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Action key"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Para ma-access ang iyong mga app, pindutin ang action key sa keyboard mo."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Binabati kita!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Nakumpleto mo na ang galaw ng action key.\n\nIpinapakita ng Action + / ang lahat ng shortcut na available sa iyo."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Backlight ng keyboard"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d sa %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Mga Home Control"</string> @@ -1436,6 +1449,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Na-redact"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"I-unlock para tingnan"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Edukasyon ayon sa konteksto"</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> @@ -1445,7 +1459,7 @@ <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> <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"Bahagi na ng slider ng liwanag ang extra dim"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Puwede mo nang gawing extra dim ang screen sa pamamagitan ng pagbababa pa sa antas ng liwanag .\n\nDahil bahagi na ang feature na ito ng slider ng liwanag, aalisin na ang mga shortcut sa extra dim."</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Puwede mo nang gawing extra dim ang screen sa pamamagitan ng pagbababa pa ng antas ng liwanag .\n\nDahil bahagi na ang feature na ito ng slider ng liwanag, aalisin na ang mga shortcut sa extra dim."</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"Alisin ang mga shortcut sa extra dim"</string> <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"Inalis ang mga shortcut sa extra dim"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Pagkakonekta"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 570657d4494a..966c6efd942e 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Açık"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Açık • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Kapalı"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Ayarla"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Ayarlarda yönet"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Etkin mod yok}=1{{mode} etkin}other{# mod etkin}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Görüşmeler"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Sessiz bildirimlerin tümünü temizle"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Bildirimler, Rahatsız Etmeyin özelliği tarafından duraklatıldı"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Bildirim yok}=1{Bildirimler {mode} tarafından duraklatıldı}=2{Bildirimler, {mode} ve bir diğer mod tarafından duraklatıldı}other{Bildirimler, {mode} ve # diğer mod tarafından duraklatıldı}}"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Şimdi başlat"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Bildirim yok"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Yeni bildirim yok"</string> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Demo modunu göster"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Alarm"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Cüzdan"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Telefonunuzla daha hızlı ve güvenli satın alma işlemleri gerçekleştirmek için gerekli ayarları yapın"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Tümünü göster"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Dokunmatik alan hareketlerini öğrenin"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Klavyenizi ve dokunmatik alanınızı kullanarak gezinin"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Dokunmatik alan hareketlerini, klavye kısayollarını ve daha fazlasını öğrenin"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Geri hareketi"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Ana sayfa hareketi"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Son uygulamaları görüntüle"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Bitti"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Geri dön"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Geri dönmek için dokunmatik alanın herhangi bir yerinde üç parmağınızla sola veya sağa kaydırın.\n\nDilerseniz işlem düğmesi + Esc klavye kısayolunu kullanarak da geri dönebilirsiniz."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Tebrikler!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Geri dön hareketini tamamladınız."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ana sayfaya gidin"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"İstediğiniz zaman ana ekrana gitmek için üç parmağınızla ekranınızın altından yukarı doğru kaydırın."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Güzel!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Ana ekrana git hareketini tamamladınız."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Son uygulamaları görüntüle"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Dokunmatik alanda üç parmağınızla yukarı doğru kaydırıp basılı tutun."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Tebrikler!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Son uygulamaları görüntüleme hareketini tamamladınız."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Eylem tuşu"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Uygulamalarınıza erişmek için klavyenizdeki eylem tuşuna basın."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Tebrikler!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Eylem tuşu hareketini tamamladınız.\n\nKullanabileceğiniz tüm kısayolları görmek için eylem + / tuşuna basın."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klavye aydınlatması"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Seviye %1$d / %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Ev Kontrolleri"</string> @@ -1436,6 +1450,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Çıkartıldı"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Görüntülemek için kilidi açın"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Bağlama dayalı eğitim"</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> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 65b1b39cccd2..c146021968ae 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Увімкнено"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Увімк. • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Вимкнено"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Налаштувати"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Керувати в налаштуваннях"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Немає активних режимів}=1{Активовано режим \"{mode}\"}one{Активовано # режим}few{Активовано # режими}many{Активовано # режимів}other{Активовано # режиму}}"</string> <string name="zen_priority_introduction" msgid="3159291973383796646">"Ви отримуватиме звукові та вібросигнали лише для вибраних будильників, нагадувань, подій і абонентів. Однак ви чутимете все, що захочете відтворити, зокрема музику, відео й ігри."</string> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Розмови"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Очистити всі беззвучні сповіщення"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Режим \"Не турбувати\" призупинив сповіщення"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Немає сповіщень}=1{Режим \"{mode}\" призупинив надсилання сповіщень}=2{\"{mode}\" і ще один режим призупинили надсилання сповіщень}one{\"{mode}\" і ще # режим призупинили надсилання сповіщень}few{\"{mode}\" і ще # режими призупинили надсилання сповіщень}many{\"{mode}\" і ще # режимів призупинили надсилання сповіщень}other{\"{mode}\" і ще # режиму призупинили надсилання сповіщень}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Показати демонстраційний режим"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Будильник"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"Гаманець"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Швидше й безпечніше сплачуйте за покупки за допомогою телефона"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Показати все"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Жести для сенсорної панелі: докладніше"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Навігація за допомогою клавіатури й сенсорної панелі"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Жести для сенсорної панелі, комбінації клавіш тощо: докладніше"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Жест \"Назад\""</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жест переходу на головний екран"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Переглянути нещодавні додатки"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Щоб перейти назад, проведіть трьома пальцями вліво або вправо по сенсорній панелі.\n\nТакож можна скористатися комбінацією \"клавіша дії\" + ESC."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Чудово!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ви виконали жест \"Назад\"."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Перейти на головний екран"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Щоб будь-коли перейти на головний екран, проведіть трьома пальцями вгору від нижнього краю екрана."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Чудово!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Ви виконали жест переходу на головний екран."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Переглянути нещодавні додатки"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Проведіть трьома пальцями вгору й утримуйте їх на сенсорній панелі."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Чудово!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Ви виконали жест для перегляду нещодавно відкритих додатків."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Клавіша дії"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Щоб переглянути додатки, натисніть клавішу дії на клавіатурі."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Вітаємо!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Ви виконали жест клавіші дії.\n\nНатисніть клавішу дії + /, щоб переглянути всі доступні комбінації клавіш."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Підсвічування клавіатури"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Рівень %1$d з %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Автоматизація дому"</string> @@ -1436,6 +1450,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Щоб переглянути всі додатки, натисніть клавішу дії на клавіатурі"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Замасковано"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Розблокуйте, щоб переглянути"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Контекстне навчання"</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> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index e65fd98e7dbf..a0e934749b3a 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"آن ہے"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"آن ہے • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"آف ہے"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"سیٹ اپ کریں"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"گفتگوئیں"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"سبھی خاموش اطلاعات کو صاف کریں"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'ڈسٹرب نہ کریں\' کے ذریعے اطلاعات کو موقوف کیا گیا"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{کوئی اطلاع نہیں ہے}=1{{mode} کی طرف سے اطلاعات کو روک دیا گیا ہے}=2{{mode} اور ایک دوسرے موڈ کے ذریعہ اطلاعات کو روک دیا گیا ہے}other{{mode} اور # دیگر طریقوں کے ذریعے اطلاعات کو روک دیا گیا ہے}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> آن ہے"</string> <string name="wallet_title" msgid="5369767670735827105">"والٹ"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"اپنے فون سے تیز تر مزید محفوظ خریداریاں کرنے کے لیے، سیٹ اپ مکمل کریں"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"سبھی دکھائیں"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"ٹچ پیڈ کے اشارے کو جانیں"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"اپنے کی بورڈ اور ٹچ پیڈ کا استعمال کر کے نیویگیٹ کریں"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"ٹچ پیڈ کے اشارے، کی بورڈ شارٹ کٹس اور مزید جانیں"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"پیچھے جانے کا اشارہ"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ہوم کا اشارہ"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"حالیہ ایپس دیکھیں"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ہو گیا"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"واپس جائیں"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"واپس جانے کے لیے، ٹچ پیڈ پر کہیں بھی تین انگلیوں کی مدد سے دائیں یا بائیں سوائپ کریں۔\n\nآپ اس کیلئے کی بورڈ شارٹ کٹ ایکشن + Esc کا بھی استعمال کر سکتے ہیں۔"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"بہترین!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"آپ نے واپس جائیں اشارے کو مکمل کر لیا۔"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ہوم پر جائیں"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"کسی بھی وقت اپنی ہوم اسکرین پر جانے کے لیے، تین انگلیوں کی مدد سے اپنی اسکرین کے نیچے سے اوپر کی طرف سوائپ کریں۔"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"عمدہ!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"آپ نے ہوم پر جانے کا اشارہ مکمل کر لیا۔"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"حالیہ ایپس دیکھیں"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"اپنے ٹچ پیڈ پر تین انگلیوں کا استعمال کرتے ہوئے اوپر کی طرف سوائپ کریں اور دبائے رکھیں۔"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"بہترین!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"آپ نے حالیہ ایپس کا اشارہ مکمل کر لیا ہے۔"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"ایکشن کلید"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"اپنی ایپس تک رسائی حاصل کرنے کے لیے، اپنے کی بورڈ پر ایکشن کلید کو دبائیں۔"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"مبارکباد!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"آپ نے ایکشن کلید کا اشارہ مکمل کر لیا۔\n\nایکشن + / دبانے سے آپ کے دستیاب تمام شارٹ کٹس دکھائی دیں گے۔"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"کی بورڈ بیک لائٹ"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d میں سے %1$d کا لیول"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"ہوم کنٹرولز"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"اپنی سبھی ایپس دیکھنے کے لیے، اپنے کی بورڈ پر ایکشن کلید دبائیں"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"چھپانے کیلئے تبدیل کردہ"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"دیکھنے کے لیے غیر مقفل کریں"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"سیاق و سباق کی تعلیم"</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> @@ -1447,7 +1461,7 @@ <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"اضافی دھندلا اب چمک سلائیڈر کا حصہ ہے"</string> <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"آپ چمکیلے پن لیول کو مزید کم کر کے اپنی اسکرین کو اضافی دھندلی بنا سکتے ہیں۔\n\nچونکہ یہ خصوصیت اب چمکیلے پن کے سلائیڈر کا حصہ ہے، اس لیے اضافی دھندلا شارٹ کٹس کو ہٹایا جا رہا ہے۔"</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"اضافی دھندلا شارٹ کٹس کو ہٹائیں"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"اضافی دھندلا شارٹ کٹس ہٹا دیے گئے"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"اضافی دھندلے شارٹ کٹس ہٹا دیے گئے"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"کنیکٹویٹی"</string> <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"ایکسیسبیلٹی"</string> <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"یوٹیلیٹیز"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 0f2db3799438..05943136ee3a 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Yoniq"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Yoniq • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Yoqilmagan"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Sozlash"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Sozlamalarda boshqarish"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{0 ta rejim faol}=1{{mode} faol}other{# ta rejim faol}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Suhbatlar"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Barcha sokin bildirishnomalarni tozalash"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Bezovta qilinmasin rejimida bildirishnomalar pauza qilinadi"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Bildirishnomalar yoʻq}=1{{mode} rejimi bildirishnomalarni pauza qilgan}=2{{mode} va yana bitta boshqa rejim bildirishnomalarni pauza qilgan}other{{mode} va # ta boshqa rejim bildirishnomalarni pauza qilgan}}"</string> <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> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Demo rejimni ko‘rsatish"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Signal"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> yoniq"</string> <string name="wallet_title" msgid="5369767670735827105">"Wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Telefonda tezroq va xavfsizroq xarid qilish uchun sozlang"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Hammasi"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Sensorli panel ishoralari haqida"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Klaviatura va sensorli panel yordamida kezing"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Sensorli panel ishoralari, tezkor tugmalar va boshqalar haqida"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Orqaga qaytish ishorasi"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Asosiy ekran ishorasi"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Oxirgi ilovalarni koʻrish"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Tayyor"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Orqaga qaytish"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Ortga qaytish uchun sensorli panelda uchta barmoqni chapga yoki oʻngga suring.\n\nBuning uchun Action + ESC tezkor tugmalaridan ham foydalanishingiz mumkin."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Barakalla!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ortga qaytish ishorasi darsini tamomladingiz."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Boshiga"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Istalgan vaqtda bosh ekranga oʻtish uchun ekranning pastidan uchta barmoq bilan tepaga suring."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Yaxshi!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Bosh ekranni ochish ishorasi darsini tamomladingiz."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Oxirgi ilovalarni koʻrish"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Sensorli panelda uchta barmoq bilan tepaga surib, bosib turing."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Barakalla!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Oxirgi ilovalarni koʻrish ishorasini tugalladingiz."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Amal tugmasi"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Ilovalarga kirish uchun klaviaturadagi amal tugmasini bosing"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Tabriklaymiz!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Amal tugmasi ishorasi darsini tamomladingiz.\n\nAmal + / bosilsa, mavjud buyruqlar koʻrsatiladi."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatura orqa yoritkichi"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Daraja: %1$d / %2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Uy boshqaruvi"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Barcha ishoralarni koʻrish uchun klaviaturadagi amal tugmasini bosing"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Chiqarildi"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Koʻrish uchun qulfdan chiqaring"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Kontekstual taʼlim"</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> @@ -1446,8 +1460,8 @@ <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Amal tugmasini istalganda bosing. Boshqa ishoralar bilan tanishish uchun bosing."</string> <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"Juda xira endi yorqinlik slayderida joylashgan"</string> <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"Endi yorqinlik darajasini yanada pasaytirish orqali ekranni yanada xiralashtirishingiz mumkin.\n\nBu funksiya yorqinlik slayderiga kiritilgani uchun \"juda xira\" buyruqlari olib tashlanmoqda."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"Juda xira buyruqlarini olib tashlash"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"Juda xira buyruqlari olib tashlandi"</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"“Juda xira” buyruqlarini olib tashlash"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"“Juda xira” buyruqlari olib tashlandi"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Aloqa"</string> <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Qulayliklar"</string> <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Vositalar"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index a37a7cd31343..c38f99fcb984 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Đang bật"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Bật • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Đang tắt"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Thiết lập"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Quản lý trong phần cài đặt"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Không có chế độ nào đang hoạt động}=1{{mode} đang hoạt động}other{# chế độ đang hoạt động}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Cuộc trò chuyện"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Xóa tất cả thông báo im lặng"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Chế độ Không làm phiền đã tạm dừng thông báo"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Không có thông báo}=1{{mode} đã tạm dừng thông báo}=2{{mode} và một chế độ khác đã tạm dừng thông báo}other{{mode} và # chế độ khác đã tạm dừng thông báo}}"</string> <string name="media_projection_action_text" msgid="3634906766918186440">"Bắt đầu ngay"</string> <string name="empty_shade_text" msgid="8935967157319717412">"Không có thông báo nào"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Không có thông báo mới"</string> @@ -706,6 +706,7 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Hiển thị chế độ trình diễn"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"Chuông báo"</string> + <string name="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g> đang bật"</string> <string name="wallet_title" msgid="5369767670735827105">"Ví"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Thiết lập để mua hàng nhanh hơn và an toàn hơn bằng điện thoại"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Hiện tất cả"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Tìm hiểu về cử chỉ trên bàn di chuột"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Di chuyển bằng bàn phím và bàn di chuột"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Tìm hiểu về cử chỉ trên bàn di chuột, phím tắt và nhiều mục khác"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Cử chỉ quay lại"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Cử chỉ chuyển đến màn hình chính"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Xem các ứng dụng gần đây"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Xong"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Quay lại"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Để quay lại, hãy dùng 3 ngón tay vuốt sang trái hoặc sang phải ở vị trí bất kỳ trên bàn di chuột.\n\nBạn cũng có thể dùng phím tắt Hành động + ESC cho thao tác này."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Tuyệt vời!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Bạn đã thực hiện xong cử chỉ quay lại."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Chuyển đến màn hình chính"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Để chuyển đến màn hình chính bất cứ lúc nào, hãy dùng 3 ngón tay vuốt lên từ cuối màn hình lên."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Tốt lắm!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Bạn đã thực hiện xong cử chỉ chuyển đến màn hình chính."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Xem các ứng dụng gần đây"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Dùng 3 ngón tay vuốt lên và giữ trên bàn di chuột."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Tuyệt vời!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Bạn đã hoàn tất cử chỉ xem ứng dụng gần đây."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Phím hành động"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Để truy cập vào cá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="tutorial_action_key_success_title" msgid="466467860120112933">"Xin chúc mừng!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Bạn đã thực hiện xong cử chỉ nhấn phím hành động.\n\nThao tác + / sẽ hiển thị tất cả phím tắt bạn hiện có."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Đèn nền bàn phím"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Độ sáng %1$d/%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Điều khiển nhà"</string> @@ -1436,6 +1449,7 @@ <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="redacted_notification_single_line_title" msgid="212019960919261670">"Bị loại bỏ"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Mở khoá để xem"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Hướng dẫn theo bối cảnh"</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> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 0d270beb0bf9..60e6c4fcb054 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"已开启"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"已开启 • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"已关闭"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"设置"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"对话"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"清除所有静音通知"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"勿扰模式暂停的通知"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{无通知}=1{{mode}暂停了通知}=2{{mode}和另外 1 种模式暂停了通知}other{{mode}和另外 # 种模式暂停了通知}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"“<xliff:g id="MODENAME">%1$s</xliff:g>”处于启用状态"</string> <string name="wallet_title" msgid="5369767670735827105">"钱包"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"开始设置,享受更加快捷安全的手机购物体验"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"全部显示"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"了解触控板手势"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"使用键盘和触控板进行导航"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"了解触控板手势、键盘快捷键等"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"返回手势"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"主屏幕手势"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"查看最近用过的应用"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"如要返回,请使用三根手指在触控板上的任意位置左滑或右滑。\n\n您也可以使用键盘快捷操作键 + ESC 键进行返回。"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"太棒了!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"您完成了“返回”手势教程。"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"前往主屏幕"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"若要随时进入主屏幕,请用三根手指从屏幕的底部向上滑动。"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"很好!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"您完成了“前往主屏幕”手势教程。"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"查看最近用过的应用"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"在触控板上用三根手指向上滑动并按住。"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"太棒了!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"您已完成“查看最近用过的应用”的手势教程。"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"快捷操作按键"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"如要访问您的应用,请按下键盘上的快捷操作按键。"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"恭喜!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"您完成了“快捷操作按键”手势教程。\n\n按下快捷操作按键 + / 可显示所有可用快捷键。"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"键盘背光"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"第 %1$d 级,共 %2$d 级"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"家居控制"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"如要查看所有应用,请按下键盘上的快捷操作按键"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"已隐去"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"解锁即可查看"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"内容相关指导"</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> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index d9a0877ec4aa..a838da4c02e4 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"開啟"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"開 • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"關閉"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"設定"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"對話"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"清除所有靜音通知"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"「請勿騷擾」模式已將通知暫停"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{沒有通知}=1{{mode}已暫停通知}=2{{mode}和另外一個模式已暫停通知}other{{mode}和另外 # 個模式已暫停通知}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g>開咗"</string> <string name="wallet_title" msgid="5369767670735827105">"錢包"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"完成設定後即可透過手機更快速安全地購物"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"顯示全部"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"瞭解觸控板手勢"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"使用鍵盤和觸控板導覽"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"瞭解觸控板手勢、鍵盤快速鍵等等"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"返去手勢"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"主畫面手勢"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"查看最近使用的應用程式"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"用三隻手指在觸控板上任何一處向左或向右滑動即可返回。\n\n你也可使用鍵盤快速鍵 Action 鍵 + Esc 鍵執行此操作。"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"太好了!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"你已完成「返回」手勢的教學課程。"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"返回主畫面"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"只要用三隻手指從螢幕底部向上滑動,隨時可以返回主畫面。"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"做得好!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"你已完成「返回主畫面」手勢的教學課程。"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"查看最近使用的應用程式"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"用三隻手指在觸控板向上滑動並按住。"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"做得好!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"你已完成「查看最近使用的應用程式」手勢的教學課程。"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"快捷操作鍵"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"如要存取應用程式,請在鍵盤上按下快捷操作鍵。"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"恭喜!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"你已完成「快捷操作鍵」手勢的教學課程。\n\n按下動作 + / 鍵即可顯示所有可使用的快速鍵。"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"鍵盤背光"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"第 %1$d 級,共 %2$d 級"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"智能家居"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"如要查看所有應用程式,請在鍵盤上按下快捷操作鍵"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"已剔除"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"解鎖即可查看"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"內容教學"</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> @@ -1445,7 +1459,7 @@ <string name="all_apps_edu_notification_title" msgid="372262997265569063">"使用鍵盤查看所有應用程式"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"隨時按下快捷操作鍵。輕按即可瞭解更多手勢。"</string> <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"亮度滑桿現已加入超暗功能"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"而家只要將亮度校得越低,螢幕就會更加暗。\n\n由於亮度滑桿而家加入咗呢個功能,所以系統將會移除超暗功能捷徑。"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"現在,只要調校亮度就能將螢幕變得超暗。\n\n由於超暗功能已加到亮度滑桿,其功能捷徑將被移除。"</string> <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"移除超暗功能捷徑"</string> <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"超暗功能捷徑已移除"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"裝置連接"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 83b456bab0b4..158b68a7d9b7 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"開啟"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"已開啟 • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"關閉"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"設定"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"對話"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"清除所有靜音通知"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"「零打擾」模式已將通知設為暫停"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{沒有通知}=1{「{mode}」模式已將通知設為暫停}=2{「{mode}」和另一個模式已將通知設為暫停}other{「{mode}」和另外 # 個模式已將通知設為暫停}}"</string> <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> @@ -706,6 +706,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="active_mode_content_description" msgid="1627555562186515927">"<xliff:g id="MODENAME">%1$s</xliff:g>已開啟"</string> <string name="wallet_title" msgid="5369767670735827105">"錢包"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"完成相關設定之後,就能以更快速安全的方式透過手機消費"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"顯示全部"</string> @@ -1405,26 +1406,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"學習觸控板手勢"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"使用鍵盤和觸控板操作"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"學習觸控板手勢、鍵盤快速鍵等"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"返回手勢"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"主畫面手勢"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"查看最近使用的應用程式"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"如要返回,請在觸控板的任何位置上用三指向左或向右滑動。\n\n使用快捷操作鍵 + ESC 鍵 (鍵盤快速鍵) 也可以返回。"</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"太棒了!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"你已完成「返回」手勢的教學課程。"</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"返回主畫面"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"用 3 指從螢幕底部向上滑動,就能隨時返回主畫面。"</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"太棒了!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"你已完成「返回主畫面」手勢的教學課程。"</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"查看最近使用的應用程式"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"在觸控板上用三指向上滑動並按住。"</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"太棒了!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"你已完成「查看最近使用的應用程式」手勢教學課程。"</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"快捷操作鍵"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"如要存取應用程式,請按下鍵盤上的快捷操作鍵。"</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"恭喜!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"你已完成「快捷操作鍵」手勢的教學課程。\n\n按下快捷操作鍵 + / 鍵,就能顯示所有可用的快速鍵。"</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"鍵盤背光"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"第 %1$d 級,共 %2$d 級"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"居家控制"</string> @@ -1436,6 +1449,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"如要查看所有應用程式,請按下鍵盤上的快捷操作鍵"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"已遮蓋"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"解鎖即可查看"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"內容教學"</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> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 34f368388d0e..a351b1b91f64 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -440,7 +440,8 @@ <string name="zen_mode_on" msgid="9085304934016242591">"Vuliwe"</string> <string name="zen_mode_on_with_details" msgid="7416143430557895497">"Vuliwe • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"Valiwe"</string> - <string name="zen_mode_set_up" msgid="7457957033034460064">"Setha"</string> + <!-- no translation found for zen_mode_set_up (8231201163894922821) --> + <skip /> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Phatha kumasethingi"</string> <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Awekho amamodi asebenzayo}=1{I-{mode} iyasebenza}one{Amamodi angu-# ayasebenza}other{Amamodi angu-# ayasebenza}}"</string> <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> @@ -573,8 +574,7 @@ <string name="notification_section_header_conversations" msgid="821834744538345661">"Izingxoxo"</string> <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Sula zonke izaziso ezithulile"</string> <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Izaziso zimiswe okwesikhashana ukungaphazamisi"</string> - <!-- no translation found for modes_suppressing_shade_text (6037581130837903239) --> - <skip /> + <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Azikho izaziso}=1{Izaziso zimiswe okwesikhashana yi-{mode}}=2{Izaziso zimiswe okwesikhashana yi-{mode} nelinye imodi elilodwa}one{Izaziso zimiswe okwesikhashana yi-{mode} kanye namanye amamodi angu-#}other{Izaziso zimiswe okwesikhashana yi-{mode} kanye namanye amamodi angu-#}}"</string> <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> @@ -706,6 +706,8 @@ <string name="show_demo_mode" msgid="3677956462273059726">"Bonisa imodi yedemo"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"I-Ethernet"</string> <string name="status_bar_alarm" msgid="87160847643623352">"I-alamu"</string> + <!-- no translation found for active_mode_content_description (1627555562186515927) --> + <skip /> <string name="wallet_title" msgid="5369767670735827105">"I-wallet"</string> <string name="wallet_empty_state_label" msgid="7776761245237530394">"Lungela ukuthenga ngokushesha, ngokuphepha ngefoni yakho"</string> <string name="wallet_app_button_label" msgid="7123784239111190992">"Bonisa konke"</string> @@ -1405,26 +1407,38 @@ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Funda ukunyakaza kwephedi lokuthinta"</string> <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Funa usebenzisa ikhibhodi yakho nephedi yokuthinta"</string> <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Funda ukunyakaza kwephedi yokuthinta, izinqamuleli zamakhibhodi, nokuningi"</string> - <string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Ukunyakazisa umzimba kwangemuva"</string> - <string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Ukunyakazisa umzimba kwasekhaya"</string> + <!-- no translation found for touchpad_tutorial_back_gesture_button (3104716365403620315) --> + <skip /> + <!-- no translation found for touchpad_tutorial_home_gesture_button (8023973153559885624) --> + <skip /> <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Buka ama-app akamuva"</string> <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Kwenziwe"</string> <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Buyela emuva"</string> - <string name="touchpad_back_gesture_guidance" msgid="6263750214998421587">"Ukuze ubuyele emuva, swayiphela kwesokunxele noma kwesokudla usebenzisa iminwe emithathu noma yikuphi ephedini yokuthinta.\n\nUngasebenzisa nesinqamuleli sekhibhodi Isenzo + ESC kulokhu."</string> - <string name="touchpad_back_gesture_success_title" msgid="7240576648330612171">"Umsebenzi omuhle!"</string> + <!-- no translation found for touchpad_back_gesture_guidance (5352221087725906542) --> + <skip /> + <!-- no translation found for touchpad_back_gesture_success_title (7370719098633023496) --> + <skip /> <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ukuqedile ukuthinta kokubuyela emuva."</string> <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Iya ekhasini lokuqala"</string> - <string name="touchpad_home_gesture_guidance" msgid="3043931356096731966">"Ukuze uye esikrinini sakho sasekhaya nganoma isiphi isikhathi, swayipha uye phezulu ngeminwe emithathu usuka phansi esikrinini sakho."</string> - <string name="touchpad_home_gesture_success_title" msgid="3778407003948209795">"Kuhle!"</string> - <string name="touchpad_home_gesture_success_body" msgid="2404031094918807067">"Ukuqedile ukuthinta kokuya ekhaya."</string> + <!-- no translation found for touchpad_home_gesture_guidance (4178219118381915899) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_title (3648264553645798470) --> + <skip /> + <!-- no translation found for touchpad_home_gesture_success_body (2590690589194027059) --> + <skip /> <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Buka ama-app akamuva"</string> - <string name="touchpad_recent_apps_gesture_guidance" msgid="6012057247259983871">"Swayiphela phezulu bese ubamba usebenzisa iminwe emithathu kuphedi yokuthinta."</string> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6304446013842271822) --> + <skip /> <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Umsebenzi omuhle!"</string> <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Uqedele ukubuka ukuthinta kwama-app akamuva."</string> - <string name="tutorial_action_key_title" msgid="2659466586996495447">"Inkinobho yokufinyelela"</string> - <string name="tutorial_action_key_guidance" msgid="5718948664616999196">"Ukuze ufinyelele ama-app wakho, cindezela inkinobho yokufinyelela kukhibhodi yakho."</string> - <string name="tutorial_action_key_success_title" msgid="466467860120112933">"Halala!"</string> - <string name="tutorial_action_key_success_body" msgid="7201991081652850430">"Uqedele ukuthinta inkinobho yokufinyelela.\n\nIsenzo +/ sibonisa zonke izinqamuleli onazo."</string> + <!-- no translation found for tutorial_action_key_title (8172535792469008169) --> + <skip /> + <!-- no translation found for tutorial_action_key_guidance (5040613427202799294) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_title (2371827347071979571) --> + <skip /> + <!-- no translation found for tutorial_action_key_success_body (1688986269491357832) --> + <skip /> <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Ilambu lekhibhodi"</string> <string name="keyboard_backlight_value" msgid="7336398765584393538">"Ileveli %1$d ka-%2$d"</string> <string name="home_controls_dream_label" msgid="6567105701292324257">"Izilawuli Zasekhaya"</string> @@ -1436,6 +1450,7 @@ <string name="all_apps_edu_toast_content" msgid="8807496014667211562">"Ukuze ubuke wonke ama-app wakho, cindezela inkinobho yokufinyelela kukhibhodi yakho"</string> <string name="redacted_notification_single_line_title" msgid="212019960919261670">"Kwenziwe iredact"</string> <string name="redacted_notification_single_line_text" msgid="8684166405005242945">"Vula ukuze ubuke"</string> + <string name="contextual_education_dialog_title" msgid="4630392552837487324">"Imfundo yokuqukethwe"</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> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 629c94f9a044..1727a5fec0a2 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -2048,5 +2048,6 @@ <dimen name="abc_slice_big_pic_min_height">64dp</dimen> <dimen name="abc_slice_big_pic_max_height">64dp</dimen> - <dimen name="contextual_edu_dialog_bottom_margin">70dp</dimen> + <dimen name="contextual_edu_dialog_bottom_margin">80dp</dimen> + <dimen name="contextual_edu_dialog_elevation">2dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 7209c44f976d..96a85d78e2b5 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1120,7 +1120,7 @@ <string name="zen_mode_off">Off</string> <!-- Modes: label for a mode that needs to be set up [CHAR LIMIT=35] --> - <string name="zen_mode_set_up">Set up</string> + <string name="zen_mode_set_up">Not set</string> <!-- 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> @@ -3752,9 +3752,9 @@ <!-- TOUCHPAD TUTORIAL--> <!-- Label for button opening tutorial for back gesture on touchpad [CHAR LIMIT=NONE] --> - <string name="touchpad_tutorial_back_gesture_button">Back gesture</string> + <string name="touchpad_tutorial_back_gesture_button">Go back</string> <!-- Label for button opening tutorial for back gesture on touchpad [CHAR LIMIT=NONE] --> - <string name="touchpad_tutorial_home_gesture_button">Home gesture</string> + <string name="touchpad_tutorial_home_gesture_button">Go home</string> <!-- Label for button opening tutorial for "view recent apps" gesture on touchpad [CHAR LIMIT=NONE] --> <string name="touchpad_tutorial_recent_apps_gesture_button">View recent apps</string> <!-- Label for button finishing touchpad tutorial [CHAR LIMIT=NONE] --> @@ -3763,26 +3763,25 @@ <!-- 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.\n\nYou can also use the keyboard shortcut -Action + ESC for this.</string> + <string name="touchpad_back_gesture_guidance">Swipe left or right using three fingers on your touchpad</string> <!-- Screen title after back gesture was done successfully [CHAR LIMIT=NONE] --> - <string name="touchpad_back_gesture_success_title">Great job!</string> + <string name="touchpad_back_gesture_success_title">Nice!</string> <!-- Text shown to the user after they complete back gesture tutorial [CHAR LIMIT=NONE] --> <string name="touchpad_back_gesture_success_body">You completed the go back gesture.</string> <!-- HOME GESTURE --> <!-- Touchpad home gesture action name in tutorial [CHAR LIMIT=NONE] --> <string name="touchpad_home_gesture_action_title">Go home</string> <!-- Touchpad home gesture guidance in gestures tutorial [CHAR LIMIT=NONE] --> - <string name="touchpad_home_gesture_guidance">To go to your home screen at any time, swipe up with three fingers from the bottom of your screen.</string> + <string name="touchpad_home_gesture_guidance">Swipe up with three fingers on your touchpad</string> <!-- Screen title after home gesture was done successfully [CHAR LIMIT=NONE] --> - <string name="touchpad_home_gesture_success_title">Nice!</string> + <string name="touchpad_home_gesture_success_title">Great job!</string> <!-- Text shown to the user after they complete home gesture tutorial [CHAR LIMIT=NONE] --> - <string name="touchpad_home_gesture_success_body">You completed the go home gesture.</string> + <string name="touchpad_home_gesture_success_body">You completed the go home gesture</string> <!-- RECENT APPS GESTURE --> <!-- Touchpad recent apps gesture action name in tutorial [CHAR LIMIT=NONE] --> <string name="touchpad_recent_apps_gesture_action_title">View recent apps</string> <!-- Touchpad recent apps gesture guidance in gestures tutorial [CHAR LIMIT=NONE] --> - <string name="touchpad_recent_apps_gesture_guidance">Swipe up and hold using three fingers on your touchpad.</string> + <string name="touchpad_recent_apps_gesture_guidance">Swipe up and hold using three fingers on your touchpad</string> <!-- Screen title after recent apps gesture was done successfully [CHAR LIMIT=NONE] --> <string name="touchpad_recent_apps_gesture_success_title">Great job!</string> <!-- Text shown to the user after they complete recent apps gesture tutorial [CHAR LIMIT=NONE] --> @@ -3790,13 +3789,13 @@ Action + ESC for this.</string> <!-- KEYBOARD TUTORIAL--> <!-- Action key tutorial title [CHAR LIMIT=NONE] --> - <string name="tutorial_action_key_title">Action key</string> + <string name="tutorial_action_key_title">View all apps</string> <!-- Action key tutorial guidance[CHAR LIMIT=NONE] --> - <string name="tutorial_action_key_guidance">To access your apps, press the action key on your keyboard.</string> + <string name="tutorial_action_key_guidance">Press the action key on your keyboard</string> <!-- Screen title after action key pressed successfully [CHAR LIMIT=NONE] --> - <string name="tutorial_action_key_success_title">Congratulations!</string> + <string name="tutorial_action_key_success_title">Well done!</string> <!-- Text shown to the user after they complete action key tutorial [CHAR LIMIT=NONE] --> - <string name="tutorial_action_key_success_body">You completed the action key gesture.\n\nAction + / shows all the shortcuts you have available.</string> + <string name="tutorial_action_key_success_body">You completed the view all apps gesture</string> <!-- Content description for keyboard backlight brightness dialog [CHAR LIMIT=NONE] --> <string name="keyboard_backlight_dialog_title">Keyboard backlight</string> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 1c09f84b6fd0..e1f25f99cc98 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -540,6 +540,7 @@ <!-- Overridden by values-television/styles.xml with tv-specific settings --> <style name="volume_dialog_theme" parent="Theme.SystemUI"> <item name="android:windowIsFloating">true</item> + <item name="android:showWhenLocked">true</item> </style> <style name="Theme.SystemUI.DayNightDialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog"/> @@ -1720,10 +1721,4 @@ <style name="ShortcutHelperTheme" parent="@style/ShortcutHelperThemeCommon"> <item name="android:windowLightNavigationBar">true</item> </style> - - <style name="ContextualEduDialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar"> - <!-- To make the dialog wrap to content when the education text is short --> - <item name="windowMinWidthMajor">0%</item> - <item name="windowMinWidthMinor">0%</item> - </style> </resources> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index f05cbf422707..2d27f1c0ca73 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -1067,6 +1067,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout { @Override public void onDestroy() { + mUserSwitcherController.removeUserSwitchCallback(mUserSwitchCallback); + ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(mView); constraintSet.clear(mUserSwitcherViewGroup.getId()); @@ -1075,6 +1077,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout { mView.removeView(mUserSwitcherViewGroup); mView.removeView(mUserSwitcher); + mUserSwitcher = null; + mUserSwitcherViewGroup = null; } private void findLargeUserIcon(int userId, Consumer<Drawable> consumer) { @@ -1102,6 +1106,10 @@ public class KeyguardSecurityContainer extends ConstraintLayout { return; } + if (mUserSwitcherViewGroup == null) { + return; + } + mUserSwitcherViewGroup.setAlpha(0f); ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f); int yTrans = mView.getResources().getDimensionPixelSize(R.dimen.pin_view_trans_y_entry); @@ -1110,14 +1118,18 @@ public class KeyguardSecurityContainer extends ConstraintLayout { animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - mUserSwitcherViewGroup.setAlpha(1f); - mUserSwitcherViewGroup.setTranslationY(0f); + if (mUserSwitcherViewGroup != null) { + mUserSwitcherViewGroup.setAlpha(1f); + mUserSwitcherViewGroup.setTranslationY(0f); + } } }); animator.addUpdateListener(animation -> { - float value = (float) animation.getAnimatedValue(); - mUserSwitcherViewGroup.setAlpha(value); - mUserSwitcherViewGroup.setTranslationY(yTrans - yTrans * value); + if (mUserSwitcherViewGroup != null) { + float value = (float) animation.getAnimatedValue(); + mUserSwitcherViewGroup.setAlpha(value); + mUserSwitcherViewGroup.setTranslationY(yTrans - yTrans * value); + } }); animator.start(); } @@ -1148,6 +1160,10 @@ public class KeyguardSecurityContainer extends ConstraintLayout { Log.e(TAG, "Current user in user switcher is null."); return; } + if (mUserSwitcher == null) { + Log.w(TAG, "User switcher is not inflated, cannot setupUserSwitcher"); + return; + } final String currentUserName = mUserSwitcherController.getCurrentUserName(); findLargeUserIcon(currentUser.info.id, (Drawable userIcon) -> { 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 60edaae21bc0..158623fa80af 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java @@ -280,6 +280,14 @@ public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate, if (mLocalBluetoothManager == null) { return; } + + // Remove the default padding of the system ui dialog + View container = dialog.findViewById(android.R.id.custom); + if (container != null && container.getParent() != null) { + View containerParent = (View) container.getParent(); + containerParent.setPadding(0, 0, 0, 0); + } + mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DIALOG_SHOW, mLaunchSourceId); mPairButton = dialog.requireViewById(R.id.pair_new_device_button); mDeviceList = dialog.requireViewById(R.id.device_list); 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 664f3f834f86..9367cb5c0198 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapter.java @@ -108,6 +108,7 @@ public class HearingDevicesListAdapter extends RecyclerView.Adapter<RecyclerView private final ImageView mIconView; private final ImageView mGearIcon; private final View mGearView; + private final View mDividerView; DeviceItemViewHolder(@NonNull View itemView, Context context) { super(itemView); @@ -118,6 +119,7 @@ public class HearingDevicesListAdapter extends RecyclerView.Adapter<RecyclerView mIconView = itemView.requireViewById(R.id.bluetooth_device_icon); mGearIcon = itemView.requireViewById(R.id.gear_icon_image); mGearView = itemView.requireViewById(R.id.gear_icon); + mDividerView = itemView.requireViewById(R.id.divider); } public void bindView(DeviceItem item, HearingDeviceItemCallback callback) { @@ -153,6 +155,7 @@ public class HearingDevicesListAdapter extends RecyclerView.Adapter<RecyclerView mGearIcon.getDrawable().mutate().setTint(tintColor); mGearView.setOnClickListener(view -> callback.onDeviceItemGearClicked(item, view)); + mDividerView.setBackgroundColor(tintColor); } } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index b39aae94ed4e..a5bd559dcbf2 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -19,6 +19,7 @@ package com.android.systemui.biometrics; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR; +import static android.view.Display.INVALID_DISPLAY; import static com.android.systemui.util.ConvenienceExtensionsKt.toKotlinLazy; @@ -54,6 +55,7 @@ import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback; import android.os.Handler; import android.os.RemoteException; +import android.os.UserHandle; import android.os.UserManager; import android.util.Log; import android.util.RotationUtils; @@ -211,9 +213,13 @@ public class AuthController implements } }; - private void closeDialog(String reason) { + private void closeDialog(String reasonString) { + closeDialog(BiometricPrompt.DISMISSED_REASON_USER_CANCEL, reasonString); + } + + private void closeDialog(@DismissedReason int reason, String reasonString) { if (isShowing()) { - Log.i(TAG, "Close BP, reason :" + reason); + Log.i(TAG, "Close BP, reason :" + reasonString); mCurrentDialog.dismissWithoutCallback(true /* animate */); mCurrentDialog = null; @@ -223,8 +229,7 @@ public class AuthController implements try { if (mReceiver != null) { - mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL, - null /* credentialAttestation */); + mReceiver.onDialogDismissed(reason, null /* credentialAttestation */); mReceiver = null; } } catch (RemoteException e) { @@ -251,25 +256,7 @@ public class AuthController implements private void cancelIfOwnerIsNotInForeground() { mExecution.assertIsMainThread(); - if (mCurrentDialog != null) { - try { - mCurrentDialog.dismissWithoutCallback(true /* animate */); - mCurrentDialog = null; - - for (Callback cb : mCallbacks) { - cb.onBiometricPromptDismissed(); - } - - if (mReceiver != null) { - mReceiver.onDialogDismissed( - BiometricPrompt.DISMISSED_REASON_USER_CANCEL, - null /* credentialAttestation */); - mReceiver = null; - } - } catch (RemoteException e) { - Log.e(TAG, "Remote exception", e); - } - } + closeDialog("owner not in foreground"); } /** @@ -1271,8 +1258,42 @@ public class AuthController implements if (!promptInfo.isAllowBackgroundAuthentication() && isOwnerInBackground()) { cancelIfOwnerIsNotInForeground(); } else { - mCurrentDialog.show(mWindowManager); + WindowManager wm = getWindowManagerForUser(userId); + if (wm != null) { + mCurrentDialog.show(wm); + } else { + closeDialog(BiometricPrompt.DISMISSED_REASON_ERROR_NO_WM, + "unable to get WM instance for user"); + } + } + } + + @Nullable + private WindowManager getWindowManagerForUser(int userId) { + if (!mUserManager.isVisibleBackgroundUsersSupported()) { + return mWindowManager; + } + UserManager um = mContext.createContextAsUser(UserHandle.of(userId), + 0 /* flags */).getSystemService(UserManager.class); + if (um == null) { + Log.e(TAG, "unable to get UserManager for user=" + userId); + return null; + } + if (!um.isUserVisible()) { + // not visible user - use default window manager + return mWindowManager; + } + int displayId = um.getMainDisplayIdAssignedToUser(); + if (displayId == INVALID_DISPLAY) { + Log.e(TAG, "unable to get display assigned to user=" + userId); + return null; + } + Display display = mDisplayManager.getDisplay(displayId); + if (display == null) { + Log.e(TAG, "unable to get Display for user=" + userId); + return null; } + return mContext.createDisplayContext(display).getSystemService(WindowManager.class); } private void onDialogDismissed(@DismissedReason int reason) { diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt index 5dd4c1cb7f72..02bf9dbab373 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt @@ -23,6 +23,7 @@ import androidx.room.Delete import androidx.room.Query import androidx.room.RoomDatabase import androidx.room.Transaction +import androidx.room.Update import androidx.sqlite.db.SupportSQLiteDatabase import com.android.systemui.communal.nano.CommunalHubState import com.android.systemui.communal.shared.model.CommunalContentSize @@ -171,8 +172,7 @@ interface CommunalWidgetDao { @Query("UPDATE communal_item_rank_table SET rank = :order WHERE uid = :itemUid") fun updateItemRank(itemUid: Long, order: Int) - @Query("UPDATE communal_widget_table SET span_y = :spanY WHERE widget_id = :widgetId") - fun updateWidgetSpanY(widgetId: Int, spanY: Int) + @Update fun updateWidget(widget: CommunalWidgetItem) @Query("DELETE FROM communal_widget_table") fun clearCommunalWidgetsTable() @@ -189,6 +189,15 @@ interface CommunalWidgetDao { } @Transaction + fun resizeWidget(appWidgetId: Int, spanY: Int, widgetIdToRankMap: Map<Int, Int>) { + val widget = getWidgetByIdNow(appWidgetId) + if (widget != null) { + updateWidget(widget.copy(spanY = spanY)) + } + updateWidgetOrder(widgetIdToRankMap) + } + + @Transaction fun addWidget( widgetId: Int, provider: ComponentName, diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt index 3312f3cac64b..0e9428970a13 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt @@ -21,6 +21,7 @@ import android.appwidget.AppWidgetProviderInfo import android.content.ComponentName import android.os.UserHandle import android.os.UserManager +import com.android.systemui.Flags.communalWidgetResizing import com.android.systemui.common.data.repository.PackageChangeRepository import com.android.systemui.common.shared.model.PackageInstallSession import com.android.systemui.communal.data.backup.CommunalBackupUtils @@ -82,7 +83,7 @@ interface CommunalWidgetRepository { * * @param widgetIdToRankMap mapping of the widget ids to the rank of the widget. */ - fun updateWidgetOrder(widgetIdToRankMap: Map<Int, Int>) {} + fun updateWidgetOrder(widgetIdToRankMap: Map<Int, Int>) /** * Restores the database by reading a state file from disk and updating the widget ids according @@ -96,10 +97,13 @@ interface CommunalWidgetRepository { /** * Update the spanY of a widget in the database. * - * @param widgetId id of the widget to update. + * @param appWidgetId id of the widget to update. * @param spanY new spanY value for the widget. + * @param widgetIdToRankMap mapping of the widget ids to its rank. Allows re-ordering widgets + * alongside the resize, in case resizing also requires re-ordering. This ensures the + * re-ordering is done in the same database transaction as the resize. */ - fun updateWidgetSpanY(widgetId: Int, spanY: Int) + fun resizeWidget(appWidgetId: Int, spanY: Int, widgetIdToRankMap: Map<Int, Int>) } @SysUISingleton @@ -135,15 +139,17 @@ constructor( componentName = widget.componentName, rank = rank.rank, providerInfo = providers[widget.widgetId], + spanY = widget.spanY, ) } } - override fun updateWidgetSpanY(widgetId: Int, spanY: Int) { + override fun resizeWidget(appWidgetId: Int, spanY: Int, widgetIdToRankMap: Map<Int, Int>) { + if (!communalWidgetResizing()) return bgScope.launch { - communalWidgetDao.updateWidgetSpanY(widgetId, spanY) + communalWidgetDao.resizeWidget(appWidgetId, spanY, widgetIdToRankMap) logger.i({ "Updated spanY of widget $int1 to $int2." }) { - int1 = widgetId + int1 = appWidgetId int2 = spanY } backupManager.dataChanged() @@ -445,7 +451,7 @@ constructor( val appWidgetId: Int, val componentName: String, val rank: Int, + val spanY: Int, var providerInfo: AppWidgetProviderInfo? = null, - var spanY: Int = 3, ) } diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt index a687734ff499..3a04d026ee84 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt @@ -399,6 +399,10 @@ constructor( fun updateWidgetOrder(widgetIdToRankMap: Map<Int, Int>) = widgetRepository.updateWidgetOrder(widgetIdToRankMap) + fun resizeWidget(appWidgetId: Int, spanY: Int, widgetIdToRankMap: Map<Int, Int>) { + widgetRepository.resizeWidget(appWidgetId, spanY, widgetIdToRankMap) + } + /** Request to unpause work profile that is currently in quiet mode. */ fun unpauseWorkProfile() { managedProfileController.setWorkModeEnabled(true) @@ -449,6 +453,7 @@ constructor( providerInfo = widget.providerInfo, appWidgetHost = appWidgetHost, inQuietMode = isQuietModeEnabled(widget.providerInfo.profile), + size = CommunalContentSize.toSize(widget.spanY), ) } is CommunalWidgetContentModel.Pending -> { @@ -457,6 +462,7 @@ constructor( rank = widget.rank, componentName = widget.componentName, icon = widget.icon, + size = CommunalContentSize.toSize(widget.spanY), ) } } diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt index c2f6e85a33e4..4c2c094a4aea 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt @@ -62,11 +62,10 @@ sealed interface CommunalContentModel { val providerInfo: AppWidgetProviderInfo, val appWidgetHost: CommunalAppWidgetHost, val inQuietMode: Boolean, + override val size: CommunalContentSize, ) : WidgetContent { override val key = KEY.widget(appWidgetId) override val componentName: ComponentName = providerInfo.provider - // Widget size is always half. - override val size = CommunalContentSize.HALF /** Whether this widget can be reconfigured after it has already been added. */ val reconfigurable: Boolean @@ -79,11 +78,10 @@ sealed interface CommunalContentModel { override val appWidgetId: Int, override val rank: Int, val providerInfo: AppWidgetProviderInfo, + override val size: CommunalContentSize, ) : WidgetContent { override val key = KEY.disabledWidget(appWidgetId) override val componentName: ComponentName = providerInfo.provider - // Widget size is always half. - override val size = CommunalContentSize.HALF val appInfo: ApplicationInfo? get() = providerInfo.providerInfo?.applicationInfo @@ -93,11 +91,10 @@ sealed interface CommunalContentModel { override val appWidgetId: Int, override val rank: Int, override val componentName: ComponentName, + override val size: CommunalContentSize, val icon: Bitmap? = null, ) : WidgetContent { override val key = KEY.pendingWidget(appWidgetId) - // Widget size is always half. - override val size = CommunalContentSize.HALF } } diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalWidgetContentModel.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalWidgetContentModel.kt index bcbc8f65ce36..0c9ea789f3d1 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalWidgetContentModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalWidgetContentModel.kt @@ -25,13 +25,14 @@ import android.os.UserHandle sealed interface CommunalWidgetContentModel { val appWidgetId: Int val rank: Int + val spanY: Int /** Widget is ready to display */ data class Available( override val appWidgetId: Int, val providerInfo: AppWidgetProviderInfo, override val rank: Int, - val spanY: Int = 3, + override val spanY: Int, ) : CommunalWidgetContentModel /** Widget is pending installation */ @@ -41,6 +42,6 @@ sealed interface CommunalWidgetContentModel { val componentName: ComponentName, val icon: Bitmap?, val user: UserHandle, - val spanY: Int = 3, + override val spanY: Int, ) : CommunalWidgetContentModel } diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt index 5f421fd19550..ba96f4e56421 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalAppWidgetHostViewBinder.kt @@ -17,19 +17,30 @@ package com.android.systemui.communal.ui.binder import android.content.Context +import android.os.Bundle import android.util.SizeF import android.view.View import android.view.ViewGroup import android.widget.FrameLayout +import androidx.compose.ui.unit.IntSize import androidx.core.view.doOnLayout +import com.android.app.tracing.coroutines.flow.flowOn import com.android.app.tracing.coroutines.launch +import com.android.systemui.Flags.communalWidgetResizing +import com.android.systemui.common.ui.view.onLayoutChanged import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.util.WidgetViewFactory import com.android.systemui.util.kotlin.DisposableHandles +import com.android.systemui.util.kotlin.toDp +import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow +import kotlin.coroutines.CoroutineContext import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DisposableHandle +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged object CommunalAppWidgetHostViewBinder { private const val TAG = "CommunalAppWidgetHostViewBinder" @@ -37,9 +48,11 @@ object CommunalAppWidgetHostViewBinder { fun bind( context: Context, applicationScope: CoroutineScope, + mainContext: CoroutineContext, + backgroundContext: CoroutineContext, container: FrameLayout, model: CommunalContentModel.WidgetContent.Widget, - size: SizeF, + size: SizeF?, factory: WidgetViewFactory, ): DisposableHandle { val disposables = DisposableHandles() @@ -49,6 +62,22 @@ object CommunalAppWidgetHostViewBinder { val widget = factory.createWidget(context, model, size) waitForLayout(container) container.post { container.setView(widget) } + if (communalWidgetResizing()) { + // Update the app widget size in the background. + launch("$TAG#updateSize", backgroundContext) { + container.sizeFlow().flowOn(mainContext).distinctUntilChanged().collect { + (width, height) -> + widget.updateAppWidgetSize( + /* newOptions = */ Bundle(), + /* minWidth = */ width, + /* minHeight = */ height, + /* maxWidth = */ width, + /* maxHeight = */ height, + /* ignorePadding = */ true, + ) + } + } + } } disposables += DisposableHandle { loadingJob.cancel() } @@ -69,3 +98,13 @@ private fun ViewGroup.setView(view: View) { (view.parent as? ViewGroup)?.removeView(view) addView(view) } + +private fun View.sizeAsDp(): IntSize = IntSize(width.toDp(context), height.toDp(context)) + +private fun View.sizeFlow(): Flow<IntSize> = conflatedCallbackFlow { + if (isLaidOut && !isLayoutRequested) { + trySend(sizeAsDp()) + } + val disposable = onLayoutChanged { trySend(sizeAsDp()) } + awaitClose { disposable.dispose() } +} diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/CommunalAppWidgetSection.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/CommunalAppWidgetSection.kt index 56b769e7bc13..2e12bad744f0 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/CommunalAppWidgetSection.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/CommunalAppWidgetSection.kt @@ -25,13 +25,17 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.viewinterop.AndroidView import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.android.systemui.Flags.communalWidgetResizing import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.ui.binder.CommunalAppWidgetHostViewBinder import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel import com.android.systemui.communal.util.WidgetViewFactory import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.dagger.qualifiers.UiBackground import com.android.systemui.res.R import javax.inject.Inject +import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DisposableHandle @@ -39,6 +43,8 @@ class CommunalAppWidgetSection @Inject constructor( @Application private val applicationScope: CoroutineScope, + @Main private val mainContext: CoroutineContext, + @UiBackground private val backgroundContext: CoroutineContext, private val factory: WidgetViewFactory, ) { @@ -76,10 +82,12 @@ constructor( context = context, container = this, model = model, - size = size, + size = if (!communalWidgetResizing()) size else null, factory = factory, applicationScope = applicationScope, - ) + mainContext = mainContext, + backgroundContext = backgroundContext, + ), ) accessibilityDelegate = viewModel.widgetAccessibilityDelegate 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 0929d3e1bda9..e25ea4cbfb25 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 @@ -105,7 +105,7 @@ abstract class BaseCommunalViewModel( scene: SceneKey, loggingReason: String, transitionKey: TransitionKey? = null, - keyguardState: KeyguardState? = null + keyguardState: KeyguardState? = null, ) { communalSceneInteractor.changeScene(scene, loggingReason, transitionKey, keyguardState) } @@ -155,17 +155,10 @@ abstract class BaseCommunalViewModel( ) {} /** Called as the UI requests deleting a widget. */ - open fun onDeleteWidget( - id: Int, - componentName: ComponentName, - rank: Int, - ) {} + open fun onDeleteWidget(id: Int, componentName: ComponentName, rank: Int) {} /** Called as the UI detects a tap event on the widget. */ - open fun onTapWidget( - componentName: ComponentName, - rank: Int, - ) {} + open fun onTapWidget(componentName: ComponentName, rank: Int) {} /** * Called as the UI requests reordering widgets. @@ -176,10 +169,19 @@ abstract class BaseCommunalViewModel( */ open fun onReorderWidgets(widgetIdToRankMap: Map<Int, Int>) {} + /** + * Called as the UI requests resizing a widget. + * + * @param appWidgetId The id of the widget being resized. + * @param spanY The new size of the widget, in grid spans. + * @param widgetIdToRankMap Mapping of the widget ids to its rank. Allows re-ordering widgets + * alongside the resize, in case resizing also requires re-ordering. This ensures the + * re-ordering is done in the same database transaction as the resize. + */ + open fun onResizeWidget(appWidgetId: Int, spanY: Int, widgetIdToRankMap: Map<Int, Int>) {} + /** Called as the UI requests opening the widget editor with an optional preselected widget. */ - open fun onOpenWidgetEditor( - shouldOpenWidgetPickerOnStart: Boolean = false, - ) {} + open fun onOpenWidgetEditor(shouldOpenWidgetPickerOnStart: Boolean = false) {} /** Called as the UI requests to dismiss the CTA tile. */ open fun onDismissCtaTile() {} 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 65f0679c4266..3ae9250b2938 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 @@ -107,9 +107,9 @@ constructor( allOf( keyguardTransitionInteractor.isFinishedIn( scene = Scenes.Gone, - stateWithoutSceneContainer = KeyguardState.GONE + stateWithoutSceneContainer = KeyguardState.GONE, ), - communalInteractor.editModeOpen + communalInteractor.editModeOpen, ) .filter { it } @@ -128,17 +128,13 @@ constructor( componentName: ComponentName, user: UserHandle, rank: Int?, - configurator: WidgetConfigurator? + configurator: WidgetConfigurator?, ) { communalInteractor.addWidget(componentName, user, rank, configurator) metricsLogger.logAddWidget(componentName.flattenToString(), rank) } - override fun onDeleteWidget( - id: Int, - componentName: ComponentName, - rank: Int, - ) { + override fun onDeleteWidget(id: Int, componentName: ComponentName, rank: Int) { communalInteractor.deleteWidget(id) metricsLogger.logRemoveWidget(componentName.flattenToString(), rank) } @@ -146,6 +142,10 @@ constructor( override fun onReorderWidgets(widgetIdToRankMap: Map<Int, Int>) = communalInteractor.updateWidgetOrder(widgetIdToRankMap) + override fun onResizeWidget(appWidgetId: Int, spanY: Int, widgetIdToRankMap: Map<Int, Int>) { + communalInteractor.resizeWidget(appWidgetId, spanY, widgetIdToRankMap) + } + override fun onReorderWidgetStart() { // Clear selection status setSelectedKey(null) @@ -173,7 +173,7 @@ constructor( val announcementText = context.getString( R.string.accessibility_announcement_communal_widget_added, - widgetLabel + widgetLabel, ) accessibilityManager.sendAccessibilityEvent( AccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT).apply { @@ -187,7 +187,7 @@ constructor( /** Launch the widget picker activity using the given {@link ActivityResultLauncher}. */ suspend fun onOpenWidgetPicker( resources: Resources, - activityLauncher: ActivityResultLauncher<Intent> + activityLauncher: ActivityResultLauncher<Intent>, ): Boolean = withContext(backgroundDispatcher) { val widgets = communalInteractor.widgetContent.first() @@ -210,21 +210,21 @@ constructor( private fun getWidgetPickerActivityIntent( resources: Resources, - excludeList: ArrayList<AppWidgetProviderInfo> + excludeList: ArrayList<AppWidgetProviderInfo>, ): Intent? { return Intent(Intent.ACTION_PICK).apply { setPackage(launcherPackage) putExtra( EXTRA_DESIRED_WIDGET_WIDTH, - resources.getDimensionPixelSize(R.dimen.communal_widget_picker_desired_width) + resources.getDimensionPixelSize(R.dimen.communal_widget_picker_desired_width), ) putExtra( EXTRA_DESIRED_WIDGET_HEIGHT, - resources.getDimensionPixelSize(R.dimen.communal_widget_picker_desired_height) + resources.getDimensionPixelSize(R.dimen.communal_widget_picker_desired_height), ) putExtra( AppWidgetManager.EXTRA_CATEGORY_FILTER, - CommunalWidgetCategories.defaultCategories + CommunalWidgetCategories.defaultCategories, ) communalSettingsInteractor.workProfileUserDisallowedByDevicePolicy.value?.let { @@ -234,7 +234,7 @@ constructor( putExtra(EXTRA_PICKER_TITLE, resources.getString(R.string.communal_widget_picker_title)) putExtra( EXTRA_PICKER_DESCRIPTION, - resources.getString(R.string.communal_widget_picker_description) + resources.getString(R.string.communal_widget_picker_description), ) putParcelableArrayListExtra(EXTRA_ADDED_APP_WIDGETS_KEY, excludeList) } diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/ResizeableItemFrameViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/ResizeableItemFrameViewModel.kt new file mode 100644 index 000000000000..87fcdd7b97ee --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/ResizeableItemFrameViewModel.kt @@ -0,0 +1,209 @@ +/* + * 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.communal.ui.viewmodel + +import androidx.compose.foundation.gestures.AnchoredDraggableState +import androidx.compose.foundation.gestures.DraggableAnchors +import androidx.compose.runtime.snapshotFlow +import com.android.app.tracing.coroutines.coroutineScope +import com.android.systemui.lifecycle.ExclusiveActivatable +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.merge +import kotlinx.coroutines.flow.onEach + +enum class DragHandle { + TOP, + BOTTOM, +} + +data class ResizeInfo( + /** + * The number of spans to resize by. A positive number indicates expansion, whereas a negative + * number indicates shrinking. + */ + val spans: Int, + /** The drag handle which was used to resize the element. */ + val fromHandle: DragHandle, +) { + /** Whether we are expanding. If false, then we are shrinking. */ + val isExpanding = spans > 0 +} + +class ResizeableItemFrameViewModel : ExclusiveActivatable() { + private data class GridLayoutInfo( + val minSpan: Int, + val maxSpan: Int, + val heightPerSpanPx: Float, + val verticalItemSpacingPx: Float, + val currentRow: Int, + val currentSpan: Int, + ) + + /** + * The layout information necessary in order to calculate the pixel offsets of the drag anchor + * points. + */ + private val gridLayoutInfo = MutableStateFlow<GridLayoutInfo?>(null) + + val topDragState = AnchoredDraggableState(0, DraggableAnchors { 0 at 0f }) + val bottomDragState = AnchoredDraggableState(0, DraggableAnchors { 0 at 0f }) + + /** Emits a [ResizeInfo] when the element is resized using a drag gesture. */ + val resizeInfo: Flow<ResizeInfo> = + merge( + snapshotFlow { topDragState.settledValue }.map { ResizeInfo(-it, DragHandle.TOP) }, + snapshotFlow { bottomDragState.settledValue } + .map { ResizeInfo(it, DragHandle.BOTTOM) }, + ) + .filter { it.spans != 0 } + .distinctUntilChanged() + + /** + * Sets the necessary grid layout information needed for calculating the pixel offsets of the + * drag anchors. + */ + fun setGridLayoutInfo( + verticalItemSpacingPx: Float, + verticalContentPaddingPx: Float, + viewportHeightPx: Int, + maxItemSpan: Int, + minItemSpan: Int, + currentRow: Int?, + currentSpan: Int?, + ) { + if (currentSpan == null || currentRow == null) { + gridLayoutInfo.value = null + return + } + require(maxItemSpan >= minItemSpan) { + "Maximum item span of $maxItemSpan cannot be less than the minimum span of $minItemSpan" + } + require(minItemSpan in 1..maxItemSpan) { + "Minimum span must be between 1 and $maxItemSpan, but was $minItemSpan" + } + require(currentSpan % minItemSpan == 0) { + "Current span of $currentSpan is not a multiple of the minimum span of $minItemSpan" + } + val availableHeight = viewportHeightPx - verticalContentPaddingPx + val totalSpacing = verticalItemSpacingPx * ((maxItemSpan / minItemSpan) - 1) + val heightPerSpanPx = (availableHeight - totalSpacing) / maxItemSpan + gridLayoutInfo.value = + GridLayoutInfo( + minSpan = minItemSpan, + maxSpan = maxItemSpan, + heightPerSpanPx = heightPerSpanPx, + verticalItemSpacingPx = verticalItemSpacingPx, + currentRow = currentRow, + currentSpan = currentSpan, + ) + } + + private fun calculateAnchorsForHandle( + handle: DragHandle, + layoutInfo: GridLayoutInfo?, + ): DraggableAnchors<Int> { + + if (layoutInfo == null || !isDragAllowed(handle, layoutInfo)) { + return DraggableAnchors { 0 at 0f } + } + + val ( + minItemSpan, + maxItemSpan, + heightPerSpanPx, + verticalSpacingPx, + currentRow, + currentSpan, + ) = layoutInfo + + // The maximum row this handle can be dragged to. + val maxRow = + if (handle == DragHandle.TOP) { + (currentRow + currentSpan - minItemSpan).coerceAtLeast(0) + } else { + maxItemSpan + } + + // The minimum row this handle can be dragged to. + val minRow = + if (handle == DragHandle.TOP) { + 0 + } else { + (currentRow + minItemSpan).coerceAtMost(maxItemSpan) + } + + // The current row position of this handle + val currentPosition = if (handle == DragHandle.TOP) currentRow else currentRow + currentSpan + + return DraggableAnchors { + for (targetRow in minRow..maxRow step minItemSpan) { + val diff = targetRow - currentPosition + val spacing = diff / minItemSpan * verticalSpacingPx + diff at diff * heightPerSpanPx + spacing + } + } + } + + private fun isDragAllowed(handle: DragHandle, layoutInfo: GridLayoutInfo): Boolean { + val minItemSpan = layoutInfo.minSpan + val maxItemSpan = layoutInfo.maxSpan + val currentRow = layoutInfo.currentRow + val currentSpan = layoutInfo.currentSpan + val atMinSize = currentSpan == minItemSpan + + // If already at the minimum size and in the first row, item cannot be expanded from the top + if (handle == DragHandle.TOP && currentRow == 0 && atMinSize) { + return false + } + + // If already at the minimum size and occupying the last row, item cannot be expanded from + // the + // bottom + if (handle == DragHandle.BOTTOM && (currentRow + currentSpan) == maxItemSpan && atMinSize) { + return false + } + + // If at maximum size, item can only be shrunk from the bottom and not the top. + if (handle == DragHandle.TOP && currentSpan == maxItemSpan) { + return false + } + + return true + } + + override suspend fun onActivated(): Nothing { + coroutineScope("ResizeableItemFrameViewModel.onActivated") { + gridLayoutInfo + .onEach { layoutInfo -> + topDragState.updateAnchors( + calculateAnchorsForHandle(DragHandle.TOP, layoutInfo) + ) + bottomDragState.updateAnchors( + calculateAnchorsForHandle(DragHandle.BOTTOM, layoutInfo) + ) + } + .launchIn(this) + awaitCancellation() + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/communal/util/WidgetViewFactory.kt b/packages/SystemUI/src/com/android/systemui/communal/util/WidgetViewFactory.kt index cafa74faf1a1..07a7c7cba2fd 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/util/WidgetViewFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/util/WidgetViewFactory.kt @@ -43,7 +43,7 @@ constructor( suspend fun createWidget( context: Context, model: CommunalContentModel.WidgetContent.Widget, - size: SizeF, + size: SizeF?, ): CommunalAppWidgetHostView = withContext("$TAG#createWidget", uiBgContext) { val view = @@ -54,14 +54,16 @@ constructor( // Instead of setting the view as the listener directly, we wrap the view in a delegate // which ensures the callbacks always get called on the main thread. appWidgetHost.setListener(model.appWidgetId, listenerFactory.create(view)) - view.updateAppWidgetSize( - /* newOptions = */ Bundle(), - /* minWidth = */ size.width.toInt(), - /* minHeight = */ size.height.toInt(), - /* maxWidth = */ size.width.toInt(), - /* maxHeight = */ size.height.toInt(), - /* ignorePadding = */ true, - ) + if (size != null) { + view.updateAppWidgetSize( + /* newOptions = */ Bundle(), + /* minWidth = */ size.width.toInt(), + /* minHeight = */ size.height.toInt(), + /* maxWidth = */ size.width.toInt(), + /* maxHeight = */ size.height.toInt(), + /* ignorePadding = */ true, + ) + } view } diff --git a/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamClockTimeComplicationComponent.kt b/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamClockTimeComplicationComponent.kt index 099e3fcf227d..4b9ac1d58b57 100644 --- a/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamClockTimeComplicationComponent.kt +++ b/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamClockTimeComplicationComponent.kt @@ -21,9 +21,10 @@ import android.view.LayoutInflater import android.view.View import android.widget.TextClock import com.android.internal.util.Preconditions -import com.android.systemui.res.R +import com.android.systemui.Flags import com.android.systemui.complication.DreamClockTimeComplication import com.android.systemui.complication.DreamClockTimeComplication.DreamClockTimeViewHolder +import com.android.systemui.res.R import dagger.Module import dagger.Provides import dagger.Subcomponent @@ -71,9 +72,13 @@ interface DreamClockTimeComplicationComponent { /* root = */ null, /* attachToRoot = */ false, ) as TextClock, - "R.layout.dream_overlay_complication_clock_time did not properly inflate" + "R.layout.dream_overlay_complication_clock_time did not properly inflate", ) - view.setFontVariationSettings(TAG_WEIGHT + WEIGHT) + if (Flags.dreamOverlayUpdatedFont()) { + view.setFontVariationSettings("'wght' 600, 'opsz' 96") + } else { + view.setFontVariationSettings(TAG_WEIGHT + WEIGHT) + } return view } } diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt index 3b5d5a8f0598..b19b2d9ece02 100644 --- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt @@ -114,7 +114,7 @@ constructor( faceAuthenticationLogger.bouncerVisibilityChanged() runFaceAuth( FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN, - fallbackToDetect = false + fallbackToDetect = false, ) } .launchIn(applicationScope) @@ -125,7 +125,7 @@ constructor( faceAuthenticationLogger.alternateBouncerVisibilityChanged() runFaceAuth( FaceAuthUiEvent.FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN, - fallbackToDetect = false + fallbackToDetect = false, ) } .launchIn(applicationScope) @@ -153,7 +153,7 @@ constructor( it.lastWakeReason.powerManagerWakeReason runFaceAuth( FaceAuthUiEvent.FACE_AUTH_UPDATED_KEYGUARD_VISIBILITY_CHANGED, - fallbackToDetect = true + fallbackToDetect = true, ) } .launchIn(applicationScope) @@ -193,13 +193,16 @@ constructor( .map { (_, curr) -> curr.userInfo.id } .sample(isBouncerVisible, ::Pair) .onEach { (userId, isBouncerCurrentlyVisible) -> + if (!isFaceAuthEnabledAndEnrolled()) { + return@onEach + } resetLockedOutState(userId) yield() runFaceAuth( FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING, // Fallback to detection if bouncer is not showing so that we can detect a // face and then show the bouncer to the user if face auth can't run - fallbackToDetect = !isBouncerCurrentlyVisible + fallbackToDetect = !isBouncerCurrentlyVisible, ) } .launchIn(applicationScope) @@ -210,7 +213,7 @@ constructor( repository.cancel() runFaceAuth( FaceAuthUiEvent.FACE_AUTH_CAMERA_AVAILABLE_CHANGED, - fallbackToDetect = true + fallbackToDetect = true, ) } } @@ -321,7 +324,7 @@ constructor( faceAuthenticationStatusOverride.value = ErrorFaceAuthenticationStatus( BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT, - context.resources.getString(R.string.keyguard_face_unlock_unavailable) + context.resources.getString(R.string.keyguard_face_unlock_unavailable), ) } else { faceAuthenticationStatusOverride.value = null diff --git a/packages/SystemUI/src/com/android/systemui/display/DisplayModule.kt b/packages/SystemUI/src/com/android/systemui/display/DisplayModule.kt index 373279cec5d1..462e820f68da 100644 --- a/packages/SystemUI/src/com/android/systemui/display/DisplayModule.kt +++ b/packages/SystemUI/src/com/android/systemui/display/DisplayModule.kt @@ -20,6 +20,8 @@ import com.android.systemui.display.data.repository.DeviceStateRepository import com.android.systemui.display.data.repository.DeviceStateRepositoryImpl import com.android.systemui.display.data.repository.DisplayRepository import com.android.systemui.display.data.repository.DisplayRepositoryImpl +import com.android.systemui.display.data.repository.FocusedDisplayRepository +import com.android.systemui.display.data.repository.FocusedDisplayRepositoryImpl import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractorImpl import dagger.Binds @@ -39,4 +41,9 @@ interface DisplayModule { fun bindsDeviceStateRepository( deviceStateRepository: DeviceStateRepositoryImpl ): DeviceStateRepository + + @Binds + fun bindsFocusedDisplayRepository( + focusedDisplayRepository: FocusedDisplayRepositoryImpl + ): FocusedDisplayRepository } diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/FocusedDisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/FocusedDisplayRepository.kt index dc07cca08d7b..6fc08f6bfab0 100644 --- a/packages/SystemUI/src/com/android/systemui/display/data/repository/FocusedDisplayRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/FocusedDisplayRepository.kt @@ -19,8 +19,7 @@ package com.android.systemui.display.data.repository import android.annotation.MainThread import android.view.Display.DEFAULT_DISPLAY import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel import com.android.systemui.log.dagger.FocusedDisplayRepoLog @@ -38,20 +37,30 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn /** Repository tracking display focus. */ +interface FocusedDisplayRepository { + /** Provides the currently focused display. */ + val focusedDisplayId: StateFlow<Int> +} + @SysUISingleton @MainThread -class FocusedDisplayRepository +class FocusedDisplayRepositoryImpl @Inject constructor( - @Application val scope: CoroutineScope, - @Main private val mainExecutor: Executor, + @Background val backgroundScope: CoroutineScope, + @Background private val backgroundExecutor: Executor, transitions: ShellTransitions, @FocusedDisplayRepoLog logBuffer: LogBuffer, -) { +) : FocusedDisplayRepository { val focusedTask: Flow<Int> = - conflatedCallbackFlow { - val listener = FocusTransitionListener { displayId -> trySend(displayId) } - transitions.setFocusTransitionListener(listener, mainExecutor) + conflatedCallbackFlow<Int> { + val listener = + object : FocusTransitionListener { + override fun onFocusedDisplayChanged(displayId: Int) { + trySend(displayId) + } + } + transitions.setFocusTransitionListener(listener, backgroundExecutor) awaitClose { transitions.unsetFocusTransitionListener(listener) } } .onEach { @@ -63,7 +72,6 @@ constructor( ) } - /** Provides the currently focused display. */ - val focusedDisplayId: StateFlow<Int> - get() = focusedTask.stateIn(scope, SharingStarted.Eagerly, DEFAULT_DISPLAY) + override val focusedDisplayId: StateFlow<Int> + get() = focusedTask.stateIn(backgroundScope, SharingStarted.Eagerly, DEFAULT_DISPLAY) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/RichOngoingViewModelComponent.kt b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModel.kt index 5552d89b6f9d..8b6cc8cb4540 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/RichOngoingViewModelComponent.kt +++ b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamUserActionsViewModel.kt @@ -14,25 +14,23 @@ * limitations under the License. */ -package com.android.systemui.statusbar.notification.row.ui.viewmodel +package com.android.systemui.dreams.ui.viewmodel -// noinspection CleanArchitectureDependencyViolation -import com.android.systemui.statusbar.notification.row.data.repository.NotificationRowRepository -import dagger.BindsInstance -import dagger.Subcomponent +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult +import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject -@Subcomponent -interface RichOngoingViewModelComponent { +/** Handles user input for the dream scene. */ +class DreamUserActionsViewModel @AssistedInject constructor() : UserActionsViewModel() { - @Subcomponent.Factory - interface Factory { - /** Creates an instance of [RichOngoingViewModelComponent]. */ - fun create( - @BindsInstance repository: NotificationRowRepository - ): RichOngoingViewModelComponent + override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) { + setActions(emptyMap()) } - fun createTimerViewModel(): TimerViewModel - - fun createEnRouteViewModel(): EnRouteViewModel + @AssistedFactory + interface Factory { + fun create(): DreamUserActionsViewModel + } } diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt index 0e2d9b6a3ae0..43e39cf08e01 100644 --- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduStatsInteractor.kt @@ -30,7 +30,7 @@ import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedul import java.time.Clock import javax.inject.Inject import kotlin.time.Duration -import kotlin.time.Duration.Companion.hours +import kotlin.time.Duration.Companion.days import kotlin.time.DurationUnit import kotlin.time.toDuration import kotlinx.coroutines.CoroutineScope @@ -64,7 +64,7 @@ constructor( get() = SystemProperties.getLong( "persist.contextual_edu.initial_delay_sec", - /* defaultValue= */ 72.hours.inWholeSeconds + /* defaultValue= */ 7.days.inWholeSeconds, ) .toDuration(DurationUnit.SECONDS) } diff --git a/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduDialog.kt b/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduDialog.kt index 287e85ca4358..ca92953dca4a 100644 --- a/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/education/ui/view/ContextualEduDialog.kt @@ -16,32 +16,40 @@ package com.android.systemui.education.ui.view -import android.app.AlertDialog +import android.app.Dialog import android.content.Context import android.os.Bundle import android.view.Gravity +import android.view.Window import android.view.WindowManager -import android.widget.ToastPresenter +import android.widget.ImageView +import android.widget.TextView import com.android.systemui.education.ui.viewmodel.ContextualEduToastViewModel import com.android.systemui.res.R class ContextualEduDialog(context: Context, private val model: ContextualEduToastViewModel) : - AlertDialog(context, R.style.ContextualEduDialog) { + Dialog(context) { override fun onCreate(savedInstanceState: Bundle?) { setUpWindowProperties() setWindowPosition() // title is used for a11y announcement window?.setTitle(context.getString(R.string.contextual_education_dialog_title)) - // TODO: b/369791926 - replace the below toast view with a custom dialog view - val toastView = ToastPresenter.getTextToastView(context, model.message) - setView(toastView) + setContentView(R.layout.contextual_edu_dialog) + setContent() super.onCreate(savedInstanceState) } + private fun setContent() { + findViewById<TextView>(R.id.edu_message)?.let { it.text = model.message } + findViewById<ImageView>(R.id.edu_icon)?.let { it.setImageResource(model.icon) } + } + private fun setUpWindowProperties() { window?.apply { + requestFeature(Window.FEATURE_NO_TITLE) setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG) clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) + setBackgroundDrawableResource(android.R.color.transparent) } setCanceledOnTouchOutside(false) } diff --git a/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduContentViewModel.kt index 632b250512cb..5a02cda8c3f5 100644 --- a/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduContentViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduContentViewModel.kt @@ -21,8 +21,11 @@ sealed class ContextualEduContentViewModel(open val userId: Int) data class ContextualEduNotificationViewModel( val title: String, val message: String, - override val userId: Int + override val userId: Int, ) : ContextualEduContentViewModel(userId) -data class ContextualEduToastViewModel(val message: String, override val userId: Int) : - ContextualEduContentViewModel(userId) +data class ContextualEduToastViewModel( + val message: String, + val icon: Int, + override val userId: Int, +) : ContextualEduContentViewModel(userId) diff --git a/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt b/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt index 32e7f41f36b8..7417a7098ea3 100644 --- a/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/education/ui/viewmodel/ContextualEduViewModel.kt @@ -48,7 +48,7 @@ constructor( ) { companion object { - const val DEFAULT_DIALOG_TIMEOUT_MILLIS = 3500 + const val DEFAULT_DIALOG_TIMEOUT_MILLIS = 5000 } private val timeoutMillis: Long @@ -71,7 +71,7 @@ constructor( it.userId, ) } else { - ContextualEduToastViewModel(getEduContent(it), it.userId) + ContextualEduToastViewModel(getEduContent(it), getEduIcon(it), it.userId) } } .timeout(timeoutMillis, emitAfterTimeout = null) @@ -118,4 +118,13 @@ constructor( return resources.getString(resourceId) } + + private fun getEduIcon(educationInfo: EducationInfo): Int { + return when (educationInfo.gestureType) { + BACK -> R.drawable.contextual_edu_swipe_back + HOME, + OVERVIEW -> R.drawable.contextual_edu_swipe_up + ALL_APPS -> R.drawable.contextual_edu_all_apps + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionKeyTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionKeyTutorialScreen.kt index 1aa5ee01f22d..4142be3f9358 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionKeyTutorialScreen.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionKeyTutorialScreen.kt @@ -37,25 +37,22 @@ import androidx.compose.ui.input.key.onKeyEvent import androidx.compose.ui.input.key.type import com.airbnb.lottie.compose.rememberLottieDynamicProperties import com.android.compose.theme.LocalAndroidColorScheme -import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.FINISHED -import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.NOT_STARTED +import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Finished +import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.NotStarted import com.android.systemui.res.R @Composable -fun ActionKeyTutorialScreen( - onDoneButtonClicked: () -> Unit, - onBack: () -> Unit, -) { +fun ActionKeyTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) { BackHandler(onBack = onBack) val screenConfig = buildScreenConfig() - var actionState by remember { mutableStateOf(NOT_STARTED) } + var actionState: TutorialActionState by remember { mutableStateOf(NotStarted) } val focusRequester = remember { FocusRequester() } Box( modifier = Modifier.fillMaxSize() .onKeyEvent { keyEvent: KeyEvent -> if (keyEvent.key == Key.MetaLeft && keyEvent.type == KeyEventType.KeyUp) { - actionState = FINISHED + actionState = Finished } true } @@ -81,13 +78,13 @@ private fun buildScreenConfig() = titleResId = R.string.tutorial_action_key_title, bodyResId = R.string.tutorial_action_key_guidance, titleSuccessResId = R.string.tutorial_action_key_success_title, - bodySuccessResId = R.string.tutorial_action_key_success_body + bodySuccessResId = R.string.tutorial_action_key_success_body, ), animations = TutorialScreenConfig.Animations( educationResId = R.raw.action_key_edu, - successResId = R.raw.action_key_success - ) + successResId = R.raw.action_key_success, + ), ) @Composable @@ -101,7 +98,7 @@ private fun rememberScreenColors(): TutorialScreenConfig.Colors { rememberColorFilterProperty(".primaryFixedDim", primaryFixedDim), rememberColorFilterProperty(".secondaryFixedDim", secondaryFixedDim), rememberColorFilterProperty(".onSecondaryFixed", onSecondaryFixed), - rememberColorFilterProperty(".onSecondaryFixedVariant", onSecondaryFixedVariant) + rememberColorFilterProperty(".onSecondaryFixedVariant", onSecondaryFixedVariant), ) val screenColors = remember(dynamicProperties) { diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionTutorialContent.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionTutorialContent.kt index f32c94b2bc01..73975a088d90 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionTutorialContent.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/composable/ActionTutorialContent.kt @@ -61,15 +61,16 @@ import com.airbnb.lottie.compose.LottieDynamicProperty import com.airbnb.lottie.compose.animateLottieCompositionAsState import com.airbnb.lottie.compose.rememberLottieComposition import com.airbnb.lottie.compose.rememberLottieDynamicProperty -import com.android.compose.modifiers.background -import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.FINISHED -import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.IN_PROGRESS -import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.NOT_STARTED +import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Finished +import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.InProgress +import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.NotStarted -enum class TutorialActionState { - NOT_STARTED, - IN_PROGRESS, - FINISHED, +sealed interface TutorialActionState { + data object NotStarted : TutorialActionState + + data class InProgress(val progress: Float = 0f) : TutorialActionState + + data object Finished : TutorialActionState } @Composable @@ -89,11 +90,11 @@ fun ActionTutorialContent( Row(modifier = Modifier.fillMaxWidth().weight(1f)) { TutorialDescription( titleTextId = - if (actionState == FINISHED) config.strings.titleSuccessResId + if (actionState == Finished) config.strings.titleSuccessResId else config.strings.titleResId, titleColor = config.colors.title, bodyTextId = - if (actionState == FINISHED) config.strings.bodySuccessResId + if (actionState == Finished) config.strings.bodySuccessResId else config.strings.bodyResId, modifier = Modifier.weight(1f), ) @@ -104,7 +105,7 @@ fun ActionTutorialContent( modifier = Modifier.weight(1f).padding(top = 8.dp), ) } - AnimatedVisibility(visible = actionState == FINISHED, enter = fadeIn()) { + AnimatedVisibility(visible = actionState == Finished, enter = fadeIn()) { DoneButton(onDoneButtonClicked = onDoneButtonClicked) } } @@ -142,7 +143,7 @@ fun TutorialAnimation( AnimatedContent( targetState = actionState, transitionSpec = { - if (initialState == NOT_STARTED) { + if (initialState == NotStarted) { val transitionDurationMillis = 150 fadeIn(animationSpec = tween(transitionDurationMillis, easing = LinearEasing)) .togetherWith( @@ -160,17 +161,17 @@ fun TutorialAnimation( }, ) { state -> when (state) { - NOT_STARTED -> + NotStarted -> EducationAnimation( config.animations.educationResId, config.colors.animationColors, ) - IN_PROGRESS -> + is InProgress -> FrozenSuccessAnimation( config.animations.successResId, config.colors.animationColors, ) - FINISHED -> + Finished -> SuccessAnimation(config.animations.successResId, config.colors.animationColors) } } 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 1e9541e1923e..6d1d9cbd9aae 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 @@ -189,6 +189,7 @@ constructor( internalTransitionInteractor.currentTransitionInfoInternal, keyguardInteractor.statusBarState, keyguardInteractor.isKeyguardDismissible, + keyguardInteractor.isKeyguardOccluded, ) .collect { ( @@ -196,7 +197,8 @@ constructor( startedStep, currentTransitionInfo, statusBarState, - isKeyguardUnlocked) -> + isKeyguardUnlocked, + isKeyguardOccluded) -> val id = transitionId if (id != null) { if (startedStep.to == KeyguardState.PRIMARY_BOUNCER) { @@ -236,9 +238,13 @@ constructor( if (nextState == TransitionState.CANCELED) { transitionRepository.startTransition( TransitionInfo( - ownerName = name, + ownerName = + "$name " + + "(on behalf of FromPrimaryBouncerInteractor)", from = KeyguardState.PRIMARY_BOUNCER, - to = KeyguardState.LOCKSCREEN, + to = + if (isKeyguardOccluded) KeyguardState.OCCLUDED + else KeyguardState.LOCKSCREEN, modeOnCanceled = TransitionModeOnCanceled.REVERSE, animator = getDefaultAnimatorForTransitionsToState( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt index 9443570705c8..1497026b5750 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt @@ -19,10 +19,12 @@ package com.android.systemui.keyguard.domain.interactor import com.android.keyguard.logging.ScrimLogger import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.keyguard.data.repository.DEFAULT_REVEAL_DURATION import com.android.systemui.keyguard.data.repository.LightRevealScrimRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.power.shared.model.ScreenPowerState +import com.android.systemui.power.shared.model.WakeSleepReason import com.android.systemui.statusbar.LightRevealEffect import com.android.systemui.util.kotlin.sample import dagger.Lazy @@ -50,11 +52,29 @@ constructor( scope.launch { transitionInteractor.startedKeyguardTransitionStep.collect { scrimLogger.d(TAG, "listenForStartedKeyguardTransitionStep", it) - lightRevealScrimRepository.startRevealAmountAnimator(willBeRevealedInState(it.to)) + val animationDuration = + if (it.to == KeyguardState.AOD && isLastSleepDueToFold) { + // Do not animate the scrim when folding as we want to cover the screen + // with the scrim immediately while displays are switching. + // This is needed to play the fold to AOD animation which starts with + // fully black screen (see FoldAodAnimationController) + 0L + } else { + DEFAULT_REVEAL_DURATION + } + + lightRevealScrimRepository.startRevealAmountAnimator( + willBeRevealedInState(it.to), + duration = animationDuration + ) } } } + private val isLastSleepDueToFold: Boolean + get() = powerInteractor.get().detailedWakefulness.value + .lastSleepReason == WakeSleepReason.FOLD + /** * Whenever a keyguard transition starts, sample the latest reveal effect from the repository * and use that for the starting transition. diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt index 8386628f4c83..57cb10ff9367 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt @@ -121,7 +121,10 @@ object KeyguardPreviewClockViewBinder { private fun applyClockDefaultConstraints(context: Context, constraints: ConstraintSet) { constraints.apply { constrainWidth(R.id.lockscreen_clock_view_large, ConstraintSet.WRAP_CONTENT) - constrainHeight(R.id.lockscreen_clock_view_large, ConstraintSet.MATCH_CONSTRAINT) + // The following two lines make lockscreen_clock_view_large is constrained to available + // height when it goes beyond constraints; otherwise, it use WRAP_CONTENT + constrainHeight(R.id.lockscreen_clock_view_large, WRAP_CONTENT) + constrainMaxHeight(R.id.lockscreen_clock_view_large, 0) val largeClockTopMargin = SystemBarUtils.getStatusBarHeight(context) + context.resources.getDimensionPixelSize( @@ -138,7 +141,7 @@ object KeyguardPreviewClockViewBinder { R.id.lockscreen_clock_view_large, ConstraintSet.END, PARENT_ID, - ConstraintSet.END + ConstraintSet.END, ) // In preview, we'll show UDFPS icon for UDFPS devices @@ -160,14 +163,14 @@ object KeyguardPreviewClockViewBinder { BOTTOM, PARENT_ID, BOTTOM, - clockBottomMargin + clockBottomMargin, ) } constrainWidth(R.id.lockscreen_clock_view, WRAP_CONTENT) constrainHeight( R.id.lockscreen_clock_view, - context.resources.getDimensionPixelSize(customizationR.dimen.small_clock_height) + context.resources.getDimensionPixelSize(customizationR.dimen.small_clock_height), ) connect( R.id.lockscreen_clock_view, @@ -175,7 +178,7 @@ object KeyguardPreviewClockViewBinder { PARENT_ID, START, context.resources.getDimensionPixelSize(customizationR.dimen.clock_padding_start) + - context.resources.getDimensionPixelSize(R.dimen.status_view_margin_horizontal) + context.resources.getDimensionPixelSize(R.dimen.status_view_margin_horizontal), ) val smallClockTopMargin = context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) + @@ -188,7 +191,7 @@ object KeyguardPreviewClockViewBinder { context: Context, rootView: ConstraintLayout, previewClock: ClockController, - viewModel: KeyguardPreviewClockViewModel + viewModel: KeyguardPreviewClockViewModel, ) { val cs = ConstraintSet().apply { clone(rootView) } applyClockDefaultConstraints(context, cs) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt index ca1a8006c6bb..68244d842046 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt @@ -60,6 +60,7 @@ constructor( primaryBouncerToAodTransitionViewModel: PrimaryBouncerToAodTransitionViewModel, primaryBouncerToDozingTransitionViewModel: PrimaryBouncerToDozingTransitionViewModel, primaryBouncerToLockscreenTransitionViewModel: PrimaryBouncerToLockscreenTransitionViewModel, + lockscreenToDozingTransitionViewModel: LockscreenToDozingTransitionViewModel, ) { val color: Flow<Int> = deviceEntryIconViewModel.useBackgroundProtection.flatMapLatest { useBackground -> @@ -103,7 +104,9 @@ constructor( offToLockscreenTransitionViewModel.deviceEntryBackgroundViewAlpha, primaryBouncerToAodTransitionViewModel.deviceEntryBackgroundViewAlpha, primaryBouncerToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha, - primaryBouncerToLockscreenTransitionViewModel.deviceEntryBackgroundViewAlpha, + primaryBouncerToLockscreenTransitionViewModel + .deviceEntryBackgroundViewAlpha, + lockscreenToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha, ) .merge() .onStart { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt index d3eefca67037..7abf35de5dae 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt @@ -55,16 +55,16 @@ constructor( onCancel = { 1f }, ) + val deviceEntryBackgroundViewAlpha: Flow<Float> = + transitionAnimation.immediatelyTransitionTo(0f) + override val deviceEntryParentViewAlpha: Flow<Float> = deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest { isUdfpsEnrolledAndEnabled -> if (isUdfpsEnrolledAndEnabled) { transitionAnimation.immediatelyTransitionTo(1f) } else { - transitionAnimation.sharedFlow( - duration = 250.milliseconds, - onStep = { 1f - it }, - ) + transitionAnimation.sharedFlow(duration = 250.milliseconds, onStep = { 1f - it }) } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt index c0b9efaaec01..914730e1ea4a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt @@ -25,7 +25,7 @@ import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes -import com.android.systemui.scene.ui.composable.transitions.FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION +import com.android.systemui.scene.ui.composable.transitions.TO_BOUNCER_FADE_FRACTION import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -49,14 +49,12 @@ constructor( duration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION, edge = Edge.create(from = LOCKSCREEN, to = Scenes.Bouncer), ) - .setupWithoutSceneContainer( - edge = Edge.create(from = LOCKSCREEN, to = PRIMARY_BOUNCER), - ) + .setupWithoutSceneContainer(edge = Edge.create(from = LOCKSCREEN, to = PRIMARY_BOUNCER)) private val alphaForAnimationStep: (Float) -> Float = when { SceneContainerFlag.isEnabled -> { step -> - 1f - Math.min((step / FROM_LOCK_SCREEN_TO_BOUNCER_FADE_FRACTION), 1f) + 1f - Math.min((step / TO_BOUNCER_FADE_FRACTION), 1f) } else -> { step -> 1f - step } } @@ -64,7 +62,7 @@ constructor( val shortcutsAlpha: Flow<Float> = transitionAnimation.sharedFlow( duration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION, - onStep = alphaForAnimationStep + onStep = alphaForAnimationStep, ) val lockscreenAlpha: Flow<Float> = shortcutsAlpha @@ -76,8 +74,8 @@ constructor( duration = 250.milliseconds, onStep = { 1f - it }, onCancel = { 0f }, - onFinish = { 0f } + onFinish = { 0f }, ), - flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f) + flowWhenShadeIsExpanded = transitionAnimation.immediatelyTransitionTo(0f), ) } diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java index 4e975ff27361..4c21da52db3a 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -369,7 +369,7 @@ public class LogModule { @SysUISingleton @MediaCarouselControllerLog public static LogBuffer provideMediaCarouselControllerBuffer(LogBufferFactory factory) { - return factory.create("MediaCarouselCtlrLog", 20); + return factory.create("MediaCarouselCtlrLog", 100); } /** diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt index 1be25a74dbea..9b443f56636a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerLogger.kt @@ -39,7 +39,7 @@ constructor(@MediaCarouselControllerLog private val buffer: LogBuffer) { { "Potential memory leak: " + "Removing control panel for $str1 from map without calling #onDestroy" - } + }, ) fun logMediaLoaded(key: String, active: Boolean) = @@ -50,7 +50,7 @@ constructor(@MediaCarouselControllerLog private val buffer: LogBuffer) { str1 = key bool1 = active }, - { "add player $str1, active: $bool1" } + { "add player $str1, active: $bool1" }, ) fun logMediaRemoved(key: String, userInitiated: Boolean) = @@ -61,7 +61,7 @@ constructor(@MediaCarouselControllerLog private val buffer: LogBuffer) { str1 = key bool1 = userInitiated }, - { "removing player $str1, by user $bool1" } + { "removing player $str1, by user $bool1" }, ) fun logRecommendationLoaded(key: String, isActive: Boolean) = @@ -72,7 +72,7 @@ constructor(@MediaCarouselControllerLog private val buffer: LogBuffer) { str1 = key bool1 = isActive }, - { "add recommendation $str1, active $bool1" } + { "add recommendation $str1, active $bool1" }, ) fun logRecommendationRemoved(key: String, immediately: Boolean) = @@ -83,12 +83,24 @@ constructor(@MediaCarouselControllerLog private val buffer: LogBuffer) { str1 = key bool1 = immediately }, - { "removing recommendation $str1, immediate=$bool1" } + { "removing recommendation $str1, immediate=$bool1" }, ) fun logCarouselHidden() = buffer.log(TAG, LogLevel.DEBUG, {}, { "hiding carousel" }) fun logCarouselVisible() = buffer.log(TAG, LogLevel.DEBUG, {}, { "showing carousel" }) + + fun logMediaHostVisibility(location: Int, visible: Boolean) { + buffer.log( + TAG, + LogLevel.DEBUG, + { + int1 = location + bool1 = visible + }, + { "media host visibility changed location=$location, visible:$visible" }, + ) + } } private const val TAG = "MediaCarouselCtlrLog" diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt index 5ddc3470da43..11251cdb6315 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt @@ -25,6 +25,7 @@ import com.android.systemui.media.controls.domain.pipeline.MediaDataManager import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.media.controls.shared.model.SmartspaceMediaData import com.android.systemui.media.controls.ui.controller.MediaCarouselController +import com.android.systemui.media.controls.ui.controller.MediaCarouselControllerLogger import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager import com.android.systemui.media.controls.ui.controller.MediaHostStatesManager import com.android.systemui.media.controls.ui.controller.MediaLocation @@ -41,6 +42,7 @@ class MediaHost( private val mediaDataManager: MediaDataManager, private val mediaHostStatesManager: MediaHostStatesManager, private val mediaCarouselController: MediaCarouselController, + private val debugLogger: MediaCarouselControllerLogger, ) : MediaHostState by state { lateinit var hostView: UniqueObjectHostView var location: Int = -1 @@ -217,6 +219,7 @@ class MediaHost( val newVisibility = if (visible) View.VISIBLE else View.GONE if (newVisibility != hostView.visibility) { hostView.visibility = newVisibility + debugLogger.logMediaHostVisibility(location, visible) visibleChangedListeners.forEach { it.invoke(visible) } } } diff --git a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java index 59b98b2792be..36a9fb3eb753 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java +++ b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java @@ -22,6 +22,7 @@ import com.android.systemui.log.LogBufferFactory; import com.android.systemui.media.controls.domain.MediaDomainModule; import com.android.systemui.media.controls.domain.pipeline.MediaDataManager; import com.android.systemui.media.controls.ui.controller.MediaCarouselController; +import com.android.systemui.media.controls.ui.controller.MediaCarouselControllerLogger; import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager; import com.android.systemui.media.controls.ui.controller.MediaHostStatesManager; import com.android.systemui.media.controls.ui.view.MediaHost; @@ -60,9 +61,10 @@ public interface MediaModule { @Named(QS_PANEL) static MediaHost providesQSMediaHost(MediaHost.MediaHostStateHolder stateHolder, MediaHierarchyManager hierarchyManager, MediaDataManager dataManager, - MediaHostStatesManager statesManager, MediaCarouselController carouselController) { + MediaHostStatesManager statesManager, MediaCarouselController carouselController, + MediaCarouselControllerLogger logger) { return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager, - carouselController); + carouselController, logger); } /** */ @@ -71,9 +73,10 @@ public interface MediaModule { @Named(QUICK_QS_PANEL) static MediaHost providesQuickQSMediaHost(MediaHost.MediaHostStateHolder stateHolder, MediaHierarchyManager hierarchyManager, MediaDataManager dataManager, - MediaHostStatesManager statesManager, MediaCarouselController carouselController) { + MediaHostStatesManager statesManager, MediaCarouselController carouselController, + MediaCarouselControllerLogger logger) { return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager, - carouselController); + carouselController, logger); } /** */ @@ -82,9 +85,10 @@ public interface MediaModule { @Named(KEYGUARD) static MediaHost providesKeyguardMediaHost(MediaHost.MediaHostStateHolder stateHolder, MediaHierarchyManager hierarchyManager, MediaDataManager dataManager, - MediaHostStatesManager statesManager, MediaCarouselController carouselController) { + MediaHostStatesManager statesManager, MediaCarouselController carouselController, + MediaCarouselControllerLogger logger) { return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager, - carouselController); + carouselController, logger); } /** */ @@ -93,9 +97,10 @@ public interface MediaModule { @Named(DREAM) static MediaHost providesDreamMediaHost(MediaHost.MediaHostStateHolder stateHolder, MediaHierarchyManager hierarchyManager, MediaDataManager dataManager, - MediaHostStatesManager statesManager, MediaCarouselController carouselController) { + MediaHostStatesManager statesManager, MediaCarouselController carouselController, + MediaCarouselControllerLogger logger) { return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager, - carouselController); + carouselController, logger); } /** */ @@ -104,9 +109,10 @@ public interface MediaModule { @Named(COMMUNAL_HUB) static MediaHost providesCommunalMediaHost(MediaHost.MediaHostStateHolder stateHolder, MediaHierarchyManager hierarchyManager, MediaDataManager dataManager, - MediaHostStatesManager statesManager, MediaCarouselController carouselController) { + MediaHostStatesManager statesManager, MediaCarouselController carouselController, + MediaCarouselControllerLogger logger) { return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager, - carouselController); + carouselController, logger); } /** Provides a logging buffer related to the media tap-to-transfer chip on the sender device. */ 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 5048a5dfdec0..b3463bdc2949 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -64,7 +64,6 @@ import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Surface; -import android.view.VelocityTracker; import android.view.ViewConfiguration; import android.view.WindowInsets; import android.view.WindowManager; @@ -191,7 +190,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack } }; - private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); private final Context mContext; private final UserTracker mUserTracker; private final OverviewProxyService mOverviewProxyService; @@ -1042,10 +1040,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack mIsTrackpadThreeFingerSwipe = isTrackpadThreeFingerSwipe(ev); - // ACTION_UP or ACTION_CANCEL is not guaranteed to be called before a new - // ACTION_DOWN, in that case we should just reuse the old instance. - mVelocityTracker.clear(); - // Verify if this is in within the touch region and we aren't in immersive mode, and // either the bouncer is showing or the notification panel is hidden mInputEventReceiver.setBatchingEnabled(false); @@ -1194,28 +1188,9 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack private void dispatchToBackAnimation(MotionEvent event) { if (mBackAnimation != null) { - mVelocityTracker.addMovement(event); - - final float velocityX; - final float velocityY; - if (event.getAction() == MotionEvent.ACTION_UP) { - // Compute the current velocity is expensive (see computeCurrentVelocity), so we - // are only doing it when the user completes the gesture. - int unitPixelPerSecond = 1000; - int maxVelocity = mViewConfiguration.getScaledMaximumFlingVelocity(); - mVelocityTracker.computeCurrentVelocity(unitPixelPerSecond, maxVelocity); - velocityX = mVelocityTracker.getXVelocity(); - velocityY = mVelocityTracker.getYVelocity(); - } else { - velocityX = Float.NaN; - velocityY = Float.NaN; - } - mBackAnimation.onBackMotion( /* touchX = */ event.getX(), /* touchY = */ event.getY(), - /* velocityX = */ velocityX, - /* velocityY = */ velocityY, /* keyAction = */ event.getActionMasked(), /* swipeEdge = */ mIsOnLeftEdge ? BackEvent.EDGE_LEFT : BackEvent.EDGE_RIGHT); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt index 51d232946b97..65c29b829429 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt @@ -52,8 +52,8 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.approachLayout import androidx.compose.ui.layout.onPlaced -import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.positionInRoot import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.res.dimensionResource @@ -66,6 +66,9 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle +import com.android.compose.animation.scene.ContentKey +import com.android.compose.animation.scene.ElementKey +import com.android.compose.animation.scene.ElementMatcher import com.android.compose.animation.scene.MutableSceneTransitionLayoutState import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.SceneScope @@ -288,7 +291,7 @@ constructor( transitions = transitions { from(QuickQuickSettings, QuickSettings) { - quickQuickSettingsToQuickSettings() + quickQuickSettingsToQuickSettings(viewModel::inFirstPage::get) } }, ) @@ -533,6 +536,10 @@ constructor( onDispose { qqsVisible.value = false } } + val squishiness by + viewModel.containerViewModel.quickQuickSettingsViewModel.squishinessViewModel + .squishiness + .collectAsStateWithLifecycle() Column(modifier = Modifier.sysuiResTag("quick_qs_panel")) { Box( modifier = @@ -546,7 +553,16 @@ constructor( topFromRoot + coordinates.size.height, ) } - .onSizeChanged { size -> qqsHeight.value = size.height } + // Use an approach layout to determien the height without squishiness, as + // that's the value that NPVC and QuickSettingsController care about + // (measured height). + .approachLayout(isMeasurementApproachInProgress = { squishiness < 1f }) { + measurable, + constraints -> + qqsHeight.value = lookaheadSize.height + val placeable = measurable.measure(constraints) + layout(placeable.width, placeable.height) { placeable.place(0, 0) } + } .padding(top = { qqsPadding }, bottom = { bottomPadding.roundToPx() }) ) { val qsEnabled by viewModel.qsEnabled.collectAsStateWithLifecycle() @@ -704,6 +720,14 @@ object SceneKeys { else -> QuickSettings } } + + val QqsTileElementMatcher = + object : ElementMatcher { + override fun matches(key: ElementKey, content: ContentKey): Boolean { + return content == SceneKeys.QuickQuickSettings && + ElementKeys.TileElementMatcher.matches(key, content) + } + } } suspend fun synchronizeQsState(state: MutableSceneTransitionLayoutState, expansion: Flow<Float>) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/FromQuickQuickSettingsToQuickSettings.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/FromQuickQuickSettingsToQuickSettings.kt index 1514986d16d9..9e3945ecba57 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/FromQuickQuickSettingsToQuickSettings.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/FromQuickQuickSettingsToQuickSettings.kt @@ -17,13 +17,23 @@ package com.android.systemui.qs.composefragment.ui import com.android.compose.animation.scene.TransitionBuilder +import com.android.systemui.qs.composefragment.SceneKeys import com.android.systemui.qs.shared.ui.ElementKeys -fun TransitionBuilder.quickQuickSettingsToQuickSettings() { +fun TransitionBuilder.quickQuickSettingsToQuickSettings(inFirstPage: () -> Boolean = { true }) { fractionRange(start = 0.5f) { fade(ElementKeys.QuickSettingsContent) } fractionRange(start = 0.9f) { fade(ElementKeys.FooterActions) } anchoredTranslate(ElementKeys.QuickSettingsContent, ElementKeys.GridAnchor) + + sharedElement(ElementKeys.TileElementMatcher, enabled = inFirstPage()) + + // This will animate between 0f (QQS) and 0.6, fading in the QQS tiles when coming back + // from non first page QS. The QS content ends fading out at 0.5f, so there's a brief + // overlap, but because they are really faint, it looks better than complete black without + // overlap. + fractionRange(end = 0.6f) { fade(SceneKeys.QqsTileElementMatcher) } + anchoredTranslate(SceneKeys.QqsTileElementMatcher, ElementKeys.GridAnchor) } diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt index 2d4e358414d5..7a8b2c2eb685 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt @@ -31,6 +31,7 @@ import com.android.systemui.qs.FooterActionsController import com.android.systemui.qs.composefragment.viewmodel.QSFragmentComposeViewModel.QSExpansionState import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel import com.android.systemui.qs.panels.domain.interactor.TileSquishinessInteractor +import com.android.systemui.qs.panels.ui.viewmodel.PaginatedGridViewModel import com.android.systemui.qs.ui.viewmodel.QuickSettingsContainerViewModel import com.android.systemui.shade.LargeScreenHeaderHelper import com.android.systemui.shade.transition.LargeScreenShadeInterpolator @@ -71,6 +72,7 @@ constructor( private val configurationInteractor: ConfigurationInteractor, private val largeScreenHeaderHelper: LargeScreenHeaderHelper, private val squishinessInteractor: TileSquishinessInteractor, + private val paginatedGridViewModel: PaginatedGridViewModel, @Assisted private val lifecycleScope: LifecycleCoroutineScope, ) : Dumpable, ExclusiveActivatable() { val footerActionsViewModel = @@ -292,6 +294,9 @@ constructor( */ var collapseExpandAccessibilityAction: Runnable? = null + val inFirstPage: Boolean + get() = paginatedGridViewModel.inFirstPage + override suspend fun onActivated(): Nothing { hydrateSquishinessInteractor() } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PagerDots.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PagerDots.kt index 331aabb532a5..0dedfe125d6f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PagerDots.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PagerDots.kt @@ -46,6 +46,8 @@ import androidx.compose.ui.unit.dp import kotlin.math.absoluteValue import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +import platform.test.motion.compose.values.MotionTestValueKey +import platform.test.motion.compose.values.motionTestValues @Composable fun PagerDots( @@ -93,13 +95,22 @@ fun PagerDots( } Row( - modifier = modifier.wrapContentWidth().pagerDotsSemantics(pagerState, coroutineScope), + modifier = + modifier + .motionTestValues { activeMarkerWidth exportAs PagerDotsMotionKeys.indicatorWidth } + .wrapContentWidth() + .pagerDotsSemantics(pagerState, coroutineScope), horizontalArrangement = spacedBy(spaceSize), verticalAlignment = Alignment.CenterVertically, ) { // This means that the active rounded rect has to be drawn between the current page // and the previous one (as we are animating back), or the current one if not transitioning - val withPrevious = pagerState.currentPageOffsetFraction <= 0 || pagerState.isOverscrolling() + val withPrevious by + remember(pagerState) { + derivedStateOf { + pagerState.currentPageOffsetFraction <= 0 || pagerState.isOverscrolling() + } + } repeat(pagerState.pageCount) { page -> Canvas(Modifier.size(dotSize)) { val rtl = layoutDirection == LayoutDirection.Rtl @@ -127,6 +138,10 @@ fun PagerDots( } } +object PagerDotsMotionKeys { + val indicatorWidth = MotionTestValueKey<Dp>("indicatorWidth") +} + private fun Modifier.pagerDotsSemantics( pagerState: PagerState, coroutineScope: CoroutineScope, diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt index 083f529a21da..e749475479d8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt @@ -31,8 +31,10 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -76,6 +78,11 @@ constructor( val pagerState = rememberPagerState(0) { pages.size } + // Used to track if this is currently in the first page or not, for animations + LaunchedEffect(key1 = pagerState) { + snapshotFlow { pagerState.currentPage == 0 }.collect { viewModel.inFirstPage = it } + } + Column { HorizontalPager( state = pagerState, diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/SquishTile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/SquishTile.kt index ada1ef4de15d..91f76418824e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/SquishTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/SquishTile.kt @@ -17,7 +17,7 @@ package com.android.systemui.qs.panels.ui.compose.infinitegrid import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.layout +import androidx.compose.ui.layout.approachLayout import kotlin.math.roundToInt /** @@ -27,17 +27,22 @@ import kotlin.math.roundToInt * [squishiness] on the measure/layout pass. * * The squished composable will be center aligned. + * + * Use an [approachLayout] to indicate that this should be measured in the lookahead step without + * using squishiness. If a parent of this node needs to determine unsquished height, they should + * also use an approachLayout tracking the squishiness. */ fun Modifier.verticalSquish(squishiness: () -> Float): Modifier { - return layout { measurable, constraints -> - val placeable = measurable.measure(constraints) - val actualHeight = placeable.height - val squishedHeight = actualHeight * squishiness() + return approachLayout(isMeasurementApproachInProgress = { squishiness() < 1 }) { measurable, _ + -> + val squishinessValue = squishiness() + val expectedHeight = lookaheadSize.height + + val placeable = measurable.measure(lookaheadConstraints) + val squishedHeight = (expectedHeight * squishinessValue).roundToInt() // Center the content by moving it UP (squishedHeight < actualHeight) - val scroll = (squishedHeight - actualHeight) / 2 + val scroll = (squishedHeight - expectedHeight) / 2 - layout(placeable.width, squishedHeight.roundToInt()) { - placeable.place(0, scroll.roundToInt()) - } + layout(placeable.width, squishedHeight) { placeable.place(0, scroll) } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt index 28bf47400c4d..d4f82983469b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt @@ -43,4 +43,10 @@ constructor( SharingStarted.WhileSubscribed(), paginatedGridInteractor.defaultRows, ) + + /* + * Tracks whether the current HorizontalPager (using this viewmodel) is in the first page. + * This requires it to be a `@SysUISingleton` to be shared between viewmodels. + */ + var inFirstPage = true } diff --git a/packages/SystemUI/src/com/android/systemui/qs/shared/ui/ElementKeys.kt b/packages/SystemUI/src/com/android/systemui/qs/shared/ui/ElementKeys.kt index 625459d1c6fa..2425f137f1fb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/shared/ui/ElementKeys.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/shared/ui/ElementKeys.kt @@ -25,7 +25,10 @@ object ElementKeys { val GridAnchor = ElementKey("QuickSettingsGridAnchor") val FooterActions = ElementKey("FooterActions") - class TileElementKey(spec: TileSpec, val position: Int) : ElementKey(spec.spec, spec.spec) + fun TileSpec.toElementKey(positionInGrid: Int) = + ElementKey(this.spec, TileIdentity(this, positionInGrid)) - fun TileSpec.toElementKey(positionInGrid: Int) = TileElementKey(this, positionInGrid) + val TileElementMatcher = ElementKey.withIdentity { it is TileIdentity } } + +private data class TileIdentity(val spec: TileSpec, val position: Int) 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 a4fe4e3e1243..ad76b4f21bfb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -169,50 +169,34 @@ public class DndTile extends QSTileImpl<BooleanState> { private void enableZenMode(@Nullable Expandable expandable) { int zenDuration = mSettingZenDuration.getValue(); - boolean showOnboarding = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0 - && Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1; - if (showOnboarding) { - // don't show on-boarding again or notification ever - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); - // turn on DND - mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG); - // show on-boarding screen - Intent intent = new Intent(Settings.ZEN_MODE_ONBOARDING); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - mActivityStarter.postStartActivityDismissingKeyguard(intent, 0); - } else { - switch (zenDuration) { - case Settings.Secure.ZEN_DURATION_PROMPT: - mUiHandler.post(() -> { - Dialog dialog = makeZenModeDialog(); - if (expandable != null) { - DialogTransitionAnimator.Controller controller = - expandable.dialogTransitionController(new DialogCuj( - InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, - INTERACTION_JANK_TAG)); - if (controller != null) { - mDialogTransitionAnimator.show(dialog, - controller, /* animateBackgroundBoundsChange= */ false); - } else { - dialog.show(); - } + switch (zenDuration) { + case Settings.Secure.ZEN_DURATION_PROMPT: + mUiHandler.post(() -> { + Dialog dialog = makeZenModeDialog(); + if (expandable != null) { + DialogTransitionAnimator.Controller controller = + expandable.dialogTransitionController(new DialogCuj( + InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, + INTERACTION_JANK_TAG)); + if (controller != null) { + mDialogTransitionAnimator.show(dialog, + controller, /* animateBackgroundBoundsChange= */ false); } else { dialog.show(); } - }); - break; - case Settings.Secure.ZEN_DURATION_FOREVER: - mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG); - break; - default: - Uri conditionId = ZenModeConfig.toTimeCondition(mContext, zenDuration, - mHost.getUserId(), true).id; - mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, - conditionId, TAG); - } + } else { + dialog.show(); + } + }); + break; + case Settings.Secure.ZEN_DURATION_FOREVER: + mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG); + break; + default: + Uri conditionId = ZenModeConfig.toTimeCondition(mContext, zenDuration, + mHost.getUserId(), true).id; + mController.setZen(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, + conditionId, TAG); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt index d89e73d2c69f..fb406d47d7a6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt @@ -45,10 +45,11 @@ import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.recordissue.IssueRecordingService.Companion.getStartIntent import com.android.systemui.recordissue.IssueRecordingService.Companion.getStopIntent +import com.android.systemui.recordissue.IssueRecordingServiceConnection import com.android.systemui.recordissue.IssueRecordingState import com.android.systemui.recordissue.RecordIssueDialogDelegate import com.android.systemui.recordissue.RecordIssueModule.Companion.TILE_SPEC -import com.android.systemui.recordissue.TraceurMessageSender +import com.android.systemui.recordissue.TraceurConnection import com.android.systemui.res.R import com.android.systemui.screenrecord.RecordingController import com.android.systemui.screenrecord.RecordingService @@ -66,7 +67,7 @@ class RecordIssueTile constructor( host: QSHost, uiEventLogger: QsEventLogger, - @Background backgroundLooper: Looper, + @Background private val backgroundLooper: Looper, @Main mainHandler: Handler, falsingManager: FalsingManager, metricsLogger: MetricsLogger, @@ -78,7 +79,8 @@ constructor( private val dialogTransitionAnimator: DialogTransitionAnimator, private val panelInteractor: PanelInteractor, private val userContextProvider: UserContextProvider, - private val traceurMessageSender: TraceurMessageSender, + irsConnProvider: IssueRecordingServiceConnection.Provider, + traceurConnProvider: TraceurConnection.Provider, @Background private val bgExecutor: Executor, private val issueRecordingState: IssueRecordingState, private val delegateFactory: RecordIssueDialogDelegate.Factory, @@ -93,11 +95,20 @@ constructor( metricsLogger, statusBarStateController, activityStarter, - qsLogger + qsLogger, ) { private val onRecordingChangeListener = Runnable { refreshState() } + private val irsConnection: IssueRecordingServiceConnection = irsConnProvider.create() + private val traceurConnection = + traceurConnProvider.create().apply { + onBound.add { + getTags(issueRecordingState) + doUnBind() + } + } + override fun handleSetListening(listening: Boolean) { super.handleSetListening(listening) if (listening) { @@ -109,7 +120,7 @@ constructor( override fun handleDestroy() { super.handleDestroy() - bgExecutor.execute { traceurMessageSender.unbindFromTraceur(mContext) } + bgExecutor.execute { irsConnection.doUnBind() } } override fun getTileLabel(): CharSequence = mContext.getString(R.string.qs_record_issue_label) @@ -142,7 +153,7 @@ constructor( DELAY_MS, INTERVAL_MS, pendingServiceIntent(getStartIntent(userContextProvider.userContext)), - pendingServiceIntent(getStopIntent(userContextProvider.userContext)) + pendingServiceIntent(getStopIntent(userContextProvider.userContext)), ) private fun stopIssueRecordingService() = @@ -154,10 +165,19 @@ constructor( userContextProvider.userContext, RecordingService.REQUEST_CODE, action, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, ) private fun showPrompt(expandable: Expandable?) { + bgExecutor.execute { + // We only want to get the tags once per session, as this is not likely to change, if at + // all on a month to month basis. Using onBound's size is a way to verify if the tag + // retrieval has already happened or not. + if (traceurConnection.onBound.isNotEmpty()) { + traceurConnection.doBind() + } + irsConnection.doBind() + } val dialog: AlertDialog = delegateFactory .create { diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt index 4d2bc91aa52a..3f875bcc288b 100644 --- a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt +++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt @@ -23,9 +23,12 @@ import android.content.Intent import android.content.res.Resources import android.net.Uri import android.os.Handler +import android.os.IBinder +import android.os.Looper import android.util.Log import com.android.internal.logging.UiEventLogger import com.android.systemui.animation.DialogTransitionAnimator +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.LongRunning import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor @@ -42,6 +45,7 @@ class IssueRecordingService @Inject constructor( controller: RecordingController, + @Background private val bgLooper: Looper, @LongRunning private val bgExecutor: Executor, @Main handler: Handler, uiEventLogger: UiEventLogger, @@ -50,8 +54,8 @@ constructor( keyguardDismissUtil: KeyguardDismissUtil, dialogTransitionAnimator: DialogTransitionAnimator, panelInteractor: PanelInteractor, - traceurMessageSender: TraceurMessageSender, private val issueRecordingState: IssueRecordingState, + traceurConnectionProvider: TraceurConnection.Provider, iActivityManager: IActivityManager, ) : RecordingService( @@ -64,18 +68,37 @@ constructor( keyguardDismissUtil, ) { + private val traceurConnection: TraceurConnection = traceurConnectionProvider.create() + private val session = IssueRecordingServiceSession( bgExecutor, dialogTransitionAnimator, panelInteractor, - traceurMessageSender, + traceurConnection, issueRecordingState, iActivityManager, notificationManager, userContextProvider, ) + /** + * It is necessary to bind to IssueRecordingService from the Record Issue Tile because there are + * instances where this service is not created in the same user profile as the record issue tile + * aka, headless system user mode. In those instances, the TraceurConnection will be considered + * a leak in between notification actions unless the tile is bound to this service to keep it + * alive. + */ + override fun onBind(intent: Intent): IBinder? { + traceurConnection.doBind() + return super.onBind(intent) + } + + override fun onUnbind(intent: Intent?): Boolean { + traceurConnection.doUnBind() + return super.onUnbind(intent) + } + override fun getTag(): String = TAG override fun getChannelId(): String = CHANNEL_ID @@ -99,7 +122,6 @@ constructor( session.share( intent.getIntExtra(EXTRA_NOTIFICATION_ID, mNotificationId), intent.getParcelableExtra(EXTRA_PATH, Uri::class.java), - this, ) // Unlike all other actions, action_share has different behavior for the screen // recording qs tile than it does for the record issue qs tile. Return sticky to diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceConnection.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceConnection.kt new file mode 100644 index 000000000000..85a580558125 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceConnection.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.systemui.recordissue + +import android.content.Intent +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.settings.UserContextProvider +import com.android.traceur.MessageConstants.SYSTEM_UI_PACKAGE_NAME +import javax.inject.Inject + +/** + * It is necessary to bind to IssueRecordingService from the Record Issue Tile because there are + * instances where this service is not created in the same user profile as the record issue tile + * aka, headless system user mode. In those instances, the TraceurConnection will be considered a + * leak in between notification actions unless the tile is bound to this service to keep it alive. + */ +class IssueRecordingServiceConnection(userContextProvider: UserContextProvider) : + UserAwareConnection( + userContextProvider, + Intent().setClassName(SYSTEM_UI_PACKAGE_NAME, IssueRecordingService::class.java.name), + ) { + @SysUISingleton + class Provider @Inject constructor(private val userContextProvider: UserContextProvider) { + fun create() = IssueRecordingServiceConnection(userContextProvider) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt index e4d3e6cae502..ad9b4fe164e8 100644 --- a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt +++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt @@ -19,7 +19,6 @@ package com.android.systemui.recordissue import android.app.IActivityManager import android.app.NotificationManager import android.content.ContentResolver -import android.content.Context import android.net.Uri import android.os.UserHandle import android.provider.Settings @@ -42,7 +41,7 @@ class IssueRecordingServiceSession( private val bgExecutor: Executor, private val dialogTransitionAnimator: DialogTransitionAnimator, private val panelInteractor: PanelInteractor, - private val traceurMessageSender: TraceurMessageSender, + private val traceurConnection: TraceurConnection, private val issueRecordingState: IssueRecordingState, private val iActivityManager: IActivityManager, private val notificationManager: NotificationManager, @@ -50,7 +49,7 @@ class IssueRecordingServiceSession( ) { fun start() { - bgExecutor.execute { traceurMessageSender.startTracing(issueRecordingState.traceConfig) } + bgExecutor.execute { traceurConnection.startTracing(issueRecordingState.traceConfig) } issueRecordingState.isRecording = true } @@ -59,12 +58,12 @@ class IssueRecordingServiceSession( if (issueRecordingState.traceConfig.longTrace) { Settings.Global.putInt(contentResolver, NOTIFY_SESSION_ENDED_SETTING, DISABLED) } - traceurMessageSender.stopTracing() + traceurConnection.stopTracing() } issueRecordingState.isRecording = false } - fun share(notificationId: Int, screenRecording: Uri?, context: Context) { + fun share(notificationId: Int, screenRecording: Uri?) { bgExecutor.execute { notificationManager.cancelAsUser( null, @@ -75,7 +74,7 @@ class IssueRecordingServiceSession( if (issueRecordingState.takeBugreport) { iActivityManager.requestBugReportWithExtraAttachment(screenRecording) } else { - traceurMessageSender.shareTraces(context, screenRecording) + traceurConnection.shareTraces(screenRecording) } } diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt index ed67e64dfb76..6758c3ba0767 100644 --- a/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt +++ b/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt @@ -64,7 +64,6 @@ constructor( private val mediaProjectionMetricsLogger: MediaProjectionMetricsLogger, private val screenCaptureDisabledDialogDelegate: ScreenCaptureDisabledDialogDelegate, private val state: IssueRecordingState, - private val traceurMessageSender: TraceurMessageSender, @Assisted private val onStarted: Runnable, ) : SystemUIDialog.Delegate { @@ -87,10 +86,6 @@ constructor( setNegativeButton(R.string.cancel) { _, _ -> } setPositiveButton(R.string.qs_record_issue_start) { _, _ -> onStarted.run() } } - bgExecutor.execute { - traceurMessageSender.onBoundToTraceur.add { traceurMessageSender.getTags(state) } - traceurMessageSender.bindToTraceur(dialog.context) - } } override fun createDialog(): SystemUIDialog = factory.create(this) @@ -151,7 +146,7 @@ constructor( mediaProjectionMetricsLogger.notifyProjectionInitiated( userTracker.userId, - SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER + SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER, ) if (!state.hasUserApprovedScreenRecording) { @@ -189,7 +184,7 @@ constructor( CustomTraceSettingsDialogDelegate( factory, state.customTraceState, - state.tagTitles + state.tagTitles, ) { onMenuItemClickListener.onMenuItemClick(it) } diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/TraceurConnection.kt b/packages/SystemUI/src/com/android/systemui/recordissue/TraceurConnection.kt new file mode 100644 index 000000000000..81529b357527 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recordissue/TraceurConnection.kt @@ -0,0 +1,152 @@ +/* + * 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.recordissue + +import android.content.ComponentName +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.os.Handler +import android.os.IBinder +import android.os.Looper +import android.os.Message +import android.os.Messenger +import android.util.Log +import androidx.annotation.WorkerThread +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.recordissue.IssueRecordingState.Companion.TAG_TITLE_DELIMITER +import com.android.systemui.settings.UserContextProvider +import com.android.traceur.FileSender +import com.android.traceur.MessageConstants +import com.android.traceur.MessageConstants.TRACING_APP_ACTIVITY +import com.android.traceur.MessageConstants.TRACING_APP_PACKAGE_NAME +import com.android.traceur.TraceConfig +import java.util.concurrent.CopyOnWriteArrayList +import javax.inject.Inject + +private const val TAG = "TraceurConnection" + +class TraceurConnection +private constructor(userContextProvider: UserContextProvider, private val bgLooper: Looper) : + UserAwareConnection( + userContextProvider, + Intent().setClassName(TRACING_APP_PACKAGE_NAME, TRACING_APP_ACTIVITY), + ) { + + @SysUISingleton + class Provider + @Inject + constructor( + private val userContextProvider: UserContextProvider, + @Background private val bgLooper: Looper, + ) { + fun create() = TraceurConnection(userContextProvider, bgLooper) + } + + val onBound: MutableList<Runnable> = CopyOnWriteArrayList(mutableListOf()) + + override fun onServiceConnected(className: ComponentName, service: IBinder) { + super.onServiceConnected(className, service) + onBound.forEach(Runnable::run) + onBound.clear() + } + + @WorkerThread + fun startTracing(traceType: TraceConfig) { + val data = + Bundle().apply { putParcelable(MessageConstants.INTENT_EXTRA_TRACE_TYPE, traceType) } + sendMessage(MessageConstants.START_WHAT, data) + } + + @WorkerThread fun stopTracing() = sendMessage(MessageConstants.STOP_WHAT) + + @WorkerThread + fun shareTraces(screenRecord: Uri?) { + val replyHandler = Messenger(ShareFilesHandler(screenRecord, userContextProvider, bgLooper)) + sendMessage(MessageConstants.SHARE_WHAT, replyTo = replyHandler) + } + + @WorkerThread + fun getTags(state: IssueRecordingState) = + sendMessage(MessageConstants.TAGS_WHAT, replyTo = Messenger(TagsHandler(bgLooper, state))) + + @WorkerThread + private fun sendMessage(what: Int, data: Bundle = Bundle(), replyTo: Messenger? = null) = + try { + val msg = + Message.obtain().apply { + this.what = what + this.data = data + this.replyTo = replyTo + } + binder?.send(msg) ?: onBound.add { binder!!.send(msg) } + } catch (e: Exception) { + Log.e(TAG, "failed to notify Traceur", e) + } +} + +private class ShareFilesHandler( + private val screenRecord: Uri?, + private val userContextProvider: UserContextProvider, + looper: Looper, +) : Handler(looper) { + + override fun handleMessage(msg: Message) { + if (MessageConstants.SHARE_WHAT == msg.what) { + shareTraces( + msg.data.getParcelable(MessageConstants.EXTRA_PERFETTO, Uri::class.java), + msg.data.getParcelable(MessageConstants.EXTRA_WINSCOPE, Uri::class.java), + ) + } else { + throw IllegalArgumentException("received unknown msg.what: " + msg.what) + } + } + + private fun shareTraces(perfetto: Uri?, winscope: Uri?) { + val uris: ArrayList<Uri> = + ArrayList<Uri>().apply { + perfetto?.let { add(it) } + winscope?.let { add(it) } + screenRecord?.let { add(it) } + } + val fileSharingIntent = + FileSender.buildSendIntent(userContextProvider.userContext, uris) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) + userContextProvider.userContext.startActivity(fileSharingIntent) + } +} + +private class TagsHandler(looper: Looper, private val state: IssueRecordingState) : + Handler(looper) { + + override fun handleMessage(msg: Message) { + if (MessageConstants.TAGS_WHAT == msg.what) { + val keys = msg.data.getStringArrayList(MessageConstants.BUNDLE_KEY_TAGS) + val values = msg.data.getStringArrayList(MessageConstants.BUNDLE_KEY_TAG_DESCRIPTIONS) + if (keys == null || values == null) { + throw IllegalArgumentException( + "Neither keys: $keys, nor values: $values can be null" + ) + } + state.tagTitles = + keys.zip(values).map { it.first + TAG_TITLE_DELIMITER + it.second }.toSet() + } else { + throw IllegalArgumentException("received unknown msg.what: " + msg.what) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/TraceurMessageSender.kt b/packages/SystemUI/src/com/android/systemui/recordissue/TraceurMessageSender.kt deleted file mode 100644 index 8bfd14a68811..000000000000 --- a/packages/SystemUI/src/com/android/systemui/recordissue/TraceurMessageSender.kt +++ /dev/null @@ -1,189 +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.systemui.recordissue - -import android.annotation.SuppressLint -import android.content.ComponentName -import android.content.Context -import android.content.Intent -import android.content.ServiceConnection -import android.content.pm.PackageManager -import android.net.Uri -import android.os.Bundle -import android.os.Handler -import android.os.IBinder -import android.os.Looper -import android.os.Message -import android.os.Messenger -import android.util.Log -import androidx.annotation.WorkerThread -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Background -import com.android.systemui.recordissue.IssueRecordingState.Companion.TAG_TITLE_DELIMITER -import com.android.traceur.FileSender -import com.android.traceur.MessageConstants -import com.android.traceur.TraceConfig -import javax.inject.Inject - -private const val TAG = "TraceurMessageSender" - -@SysUISingleton -class TraceurMessageSender @Inject constructor(@Background private val backgroundLooper: Looper) { - private var binder: Messenger? = null - private var isBound: Boolean = false - - val onBoundToTraceur = mutableListOf<Runnable>() - - private val traceurConnection = - object : ServiceConnection { - override fun onServiceConnected(className: ComponentName, service: IBinder) { - binder = Messenger(service) - isBound = true - onBoundToTraceur.forEach(Runnable::run) - onBoundToTraceur.clear() - } - - override fun onServiceDisconnected(className: ComponentName) { - binder = null - isBound = false - } - } - - @SuppressLint("WrongConstant") - @WorkerThread - fun bindToTraceur(context: Context) { - if (isBound) { - // Binding needs to happen after the phone has been unlocked. The RecordIssueTile is - // initialized before this happens though, so binding is placed at a later time, during - // normal operations that can be repeated. This check avoids calling "bindService" 2x+ - return - } - try { - val info = - context.packageManager.getPackageInfo( - MessageConstants.TRACING_APP_PACKAGE_NAME, - PackageManager.MATCH_SYSTEM_ONLY - ) - val intent = - Intent().setClassName(info.packageName, MessageConstants.TRACING_APP_ACTIVITY) - val flags = - Context.BIND_AUTO_CREATE or - Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE or - Context.BIND_WAIVE_PRIORITY - context.bindService(intent, traceurConnection, flags) - } catch (e: Exception) { - Log.e(TAG, "failed to bind to Traceur's service", e) - } - } - - @WorkerThread - fun unbindFromTraceur(context: Context) { - if (isBound) { - context.unbindService(traceurConnection) - } - } - - @WorkerThread - fun startTracing(traceType: TraceConfig) { - val data = - Bundle().apply { putParcelable(MessageConstants.INTENT_EXTRA_TRACE_TYPE, traceType) } - notifyTraceur(MessageConstants.START_WHAT, data) - } - - @WorkerThread fun stopTracing() = notifyTraceur(MessageConstants.STOP_WHAT) - - @WorkerThread - fun shareTraces(context: Context, screenRecord: Uri?) { - val replyHandler = Messenger(ShareFilesHandler(context, screenRecord, backgroundLooper)) - notifyTraceur(MessageConstants.SHARE_WHAT, replyTo = replyHandler) - } - - @WorkerThread - fun getTags(state: IssueRecordingState) { - val replyHandler = Messenger(TagsHandler(backgroundLooper, state)) - notifyTraceur(MessageConstants.TAGS_WHAT, replyTo = replyHandler) - } - - @WorkerThread - private fun notifyTraceur(what: Int, data: Bundle = Bundle(), replyTo: Messenger? = null) { - try { - binder!!.send( - Message.obtain().apply { - this.what = what - this.data = data - this.replyTo = replyTo - } - ) - } catch (e: Exception) { - Log.e(TAG, "failed to notify Traceur", e) - } - } - - private class ShareFilesHandler( - private val context: Context, - private val screenRecord: Uri?, - looper: Looper, - ) : Handler(looper) { - - override fun handleMessage(msg: Message) { - if (MessageConstants.SHARE_WHAT == msg.what) { - shareTraces( - msg.data.getParcelable(MessageConstants.EXTRA_PERFETTO, Uri::class.java), - msg.data.getParcelable(MessageConstants.EXTRA_WINSCOPE, Uri::class.java) - ) - } else { - throw IllegalArgumentException("received unknown msg.what: " + msg.what) - } - } - - private fun shareTraces(perfetto: Uri?, winscope: Uri?) { - val uris: List<Uri> = - mutableListOf<Uri>().apply { - perfetto?.let { add(it) } - winscope?.let { add(it) } - screenRecord?.let { add(it) } - } - val fileSharingIntent = - FileSender.buildSendIntent(context, uris) - .addFlags( - Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT - ) - context.startActivity(fileSharingIntent) - } - } - - private class TagsHandler(looper: Looper, private val state: IssueRecordingState) : - Handler(looper) { - - override fun handleMessage(msg: Message) { - if (MessageConstants.TAGS_WHAT == msg.what) { - val keys = msg.data.getStringArrayList(MessageConstants.BUNDLE_KEY_TAGS) - val values = - msg.data.getStringArrayList(MessageConstants.BUNDLE_KEY_TAG_DESCRIPTIONS) - if (keys == null || values == null) { - throw IllegalArgumentException( - "Neither keys: $keys, nor values: $values can be null" - ) - } - state.tagTitles = - keys.zip(values).map { it.first + TAG_TITLE_DELIMITER + it.second }.toSet() - } else { - throw IllegalArgumentException("received unknown msg.what: " + msg.what) - } - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/UserAwareConnection.kt b/packages/SystemUI/src/com/android/systemui/recordissue/UserAwareConnection.kt new file mode 100644 index 000000000000..6aaa27dd7387 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recordissue/UserAwareConnection.kt @@ -0,0 +1,76 @@ +/* + * 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.recordissue + +import android.annotation.SuppressLint +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.os.IBinder +import android.os.Messenger +import android.util.Log +import androidx.annotation.VisibleForTesting +import androidx.annotation.WorkerThread +import com.android.systemui.settings.UserContextProvider + +private const val TAG = "UserAwareConnection" +private const val BIND_FLAGS = + Context.BIND_AUTO_CREATE or + Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE or + Context.BIND_WAIVE_PRIORITY + +/** ServiceConnection class that can be used to keep an IntentService alive. */ +open class UserAwareConnection( + protected val userContextProvider: UserContextProvider, + private val intent: Intent, +) : ServiceConnection { + @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) var binder: Messenger? = null + private var shouldUnBind = false + + override fun onServiceConnected(className: ComponentName, service: IBinder) { + binder = Messenger(service) + } + + override fun onServiceDisconnected(className: ComponentName) { + binder = null + } + + @SuppressLint("WrongConstant") + @WorkerThread + fun doBind() { + if (shouldUnBind) { + // Binding needs to happen after the phone has been unlocked. The RecordIssueTile is + // initialized before this happens though, so binding is placed at a later time, during + // normal operations that can be repeated. This check avoids calling "bindService" 2x+ + return + } + try { + shouldUnBind = userContextProvider.userContext.bindService(intent, this, BIND_FLAGS) + } catch (e: Exception) { + Log.e(TAG, "failed to bind to the service", e) + } + } + + @WorkerThread + fun doUnBind() { + if (shouldUnBind) { + userContextProvider.userContext.unbindService(this) + shouldUnBind = false + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt index a89f752fe212..4beec1041a03 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt @@ -44,6 +44,7 @@ import dagger.multibindings.IntoMap [ BouncerSceneModule::class, CommunalSceneModule::class, + DreamSceneModule::class, EmptySceneModule::class, GoneSceneModule::class, LockscreenSceneModule::class, @@ -98,6 +99,7 @@ interface SceneContainerFrameworkModule { listOfNotNull( Scenes.Gone, Scenes.Communal, + Scenes.Dream, Scenes.Lockscreen, Scenes.Bouncer, Scenes.QuickSettings.takeUnless { DualShade.isEnabled }, @@ -114,9 +116,10 @@ interface SceneContainerFrameworkModule { Scenes.Gone to 0, Scenes.Lockscreen to 0, Scenes.Communal to 1, - Scenes.Shade to 2.takeUnless { DualShade.isEnabled }, - Scenes.QuickSettings to 3.takeUnless { DualShade.isEnabled }, - Scenes.Bouncer to 4, + Scenes.Dream to 2, + Scenes.Shade to 3.takeUnless { DualShade.isEnabled }, + Scenes.QuickSettings to 4.takeUnless { DualShade.isEnabled }, + Scenes.Bouncer to 5, ) .filterValues { it != null } .mapValues { checkNotNull(it.value) }, diff --git a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepository.kt b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepository.kt deleted file mode 100644 index a8d077777121..000000000000 --- a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepository.kt +++ /dev/null @@ -1,56 +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.systemui.scene.data.repository - -import android.graphics.Region -import android.view.ISystemGestureExclusionListener -import android.view.IWindowManager -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow -import javax.inject.Inject -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.Flow - -@SysUISingleton -class SystemGestureExclusionRepository -@Inject -constructor(private val windowManager: IWindowManager) { - - /** - * Returns [Flow] of the [Region] in which system gestures should be excluded on the display - * identified with [displayId]. - */ - fun exclusionRegion(displayId: Int): Flow<Region?> { - return conflatedCallbackFlow { - val listener = - object : ISystemGestureExclusionListener.Stub() { - override fun onSystemGestureExclusionChanged( - displayId: Int, - restrictedRegion: Region?, - unrestrictedRegion: Region?, - ) { - trySend(restrictedRegion) - } - } - windowManager.registerSystemGestureExclusionListener(listener, displayId) - - awaitClose { - windowManager.unregisterSystemGestureExclusionListener(listener, displayId) - } - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractor.kt deleted file mode 100644 index 4cee874f5f8e..000000000000 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractor.kt +++ /dev/null @@ -1,35 +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.systemui.scene.domain.interactor - -import android.graphics.Region -import com.android.systemui.scene.data.repository.SystemGestureExclusionRepository -import javax.inject.Inject -import kotlinx.coroutines.flow.Flow - -class SystemGestureExclusionInteractor -@Inject -constructor(private val repository: SystemGestureExclusionRepository) { - - /** - * Returns [Flow] of the [Region] in which system gestures should be excluded on the display - * identified with [displayId]. - */ - fun exclusionRegion(displayId: Int): Flow<Region?> { - return repository.exclusionRegion(displayId) - } -} diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt index 82b4b1c57f7e..16492efa658a 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt @@ -33,6 +33,9 @@ object Scenes { /** The communal scene shows the glanceable hub when device is locked and docked. */ @JvmField val Communal = SceneKey("communal") + /** The dream scene shows up when a dream activity is showing. */ + @JvmField val Dream = SceneKey("dream") + /** * "Gone" is not a real scene but rather the absence of scenes when we want to skip showing any * content from the scene framework. diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt index a8be5804d04a..38f4e73d3234 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt @@ -107,13 +107,7 @@ object SceneWindowRootViewBinder { view.viewModel( traceName = "SceneWindowRootViewBinder", minWindowLifecycleState = WindowLifecycleState.ATTACHED, - factory = { - viewModelFactory.create( - view, - view.context.displayId, - motionEventHandlerReceiver, - ) - }, + factory = { viewModelFactory.create(view, motionEventHandlerReceiver) }, ) { viewModel -> try { view.setViewTreeOnBackPressedDispatcherOwner( diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt index ea19020d84d4..f0f476e65e2f 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt @@ -25,6 +25,7 @@ import android.view.View import android.view.WindowInsets import android.widget.FrameLayout import androidx.core.view.updateMargins +import com.android.systemui.Flags import com.android.systemui.compose.ComposeInitializer import com.android.systemui.res.R @@ -103,6 +104,8 @@ open class WindowRootView( private fun applyMargins() { val count = childCount + val hasFlagsEnabled = Flags.checkLockscreenGoneTransition() + var hasChildMarginUpdated = false for (i in 0 until count) { val child = getChildAt(i) if (child.layoutParams is LayoutParams) { @@ -113,10 +116,17 @@ open class WindowRootView( layoutParams.leftMargin != leftInset) ) { layoutParams.updateMargins(left = leftInset, right = rightInset) - child.requestLayout() + hasChildMarginUpdated = true + if (!hasFlagsEnabled) { + child.requestLayout() + } } } } + if (hasFlagsEnabled && hasChildMarginUpdated) { + // Request layout at once after all children's margins has updated + requestLayout() + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilter.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilter.kt deleted file mode 100644 index a1d915a658ec..000000000000 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerGestureFilter.kt +++ /dev/null @@ -1,65 +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.systemui.scene.ui.viewmodel - -import androidx.compose.runtime.getValue -import androidx.compose.ui.geometry.Offset -import com.android.systemui.lifecycle.ExclusiveActivatable -import com.android.systemui.lifecycle.Hydrator -import com.android.systemui.scene.domain.interactor.SystemGestureExclusionInteractor -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject -import kotlin.math.roundToInt - -/** Decides whether drag gestures should be filtered out in the scene container framework. */ -class SceneContainerGestureFilter -@AssistedInject -constructor(interactor: SystemGestureExclusionInteractor, @Assisted displayId: Int) : - ExclusiveActivatable() { - - private val hydrator = Hydrator("SceneContainerGestureFilter.hydrator") - private val exclusionRegion by - hydrator.hydratedStateOf( - traceName = "exclusionRegion", - initialValue = null, - source = interactor.exclusionRegion(displayId), - ) - - override suspend fun onActivated(): Nothing { - hydrator.activate() - } - - /** - * Returns `true` if a drag gesture starting at [startPosition] should be filtered out (e.g. - * ignored, `false` otherwise. - * - * Invoke this and pass in the position of the `ACTION_DOWN` pointer event that began the - * gesture. - */ - fun shouldFilterGesture(startPosition: Offset): Boolean { - check(isActive) { "Must be activated to use!" } - - return exclusionRegion?.contains(startPosition.x.roundToInt(), startPosition.y.roundToInt()) - ?: false - } - - @AssistedFactory - interface Factory { - fun create(displayId: Int): SceneContainerGestureFilter - } -} diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt index f5053853846c..889380a4ddbf 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt @@ -19,7 +19,6 @@ package com.android.systemui.scene.ui.viewmodel import android.view.MotionEvent import android.view.View import androidx.compose.runtime.getValue -import androidx.compose.ui.geometry.Offset import com.android.app.tracing.coroutines.launch import com.android.compose.animation.scene.ContentKey import com.android.compose.animation.scene.DefaultEdgeDetector @@ -61,10 +60,8 @@ constructor( shadeInteractor: ShadeInteractor, private val splitEdgeDetector: SplitEdgeDetector, private val logger: SceneLogger, - gestureFilterFactory: SceneContainerGestureFilter.Factory, hapticsViewModelFactory: SceneContainerHapticsViewModel.Factory, @Assisted view: View, - @Assisted displayId: Int, @Assisted private val motionEventHandlerReceiver: (MotionEventHandler?) -> Unit, ) : ExclusiveActivatable() { @@ -92,8 +89,6 @@ constructor( }, ) - private val gestureFilter: SceneContainerGestureFilter = gestureFilterFactory.create(displayId) - override suspend fun onActivated(): Nothing { try { // Sends a MotionEventHandler to the owner of the view-model so they can report @@ -112,7 +107,6 @@ constructor( coroutineScope { launch { hydrator.activate() } - launch { gestureFilter.activate() } launch("SceneContainerHapticsViewModel") { hapticsViewModel.activate() } } awaitCancellation() @@ -262,17 +256,6 @@ constructor( } } - /** - * Returns `true` if a drag gesture starting at [startPosition] should be filtered out (e.g. - * ignored, `false` otherwise. - * - * Invoke this and pass in the position of the `ACTION_DOWN` pointer event that began the - * gesture. - */ - fun shouldFilterGesture(startPosition: Offset): Boolean { - return gestureFilter.shouldFilterGesture(startPosition) - } - /** Defines interface for classes that can handle externally-reported [MotionEvent]s. */ interface MotionEventHandler { /** Notifies that a [MotionEvent] has occurred. */ @@ -289,7 +272,6 @@ constructor( interface Factory { fun create( view: View, - displayId: Int, motionEventHandlerReceiver: (MotionEventHandler?) -> Unit, ): SceneContainerViewModel } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/HeadlessScreenshotHandler.kt b/packages/SystemUI/src/com/android/systemui/screenshot/HeadlessScreenshotHandler.kt index 6730d2d86d5f..7b566885c092 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/HeadlessScreenshotHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/HeadlessScreenshotHandler.kt @@ -49,7 +49,7 @@ constructor( override fun handleScreenshot( screenshot: ScreenshotData, finisher: Consumer<Uri?>, - requestCallback: TakeScreenshotService.RequestCallback + requestCallback: TakeScreenshotService.RequestCallback, ) { if (screenshot.type == WindowManager.TAKE_SCREENSHOT_FULLSCREEN) { screenshot.bitmap = imageCapture.captureDisplay(screenshot.displayId, crop = null) @@ -69,8 +69,8 @@ constructor( Executors.newSingleThreadExecutor(), UUID.randomUUID(), screenshot.bitmap, - screenshot.getUserOrDefault(), - screenshot.displayId + screenshot.userHandle, + screenshot.displayId, ) future.addListener( { @@ -86,7 +86,7 @@ constructor( requestCallback.reportError() } }, - mainExecutor + mainExecutor, ) } @@ -98,11 +98,11 @@ constructor( .notifyScreenshotError(R.string.screenshot_failed_to_save_text) } else { uiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED, 0, screenshot.packageNameString) - if (userManager.isManagedProfile(screenshot.getUserOrDefault().identifier)) { + if (userManager.isManagedProfile(screenshot.userHandle.identifier)) { uiEventLogger.log( ScreenshotEvent.SCREENSHOT_SAVED_TO_WORK_PROFILE, 0, - screenshot.packageNameString + screenshot.packageNameString, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java index 7724abd4aaac..e58960072454 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotController.java @@ -301,7 +301,7 @@ public class LegacyScreenshotController implements InteractiveScreenshotHandler saveScreenshotInBackground(screenshot, requestId, finisher, result -> { if (result.uri != null) { ScreenshotSavedResult savedScreenshot = new ScreenshotSavedResult( - result.uri, screenshot.getUserOrDefault(), result.timestamp); + result.uri, screenshot.getUserHandle(), result.timestamp); mActionsController.setCompletedScreenshot(requestId, savedScreenshot); } }); diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.kt index 29208f89c4e1..a762d84700b6 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.kt @@ -97,12 +97,13 @@ internal constructor( private val window: ScreenshotWindow private val actionExecutor: ActionExecutor private val copyBroadcastReceiver: BroadcastReceiver + private val currentRequestCallbacks: MutableList<TakeScreenshotService.RequestCallback> = + mutableListOf() private var screenshotSoundController: ScreenshotSoundController? = null private var screenBitmap: Bitmap? = null private var screenshotTakenInPortrait = false private var screenshotAnimation: Animator? = null - private var currentRequestCallback: TakeScreenshotService.RequestCallback? = null private var packageName = "" /** Tracks config changes that require re-creating UI */ @@ -169,8 +170,8 @@ internal constructor( requestCallback: TakeScreenshotService.RequestCallback, ) { Assert.isMainThread() + screenshotHandler.resetTimeout() - currentRequestCallback = requestCallback if (screenshot.type == TAKE_SCREENSHOT_FULLSCREEN && screenshot.bitmap == null) { val bounds = fullScreenRect screenshot.bitmap = imageCapture.captureDisplay(display.displayId, bounds) @@ -181,7 +182,7 @@ internal constructor( if (currentBitmap == null) { Log.e(TAG, "handleScreenshot: Screenshot bitmap was null") notificationController.notifyScreenshotError(R.string.screenshot_failed_to_capture_text) - currentRequestCallback?.reportError() + requestCallback.reportError() return } @@ -194,8 +195,10 @@ internal constructor( // User setup isn't complete, so we don't want to show any UI beyond a toast, as editing // and sharing shouldn't be exposed to the user. saveScreenshotAndToast(screenshot, finisher) + requestCallback.onFinish() return } + currentRequestCallbacks.add(requestCallback) broadcastSender.sendBroadcast( Intent(ClipboardOverlayController.SCREENSHOT_ACTION), @@ -214,11 +217,7 @@ internal constructor( saveScreenshotInBackground(screenshot, requestId, finisher) { result -> if (result.uri != null) { val savedScreenshot = - ScreenshotSavedResult( - result.uri, - screenshot.getUserOrDefault(), - result.timestamp, - ) + ScreenshotSavedResult(result.uri, screenshot.userHandle, result.timestamp) actionsController.setCompletedScreenshot(requestId, savedScreenshot) } } @@ -235,7 +234,7 @@ internal constructor( window.setFocusable(true) viewProxy.requestFocus() - enqueueScrollCaptureRequest(requestId, screenshot.userHandle!!) + enqueueScrollCaptureRequest(requestId, screenshot.userHandle) window.attachWindow() @@ -267,7 +266,7 @@ internal constructor( private fun prepareViewForNewScreenshot(screenshot: ScreenshotData, oldPackageName: String?) { window.whenWindowAttached { - announcementResolver.getScreenshotAnnouncement(screenshot.userHandle!!.identifier) { + announcementResolver.getScreenshotAnnouncement(screenshot.userHandle.identifier) { viewProxy.announceForAccessibility(it) } } @@ -499,8 +498,8 @@ internal constructor( Log.d(TAG, "finishDismiss") actionsController.endScreenshotSession() scrollCaptureExecutor.close() - currentRequestCallback?.onFinish() - currentRequestCallback = null + currentRequestCallbacks.forEach { it.onFinish() } + currentRequestCallbacks.clear() viewProxy.reset() removeWindow() screenshotHandler.cancelTimeout() @@ -517,7 +516,7 @@ internal constructor( bgExecutor, requestId, screenshot.bitmap, - screenshot.getUserOrDefault(), + screenshot.userHandle, display.displayId, ) future.addListener( @@ -525,7 +524,7 @@ internal constructor( try { val result = future.get() Log.d(TAG, "Saved screenshot: $result") - logScreenshotResultStatus(result.uri, screenshot.userHandle!!) + logScreenshotResultStatus(result.uri, screenshot.userHandle) onResult.accept(result) if (LogConfig.DEBUG_CALLBACK) { Log.d(TAG, "finished bg processing, calling back with uri: ${result.uri}") diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt index b5d45a488997..2df1e8aa2e68 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt @@ -15,17 +15,17 @@ import com.android.internal.util.ScreenshotRequest /** [ScreenshotData] represents the current state of a single screenshot being acquired. */ data class ScreenshotData( - @ScreenshotType var type: Int, - @ScreenshotSource var source: Int, + @ScreenshotType val type: Int, + @ScreenshotSource val source: Int, /** UserHandle for the owner of the app being screenshotted, if known. */ - var userHandle: UserHandle?, + val userHandle: UserHandle, /** ComponentName of the top-most app in the screenshot. */ - var topComponent: ComponentName?, + val topComponent: ComponentName?, var screenBounds: Rect?, - var taskId: Int, + val taskId: Int, var insets: Insets, var bitmap: Bitmap?, - var displayId: Int, + val displayId: Int, ) { val packageNameString get() = topComponent?.packageName ?: "" @@ -40,7 +40,7 @@ data class ScreenshotData( ScreenshotData( type = request.type, source = request.source, - userHandle = if (request.userId >= 0) UserHandle.of(request.userId) else null, + userHandle = UserHandle.of(request.userId), topComponent = request.topComponent, screenBounds = request.boundsInScreen, taskId = request.taskId, @@ -50,16 +50,21 @@ data class ScreenshotData( ) @VisibleForTesting - fun forTesting() = + fun forTesting( + userHandle: UserHandle = UserHandle.CURRENT, + source: Int = ScreenshotSource.SCREENSHOT_KEY_CHORD, + topComponent: ComponentName? = null, + bitmap: Bitmap? = null, + ) = ScreenshotData( type = WindowManager.TAKE_SCREENSHOT_FULLSCREEN, - source = ScreenshotSource.SCREENSHOT_KEY_CHORD, - userHandle = null, - topComponent = null, + source = source, + userHandle = userHandle, + topComponent = topComponent, screenBounds = null, taskId = 0, insets = Insets.NONE, - bitmap = null, + bitmap = bitmap, displayId = Display.DEFAULT_DISPLAY, ) } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt index ab8a9539b7f2..a7557463b12f 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt @@ -28,6 +28,7 @@ import com.android.systemui.Flags.screenshotMultidisplayFocusChange import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.display.data.repository.DisplayRepository +import com.android.systemui.display.data.repository.FocusedDisplayRepository import com.android.systemui.res.R import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_CAPTURE_FAILED import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_DISMISSED_OTHER @@ -83,6 +84,7 @@ constructor( private val uiEventLogger: UiEventLogger, private val screenshotNotificationControllerFactory: ScreenshotNotificationsController.Factory, private val headlessScreenshotHandler: HeadlessScreenshotHandler, + private val focusedDisplayRepository: FocusedDisplayRepository, ) : TakeScreenshotExecutor { private val displays = displayRepository.displays private var screenshotController: InteractiveScreenshotHandler? = null @@ -216,14 +218,13 @@ constructor( ?: error("Can't find default display") // All other invocations use the focused display - else -> focusedDisplay() + else -> + displayRepository.getDisplay(focusedDisplayRepository.focusedDisplayId.value) + ?: displayRepository.getDisplay(Display.DEFAULT_DISPLAY) + ?: error("Can't find default display") } } - // TODO(b/367394043): Determine the focused display here. - private suspend fun focusedDisplay() = - displayRepository.getDisplay(Display.DEFAULT_DISPLAY) ?: error("Can't find default display") - /** Propagates the close system dialog signal to the ScreenshotController. */ override fun onCloseSystemDialogsReceived() { if (screenshotController?.isPendingSharedTransition() == false) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/PolicyRequestProcessor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/PolicyRequestProcessor.kt index b3d5c9e9691c..b67ad8a2b947 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/PolicyRequestProcessor.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/PolicyRequestProcessor.kt @@ -92,7 +92,7 @@ class PolicyRequestProcessor( updates.component, updates.owner, type.taskId, - type.taskBounds + type.taskBounds, ) is FullScreen -> replaceWithScreenshot( @@ -122,7 +122,7 @@ class PolicyRequestProcessor( componentName = topMainRootTask?.topActivity ?: defaultComponent, taskId = topMainRootTask?.taskId, owner = defaultOwner, - displayId = original.displayId + displayId = original.displayId, ) } @@ -141,14 +141,14 @@ class PolicyRequestProcessor( userHandle = owner, taskId = taskId, topComponent = componentName, - screenBounds = taskBounds + screenBounds = taskBounds, ) } private suspend fun replaceWithScreenshot( original: ScreenshotData, componentName: ComponentName?, - owner: UserHandle?, + owner: UserHandle, displayId: Int, taskId: Int? = null, ): ScreenshotData { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt index a4906c12b487..91efa0a283a9 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt @@ -41,7 +41,7 @@ import kotlin.math.sign class ScreenshotAnimationController( private val view: ScreenshotShelfView, - private val viewModel: ScreenshotViewModel + private val viewModel: ScreenshotViewModel, ) { private var animator: Animator? = null private val screenshotPreview = view.requireViewById<ImageView>(R.id.screenshot_preview) @@ -56,7 +56,7 @@ class ScreenshotAnimationController( listOf<View>( view.requireViewById(R.id.screenshot_preview_border), view.requireViewById(R.id.screenshot_badge), - view.requireViewById(R.id.screenshot_dismiss_button) + view.requireViewById(R.id.screenshot_dismiss_button), ) private val fadeUI = listOf<View>( @@ -70,9 +70,11 @@ class ScreenshotAnimationController( fun getEntranceAnimation( bounds: Rect, showFlash: Boolean, - onRevealMilestone: () -> Unit + onRevealMilestone: () -> Unit, ): Animator { val entranceAnimation = AnimatorSet() + view.alpha = 1f + view.translationX = 0f val previewAnimator = getPreviewAnimator(bounds) @@ -142,7 +144,7 @@ class ScreenshotAnimationController( fun runLongScreenshotTransition( destRect: Rect, longScreenshot: ScrollCaptureController.LongScreenshot, - onTransitionEnd: Runnable + onTransitionEnd: Runnable, ): Animator { val animSet = AnimatorSet() @@ -165,7 +167,7 @@ class ScreenshotAnimationController( matrix.setScale(currentScale, currentScale) matrix.postTranslate( longScreenshot.left * currentScale, - longScreenshot.top * currentScale + longScreenshot.top * currentScale, ) scrollTransitionPreview.setImageMatrix(matrix) val destinationScale: Float = destRect.width() / scrollTransitionPreview.width.toFloat() @@ -315,7 +317,7 @@ class ScreenshotAnimationController( } private fun getAdjustedVelocity(requestedVelocity: Float?): Float { - return if (requestedVelocity == null) { + return if (requestedVelocity == null || abs(requestedVelocity) < .005f) { val isLTR = view.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_LTR // dismiss to the left in LTR locales, to the right in RTL if (isLTR) -MINIMUM_VELOCITY else MINIMUM_VELOCITY diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/SwipeGestureListener.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/SwipeGestureListener.kt index 61d448960f98..ecb45e1f9373 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/SwipeGestureListener.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/SwipeGestureListener.kt @@ -25,7 +25,7 @@ import kotlin.math.abs class SwipeGestureListener( private val view: View, private val onDismiss: (Float?) -> Unit, - private val onCancel: () -> Unit + private val onCancel: () -> Unit, ) { private val velocityTracker = VelocityTracker.obtain() private val displayMetrics = view.resources.displayMetrics @@ -54,9 +54,9 @@ class SwipeGestureListener( onDismiss.invoke(xVelocity) return true } else { - velocityTracker.clear() onCancel.invoke() } + velocityTracker.clear() } MotionEvent.ACTION_MOVE -> { velocityTracker.addMovement(ev) diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index 5896659e9898..2bff7c86059d 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -30,6 +30,7 @@ import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK; import static com.android.systemui.classifier.Classifier.GENERIC; import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; import static com.android.systemui.classifier.Classifier.UNLOCK; +import static com.android.systemui.keyguard.shared.model.KeyguardState.AOD; import static com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING; import static com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING_LOCKSCREEN_HOSTED; import static com.android.systemui.keyguard.shared.model.KeyguardState.GONE; @@ -1213,6 +1214,16 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump }, mMainDispatcher); } + if (MigrateClocksToBlueprint.isEnabled()) { + collectFlow(mView, mKeyguardTransitionInteractor.transition( + Edge.Companion.create(AOD, LOCKSCREEN)), + (TransitionStep step) -> { + if (step.getTransitionState() == TransitionState.FINISHED) { + updateExpandedHeightToMaxHeight(); + } + }, mMainDispatcher); + } + // Ensures that flags are updated when an activity launches collectFlow(mView, mShadeAnimationInteractor.isLaunchingActivity(), diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt index 65b6231705d4..e5f684635ac7 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActions.kt @@ -30,41 +30,47 @@ import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge fun singleShadeActions( requireTwoPointersForTopEdgeForQs: Boolean = false ): Array<Pair<UserAction, UserActionResult>> { + val shadeUserActionResult = UserActionResult(Scenes.Shade, isIrreversible = true) + val qsSceneUserActionResult = UserActionResult(Scenes.QuickSettings, isIrreversible = true) return arrayOf( // Swiping down, not from the edge, always goes to shade. - Swipe.Down to Scenes.Shade, - swipeDown(pointerCount = 2) to Scenes.Shade, + Swipe.Down to shadeUserActionResult, + swipeDown(pointerCount = 2) to shadeUserActionResult, // Swiping down from the top edge. swipeDownFromTop(pointerCount = 1) to if (requireTwoPointersForTopEdgeForQs) { - Scenes.Shade + shadeUserActionResult } else { - Scenes.QuickSettings + qsSceneUserActionResult }, - swipeDownFromTop(pointerCount = 2) to Scenes.QuickSettings, + swipeDownFromTop(pointerCount = 2) to qsSceneUserActionResult, ) } /** Returns collection of [UserAction] to [UserActionResult] pairs for opening the split shade. */ fun splitShadeActions(): Array<Pair<UserAction, UserActionResult>> { - val splitShadeSceneKey = UserActionResult(Scenes.Shade, ToSplitShade) + val shadeUserActionResult = UserActionResult(Scenes.Shade, ToSplitShade, isIrreversible = true) return arrayOf( // Swiping down, not from the edge, always goes to shade. - Swipe.Down to splitShadeSceneKey, - swipeDown(pointerCount = 2) to splitShadeSceneKey, + Swipe.Down to shadeUserActionResult, + swipeDown(pointerCount = 2) to shadeUserActionResult, // Swiping down from the top edge goes to QS. - swipeDownFromTop(pointerCount = 1) to splitShadeSceneKey, - swipeDownFromTop(pointerCount = 2) to splitShadeSceneKey, + swipeDownFromTop(pointerCount = 1) to shadeUserActionResult, + swipeDownFromTop(pointerCount = 2) to shadeUserActionResult, ) } /** Returns collection of [UserAction] to [UserActionResult] pairs for opening the dual shade. */ fun dualShadeActions(): Array<Pair<UserAction, UserActionResult>> { + val notifShadeUserActionResult = + UserActionResult.ShowOverlay(Overlays.NotificationsShade, isIrreversible = true) + val qsShadeuserActionResult = + UserActionResult.ShowOverlay(Overlays.QuickSettingsShade, isIrreversible = true) return arrayOf( - Swipe.Down to Overlays.NotificationsShade, + Swipe.Down to notifShadeUserActionResult, Swipe(direction = SwipeDirection.Down, fromSource = SceneContainerEdge.TopRight) to - Overlays.QuickSettingsShade, + qsShadeuserActionResult, ) } diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt index cc6e8c246ff7..3113dc462e6a 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt @@ -32,6 +32,7 @@ import com.android.systemui.shade.shared.model.ShadeMode import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.filter /** * Models the UI state for the user actions that the user can perform to navigate to other scenes. @@ -50,7 +51,9 @@ constructor( combine( shadeInteractor.shadeMode, qsSceneAdapter.isCustomizerShowing, - sceneBackInteractor.backScene.map { it ?: SceneFamilies.Home }, + sceneBackInteractor.backScene + .filter { it != Scenes.Shade } + .map { it ?: SceneFamilies.Home }, ) { shadeMode, isCustomizerShowing, backScene -> buildMap<UserAction, UserActionResult> { if (!isCustomizerShowing) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java index e47952fd6c4a..a79b78f8d5f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -58,6 +58,7 @@ import androidx.annotation.WorkerThread; import com.android.internal.statusbar.NotificationVisibility; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.Dumpable; +import com.android.systemui.Flags; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; @@ -813,11 +814,17 @@ public class NotificationLockscreenUserManagerImpl implements private void notifyNotificationStateChanged() { if (!Looper.getMainLooper().isCurrentThread()) { - mMainExecutor.execute(() -> { + if (Flags.checkLockscreenGoneTransition()) { for (NotificationStateChangedListener listener : mNotifStateChangedListeners) { - listener.onNotificationStateChanged(); + mMainExecutor.execute(listener::onNotificationStateChanged); } - }); + } else { + mMainExecutor.execute(() -> { + for (NotificationStateChangedListener listener : mNotifStateChangedListeners) { + listener.onNotificationStateChanged(); + } + }); + } } else { for (NotificationStateChangedListener listener : mNotifStateChangedListeners) { listener.onNotificationStateChanged(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java index e3c47a43aad4..321593b6ada4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java @@ -596,7 +596,8 @@ public class NetworkControllerImpl extends BroadcastReceiver // NetworkCapabilities, but we need to convert it into TRANSPORT_WIFI in order to // distinguish it from VCN over Cellular. if (transportTypes[i] == NetworkCapabilities.TRANSPORT_CELLULAR - && Utils.tryGetWifiInfoForVcn(networkCapabilities) != null) { + && Utils.tryGetWifiInfoForVcn(mConnectivityManager, networkCapabilities) + != null) { transportTypes[i] = NetworkCapabilities.TRANSPORT_WIFI; break; } @@ -1112,7 +1113,9 @@ public class NetworkControllerImpl extends BroadcastReceiver continue; } if (transportType == NetworkCapabilities.TRANSPORT_CELLULAR - && Utils.tryGetWifiInfoForVcn(mLastDefaultNetworkCapabilities) != null) { + && Utils.tryGetWifiInfoForVcn( + mConnectivityManager, mLastDefaultNetworkCapabilities) + != null) { mConnectedTransports.set(NetworkCapabilities.TRANSPORT_WIFI); if (mLastDefaultNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) { mValidatedTransports.set(NetworkCapabilities.TRANSPORT_WIFI); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS index 5558ab1e2af2..0a7f08d5860b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS @@ -2,11 +2,13 @@ set noparent # Bug component: 78010 +jeffdq@google.com +juliacr@google.com + aioana@google.com aroederer@google.com +asc@google.com iyz@google.com -jeffdq@google.com -juliacr@google.com juliatuttle@google.com kurucz@google.com liuyining@google.com @@ -15,4 +17,4 @@ matiashe@google.com valiiftime@google.com yurilin@google.com -per-file MediaNotificationProcessor.java = ethibodeau@google.com, asc@google.com +per-file MediaNotificationProcessor.java = ethibodeau@google.com diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index cb133ecadab2..e74ed8d27ec2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -68,11 +68,9 @@ import com.android.systemui.statusbar.notification.icon.IconPack; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController; import com.android.systemui.statusbar.notification.row.NotificationGuts; -import com.android.systemui.statusbar.notification.row.data.repository.NotificationRowRepository; import com.android.systemui.statusbar.notification.row.shared.HeadsUpStatusBarModel; import com.android.systemui.statusbar.notification.row.shared.NotificationContentModel; import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor; -import com.android.systemui.statusbar.notification.row.shared.RichOngoingContentModel; import com.android.systemui.statusbar.notification.stack.PriorityBucket; import com.android.systemui.util.ListenerSet; @@ -99,7 +97,7 @@ import java.util.Objects; * At the moment, there are many things here that shouldn't be and vice-versa. Hopefully we can * clean this up in the future. */ -public final class NotificationEntry extends ListEntry implements NotificationRowRepository { +public final class NotificationEntry extends ListEntry { private final String mKey; private StatusBarNotification mSbn; @@ -161,8 +159,6 @@ public final class NotificationEntry extends ListEntry implements NotificationRo StateFlowKt.MutableStateFlow(null); private final MutableStateFlow<CharSequence> mHeadsUpStatusBarTextPublic = StateFlowKt.MutableStateFlow(null); - private final MutableStateFlow<RichOngoingContentModel> mRichOngoingContentModel = - StateFlowKt.MutableStateFlow(null); // indicates when this entry's view was first attached to a window // this value will reset when the view is completely removed from the shade (ie: filtered out) @@ -969,12 +965,6 @@ public final class NotificationEntry extends ListEntry implements NotificationRo return mHeadsUpStatusBarTextPublic; } - /** Gets the current RON content model, which may be null */ - @NonNull - public StateFlow<RichOngoingContentModel> getRichOngoingContentModel() { - return mRichOngoingContentModel; - } - /** * Sets the text to be displayed on the StatusBar, when this notification is the top pinned * heads up, and its content is sensitive right now. @@ -1069,7 +1059,6 @@ public final class NotificationEntry extends ListEntry implements NotificationRo HeadsUpStatusBarModel headsUpStatusBarModel = contentModel.getHeadsUpStatusBarModel(); this.mHeadsUpStatusBarText.setValue(headsUpStatusBarModel.getPrivateText()); this.mHeadsUpStatusBarTextPublic.setValue(headsUpStatusBarModel.getPublicText()); - this.mRichOngoingContentModel.setValue(contentModel.getRichOngoingContentModel()); } /** Information about a suggestion that is being edited. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java index 41419f31eb7a..8660cd117493 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java @@ -22,15 +22,18 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.android.systemui.Dumpable; +import com.android.systemui.Flags; import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; +import com.android.systemui.keyguard.shared.model.Edge; import com.android.systemui.keyguard.shared.model.KeyguardState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.scene.shared.flag.SceneContainerFlag; +import com.android.systemui.scene.shared.model.Scenes; import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor; import com.android.systemui.shade.domain.interactor.ShadeInteractor; import com.android.systemui.statusbar.notification.VisibilityLocationProvider; @@ -85,6 +88,7 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable { private boolean mNotifPanelLaunchingActivity; private boolean mCommunalShowing = false; private boolean mLockscreenShowing = false; + private boolean mLockscreenInGoneTransition = false; private boolean mPipelineRunAllowed; private boolean mReorderingAllowed; @@ -158,6 +162,13 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable { KeyguardState.LOCKSCREEN), this::onLockscreenKeyguardStateTransitionValueChanged); } + if (Flags.checkLockscreenGoneTransition()) { + mJavaAdapter.alwaysCollectFlow(mKeyguardTransitionInteractor.isInTransition( + Edge.create(KeyguardState.LOCKSCREEN, Scenes.Gone), + Edge.create(KeyguardState.LOCKSCREEN, KeyguardState.GONE)), + this::onLockscreenInGoneTransitionChanged); + } + pipeline.setVisualStabilityManager(mNotifStabilityManager); } @@ -239,7 +250,9 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable { private void updateAllowedStates(String field, boolean value) { boolean wasPipelineRunAllowed = mPipelineRunAllowed; boolean wasReorderingAllowed = mReorderingAllowed; - mPipelineRunAllowed = !isPanelCollapsingOrLaunchingActivity(); + // No need to run notification pipeline when the lockscreen is in fading animation. + mPipelineRunAllowed = !(isPanelCollapsingOrLaunchingActivity() + || (Flags.checkLockscreenGoneTransition() && mLockscreenInGoneTransition)); mReorderingAllowed = isReorderingAllowed(); if (wasPipelineRunAllowed != mPipelineRunAllowed || wasReorderingAllowed != mReorderingAllowed) { @@ -330,7 +343,6 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable { updateAllowedStates("fullyDozed", fullyDozed); } }; - final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { @Override public void onFinishedGoingToSleep() { @@ -353,6 +365,9 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable { pw.println("pipelineRunAllowed: " + mPipelineRunAllowed); pw.println(" notifPanelCollapsing: " + mNotifPanelCollapsing); pw.println(" launchingNotifActivity: " + mNotifPanelLaunchingActivity); + if (Flags.checkLockscreenGoneTransition()) { + pw.println(" lockscreenInGoneTransition: " + mLockscreenInGoneTransition); + } pw.println("reorderingAllowed: " + mReorderingAllowed); pw.println(" sleepy: " + mSleepy); pw.println(" fullyDozed: " + mFullyDozed); @@ -401,4 +416,15 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable { mLockscreenShowing = isShowing; updateAllowedStates("lockscreenShowing", isShowing); } + + private void onLockscreenInGoneTransitionChanged(boolean inGoneTransition) { + if (!Flags.checkLockscreenGoneTransition()) { + return; + } + if (inGoneTransition == mLockscreenInGoneTransition) { + return; + } + mLockscreenInGoneTransition = inGoneTransition; + updateAllowedStates("lockscreenInGoneTransition", mLockscreenInGoneTransition); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt index aa203d7c0aa9..e25127e3e0d6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt @@ -39,10 +39,10 @@ class HeadsUpNotificationInteractor @Inject constructor( private val headsUpRepository: HeadsUpRepository, - private val faceAuthInteractor: DeviceEntryFaceAuthInteractor, - private val keyguardTransitionInteractor: KeyguardTransitionInteractor, - private val notificationsKeyguardInteractor: NotificationsKeyguardInteractor, - private val shadeInteractor: ShadeInteractor, + faceAuthInteractor: DeviceEntryFaceAuthInteractor, + keyguardTransitionInteractor: KeyguardTransitionInteractor, + notificationsKeyguardInteractor: NotificationsKeyguardInteractor, + shadeInteractor: ShadeInteractor, ) { /** The top-ranked heads up row, regardless of pinned state */ @@ -56,8 +56,7 @@ constructor( } .distinctUntilChanged() - /** Set of currently pinned top-level heads up rows to be displayed. */ - val pinnedHeadsUpRows: Flow<Set<HeadsUpRowKey>> by lazy { + private val activeHeadsUpRows: Flow<Set<Pair<HeadsUpRowKey, Boolean>>> by lazy { if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { flowOf(emptySet()) } else { @@ -67,9 +66,7 @@ constructor( repositories.map { repo -> repo.isPinned.map { isPinned -> repo to isPinned } } - combine(toCombine) { pairs -> - pairs.filter { (_, isPinned) -> isPinned }.map { (repo, _) -> repo }.toSet() - } + combine(toCombine) { pairs -> pairs.toSet() } } else { // if the set is empty, there are no flows to combine flowOf(emptySet()) @@ -78,6 +75,26 @@ constructor( } } + /** Set of currently active top-level heads up rows to be displayed. */ + val activeHeadsUpRowKeys: Flow<Set<HeadsUpRowKey>> by lazy { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { + flowOf(emptySet()) + } else { + activeHeadsUpRows.map { it.map { (repo, _) -> repo }.toSet() } + } + } + + /** Set of currently pinned top-level heads up rows to be displayed. */ + val pinnedHeadsUpRowKeys: Flow<Set<HeadsUpRowKey>> by lazy { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { + flowOf(emptySet()) + } else { + activeHeadsUpRows.map { + it.filter { (_, isPinned) -> isPinned }.map { (repo, _) -> repo }.toSet() + } + } + } + /** Are there any pinned heads up rows to display? */ val hasPinnedRows: Flow<Boolean> by lazy { if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt index 8c8f200f78b7..695e088b5f8b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt @@ -18,6 +18,8 @@ package com.android.systemui.statusbar.notification.emptyshade.ui.viewmodel import android.content.Context import android.icu.text.MessageFormat +import com.android.app.tracing.coroutines.flow.flowOn +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dump.DumpManager import com.android.systemui.modes.shared.ModesUi import com.android.systemui.res.R @@ -32,6 +34,7 @@ import com.android.systemui.util.kotlin.FlowDumperImpl import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import java.util.Locale +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -50,11 +53,16 @@ constructor( zenModeInteractor: ZenModeInteractor, seenNotificationsInteractor: SeenNotificationsInteractor, notificationSettingsInteractor: NotificationSettingsInteractor, + @Background bgDispatcher: CoroutineDispatcher, dumpManager: DumpManager, ) : FlowDumperImpl(dumpManager) { val areNotificationsHiddenInShade: Flow<Boolean> by lazy { if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) { flowOf(false) + } else if (ModesEmptyShadeFix.isEnabled) { + zenModeInteractor.areNotificationsHiddenInShade + .dumpWhileCollecting("areNotificationsHiddenInShade") + .flowOn(bgDispatcher) } else { zenModeInteractor.areNotificationsHiddenInShade.dumpWhileCollecting( "areNotificationsHiddenInShade" @@ -80,31 +88,33 @@ constructor( // recommended architecture, and making it so it reacts to changes for the new Modes. // The former does not depend on the modes flags being on, but the latter does. if (ModesUi.isEnabled) { - zenModeInteractor.modesHidingNotifications.map { modes -> - // Create a string that is either "No notifications" if no modes are filtering - // them out, or something like "Notifications paused by SomeMode" otherwise. - val msgFormat = - MessageFormat( - context.getString(R.string.modes_suppressing_shade_text), - Locale.getDefault(), - ) - val count = modes.count() - val args: MutableMap<String, Any> = HashMap() - args["count"] = count - if (count >= 1) { - args["mode"] = modes[0].name + zenModeInteractor.modesHidingNotifications.map { modes -> + // Create a string that is either "No notifications" if no modes are + // filtering + // them out, or something like "Notifications paused by SomeMode" otherwise. + val msgFormat = + MessageFormat( + context.getString(R.string.modes_suppressing_shade_text), + Locale.getDefault(), + ) + val count = modes.count() + val args: MutableMap<String, Any> = HashMap() + args["count"] = count + if (count >= 1) { + args["mode"] = modes[0].name + } + msgFormat.format(args) } - msgFormat.format(args) - } - } else { - areNotificationsHiddenInShade.map { areNotificationsHiddenInShade -> - if (areNotificationsHiddenInShade) { - context.getString(R.string.dnd_suppressing_shade_text) - } else { - context.getString(R.string.empty_shade_text) + } else { + areNotificationsHiddenInShade.map { areNotificationsHiddenInShade -> + if (areNotificationsHiddenInShade) { + context.getString(R.string.dnd_suppressing_shade_text) + } else { + context.getString(R.string.empty_shade_text) + } } } - } + .flowOn(bgDispatcher) } } @@ -120,23 +130,24 @@ constructor( val onClick: Flow<SettingsIntent> by lazy { ModesEmptyShadeFix.assertInNewMode() combine( - zenModeInteractor.modesHidingNotifications, - notificationSettingsInteractor.isNotificationHistoryEnabled, - ) { modes, isNotificationHistoryEnabled -> - if (modes.isNotEmpty()) { - if (modes.size == 1) { - SettingsIntent.forModeSettings(modes[0].id) - } else { - SettingsIntent.forModesSettings() - } - } else { - if (isNotificationHistoryEnabled) { - SettingsIntent.forNotificationHistory() + zenModeInteractor.modesHidingNotifications, + notificationSettingsInteractor.isNotificationHistoryEnabled, + ) { modes, isNotificationHistoryEnabled -> + if (modes.isNotEmpty()) { + if (modes.size == 1) { + SettingsIntent.forModeSettings(modes[0].id) + } else { + SettingsIntent.forModesSettings() + } } else { - SettingsIntent.forNotificationSettings() + if (isNotificationHistoryEnabled) { + SettingsIntent.forNotificationHistory() + } else { + SettingsIntent.forNotificationSettings() + } } } - } + .flowOn(bgDispatcher) } @AssistedFactory diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 5003a6af5c4c..2c6b09cb4cb6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -3218,7 +3218,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } @Override - protected void resetAllContentAlphas() { + public void resetAllContentAlphas() { mLogger.logResetAllContentAlphas(getEntry()); mPrivateLayout.setAlpha(1f); mPrivateLayout.setLayerType(LAYER_TYPE_NONE, null); @@ -3873,13 +3873,17 @@ public class ExpandableNotificationRow extends ActivatableNotificationView pw.print(", mShowingPublicInitialized: " + mShowingPublicInitialized); NotificationContentView showingLayout = getShowingLayout(); pw.print(", privateShowing: " + (showingLayout == mPrivateLayout)); + pw.print(", childrenContainerShowing: " + + (!shouldShowPublic() && mIsSummaryWithChildren)); pw.print(", mShowNoBackground: " + mShowNoBackground); + pw.print(", clipBounds: " + getClipBounds()); + pw.println(); if (NotificationContentView.INCLUDE_HEIGHTS_TO_DUMP) { dumpHeights(pw); } showingLayout.dump(pw, args); - + dumpCustomOutline(pw, args); if (getViewState() != null) { getViewState().dump(pw, args); pw.println(); @@ -3896,6 +3900,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView ? 0 : mChildrenContainer.getTransientViewCount(); if (mIsSummaryWithChildren || transientViewCount > 0) { pw.println(mChildrenContainer.debugString()); + pw.println("Children Container Intrinsic Height: " + + mChildrenContainer.getIntrinsicHeight()); pw.println(); List<ExpandableNotificationRow> notificationChildren = getAttachedChildren(); pw.print("Children: " + notificationChildren.size() + " {"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java index aefd34817fdc..a323c2604c63 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java @@ -365,11 +365,17 @@ public abstract class ExpandableOutlineView extends ExpandableView { DumpUtilsKt.withIncreasedIndent(pw, () -> { pw.println(getRoundableState().debugString()); if (DUMP_VERBOSE) { - pw.println("mCustomOutline: " + mCustomOutline + " mOutlineRect: " + mOutlineRect); - pw.println("mOutlineAlpha: " + mOutlineAlpha); - pw.println("mAlwaysRoundBothCorners: " + mAlwaysRoundBothCorners); + dumpCustomOutline(pw, args); } }); } + protected void dumpCustomOutline(IndentingPrintWriter pw, String[] args) { + pw.print("CustomOutline: "); + pw.print("mCustomOutline", mCustomOutline); + pw.print("mOutlineRect", mOutlineRect); + pw.print("mOutlineAlpha", mOutlineAlpha); + pw.print("mAlwaysRoundBothCorners", mAlwaysRoundBothCorners); + pw.println(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java index 8c80fd400360..36e3e92e4063 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java @@ -203,13 +203,16 @@ public class NotificationContentInflater implements NotificationRowContentBinder messagingStyle = mConversationProcessor .processNotification(entry, builder, mLogger); } - result.mInflatedSingleLineViewModel = SingleLineViewInflater + SingleLineViewModel viewModel = SingleLineViewInflater .inflateSingleLineViewModel( entry.getSbn().getNotification(), messagingStyle, builder, row.getContext() ); + // If the messagingStyle is null, we want to inflate the normal view + isConversation = viewModel.isConversation(); + result.mInflatedSingleLineViewModel = viewModel; result.mInflatedSingleLineView = SingleLineViewInflater.inflatePrivateSingleLineView( isConversation, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 48c974a33f12..9166e7e9bed2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -76,8 +76,6 @@ import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent; import com.android.systemui.util.Compile; import com.android.systemui.util.DumpUtilsKt; -import kotlinx.coroutines.DisposableHandle; - import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; @@ -116,10 +114,6 @@ public class NotificationContentView extends FrameLayout implements Notification @VisibleForTesting protected HybridNotificationView mSingleLineView; - @Nullable public DisposableHandle mContractedBinderHandle; - @Nullable public DisposableHandle mExpandedBinderHandle; - @Nullable public DisposableHandle mHeadsUpBinderHandle; - private RemoteInputView mExpandedRemoteInput; private RemoteInputView mHeadsUpRemoteInput; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt index c342bcd2706b..b166defb96a2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt @@ -46,9 +46,6 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager import com.android.systemui.statusbar.notification.ConversationNotificationProcessor import com.android.systemui.statusbar.notification.InflationException import com.android.systemui.statusbar.notification.collection.NotificationEntry -import com.android.systemui.statusbar.notification.row.ContentViewInflationResult.InflatedContentViewHolder -import com.android.systemui.statusbar.notification.row.ContentViewInflationResult.KeepExistingView -import com.android.systemui.statusbar.notification.row.ContentViewInflationResult.NullContentView import com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_CONTRACTED import com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_EXPANDED import com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP @@ -71,7 +68,6 @@ import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedac import com.android.systemui.statusbar.notification.row.shared.NewRemoteViews import com.android.systemui.statusbar.notification.row.shared.NotificationContentModel import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor -import com.android.systemui.statusbar.notification.row.shared.RichOngoingContentModel import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineViewBinder import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer @@ -95,8 +91,6 @@ constructor( private val remoteViewCache: NotifRemoteViewCache, private val remoteInputManager: NotificationRemoteInputManager, private val conversationProcessor: ConversationNotificationProcessor, - private val ronExtractor: RichOngoingNotificationContentExtractor, - private val ronInflater: RichOngoingNotificationViewInflater, @NotifInflation private val inflationExecutor: Executor, private val smartReplyStateInflater: SmartReplyStateInflater, private val notifLayoutInflaterFactoryProvider: NotifLayoutInflaterFactory.Provider, @@ -144,8 +138,6 @@ constructor( remoteViewCache, entry, conversationProcessor, - ronExtractor, - ronInflater, row, bindParams.isMinimized, bindParams.usesIncreasedHeight, @@ -190,7 +182,6 @@ constructor( notifLayoutInflaterFactoryProvider = notifLayoutInflaterFactoryProvider, headsUpStyleProvider = headsUpStyleProvider, conversationProcessor = conversationProcessor, - ronExtractor = ronExtractor, logger = logger, ) inflateSmartReplyViews( @@ -282,22 +273,16 @@ constructor( when (inflateFlag) { FLAG_CONTENT_VIEW_CONTRACTED -> row.privateLayout.performWhenContentInactive(VISIBLE_TYPE_CONTRACTED) { - row.privateLayout.mContractedBinderHandle?.dispose() - row.privateLayout.mContractedBinderHandle = null row.privateLayout.setContractedChild(null) remoteViewCache.removeCachedView(entry, FLAG_CONTENT_VIEW_CONTRACTED) } FLAG_CONTENT_VIEW_EXPANDED -> row.privateLayout.performWhenContentInactive(VISIBLE_TYPE_EXPANDED) { - row.privateLayout.mExpandedBinderHandle?.dispose() - row.privateLayout.mExpandedBinderHandle = null row.privateLayout.setExpandedChild(null) remoteViewCache.removeCachedView(entry, FLAG_CONTENT_VIEW_EXPANDED) } FLAG_CONTENT_VIEW_HEADS_UP -> row.privateLayout.performWhenContentInactive(VISIBLE_TYPE_HEADSUP) { - row.privateLayout.mHeadsUpBinderHandle?.dispose() - row.privateLayout.mHeadsUpBinderHandle = null row.privateLayout.setHeadsUpChild(null) remoteViewCache.removeCachedView(entry, FLAG_CONTENT_VIEW_HEADS_UP) row.privateLayout.setHeadsUpInflatedSmartReplies(null) @@ -378,8 +363,6 @@ constructor( private val remoteViewCache: NotifRemoteViewCache, private val entry: NotificationEntry, private val conversationProcessor: ConversationNotificationProcessor, - private val ronExtractor: RichOngoingNotificationContentExtractor, - private val ronInflater: RichOngoingNotificationViewInflater, private val row: ExpandableNotificationRow, private val isMinimized: Boolean, private val usesIncreasedHeight: Boolean, @@ -459,7 +442,6 @@ constructor( notifLayoutInflaterFactoryProvider = notifLayoutInflaterFactoryProvider, headsUpStyleProvider = headsUpStyleProvider, conversationProcessor = conversationProcessor, - ronExtractor = ronExtractor, logger = logger ) logger.logAsyncTaskProgress( @@ -506,90 +488,6 @@ constructor( } } - val richOngoingContentModel = inflationProgress.contentModel.richOngoingContentModel - - if ( - richOngoingContentModel != null && - reInflateFlags and CONTENT_VIEWS_TO_CREATE_RICH_ONGOING != 0 - ) { - logger.logAsyncTaskProgress(entry, "inflating RON view") - val inflateContractedView = reInflateFlags and FLAG_CONTENT_VIEW_CONTRACTED != 0 - val inflateExpandedView = reInflateFlags and FLAG_CONTENT_VIEW_EXPANDED != 0 - val inflateHeadsUpView = reInflateFlags and FLAG_CONTENT_VIEW_HEADS_UP != 0 - - inflationProgress.contractedRichOngoingNotificationViewHolder = - if (inflateContractedView) { - ronInflater.inflateView( - contentModel = richOngoingContentModel, - existingView = row.privateLayout.contractedChild, - entry = entry, - systemUiContext = context, - parentView = row.privateLayout, - viewType = RichOngoingNotificationViewType.Contracted - ) - } else { - if ( - ronInflater.canKeepView( - contentModel = richOngoingContentModel, - existingView = row.privateLayout.contractedChild, - viewType = RichOngoingNotificationViewType.Contracted - ) - ) { - KeepExistingView - } else { - NullContentView - } - } - - inflationProgress.expandedRichOngoingNotificationViewHolder = - if (inflateExpandedView) { - ronInflater.inflateView( - contentModel = richOngoingContentModel, - existingView = row.privateLayout.expandedChild, - entry = entry, - systemUiContext = context, - parentView = row.privateLayout, - viewType = RichOngoingNotificationViewType.Expanded - ) - } else { - if ( - ronInflater.canKeepView( - contentModel = richOngoingContentModel, - existingView = row.privateLayout.expandedChild, - viewType = RichOngoingNotificationViewType.Expanded - ) - ) { - KeepExistingView - } else { - NullContentView - } - } - - inflationProgress.headsUpRichOngoingNotificationViewHolder = - if (inflateHeadsUpView) { - ronInflater.inflateView( - contentModel = richOngoingContentModel, - existingView = row.privateLayout.headsUpChild, - entry = entry, - systemUiContext = context, - parentView = row.privateLayout, - viewType = RichOngoingNotificationViewType.HeadsUp - ) - } else { - if ( - ronInflater.canKeepView( - contentModel = richOngoingContentModel, - existingView = row.privateLayout.headsUpChild, - viewType = RichOngoingNotificationViewType.HeadsUp - ) - ) { - KeepExistingView - } else { - NullContentView - } - } - } - logger.logAsyncTaskProgress(entry, "getting row image resolver (on wrong thread!)") val imageResolver = row.imageResolver // wait for image resolver to finish preloading @@ -695,9 +593,6 @@ constructor( var inflatedSmartReplyState: InflatedSmartReplyState? = null var expandedInflatedSmartReplies: InflatedSmartReplyViewHolder? = null var headsUpInflatedSmartReplies: InflatedSmartReplyViewHolder? = null - var contractedRichOngoingNotificationViewHolder: ContentViewInflationResult? = null - var expandedRichOngoingNotificationViewHolder: ContentViewInflationResult? = null - var headsUpRichOngoingNotificationViewHolder: ContentViewInflationResult? = null // Inflated SingleLineView that lacks the UI State var inflatedSingleLineView: HybridNotificationView? = null @@ -734,7 +629,6 @@ constructor( val inflateHeadsUp = (reInflateFlags and FLAG_CONTENT_VIEW_HEADS_UP != 0 && result.remoteViews.headsUp != null) - if (inflateContracted || inflateExpanded || inflateHeadsUp) { logger.logAsyncTaskProgress(entry, "inflating contracted smart reply state") result.inflatedSmartReplyState = inflater.inflateSmartReplyState(entry) @@ -776,7 +670,6 @@ constructor( notifLayoutInflaterFactoryProvider: NotifLayoutInflaterFactory.Provider, headsUpStyleProvider: HeadsUpStyleProvider, conversationProcessor: ConversationNotificationProcessor, - ronExtractor: RichOngoingNotificationContentExtractor, logger: NotificationRowContentBinderLogger ): InflationProgress { // process conversations and extract the messaging style @@ -785,24 +678,9 @@ constructor( conversationProcessor.processNotification(entry, builder, logger) } else null - val richOngoingContentModel = - if (reInflateFlags and CONTENT_VIEWS_TO_CREATE_RICH_ONGOING != 0) { - ronExtractor.extractContentModel( - entry = entry, - builder = builder, - systemUIContext = systemUIContext, - packageContext = packageContext - ) - } else { - // if we're not re-inflating any RON views, make sure the model doesn't change - entry.richOngoingContentModel.value - } - - val remoteViewsFlags = getRemoteViewsFlags(reInflateFlags, richOngoingContentModel) - val remoteViews = createRemoteViews( - reInflateFlags = remoteViewsFlags, + reInflateFlags = reInflateFlags, builder = builder, isMinimized = isMinimized, usesIncreasedHeight = usesIncreasedHeight, @@ -850,7 +728,6 @@ constructor( headsUpStatusBarModel = headsUpStatusBarModel, singleLineViewModel = singleLineViewModel, publicSingleLineViewModel = publicSingleLineViewModel, - richOngoingContentModel = richOngoingContentModel, ) return InflationProgress( @@ -1506,31 +1383,11 @@ constructor( } logger.logAsyncTaskProgress(entry, "finishing") - // before updating the content model, stop existing binding if necessary - if (result.contractedRichOngoingNotificationViewHolder.shouldDisposeViewBinder()) { - row.privateLayout.mContractedBinderHandle?.dispose() - row.privateLayout.mContractedBinderHandle = null - } - - if (result.expandedRichOngoingNotificationViewHolder.shouldDisposeViewBinder()) { - row.privateLayout.mExpandedBinderHandle?.dispose() - row.privateLayout.mExpandedBinderHandle = null - } - - if (result.headsUpRichOngoingNotificationViewHolder.shouldDisposeViewBinder()) { - row.privateLayout.mHeadsUpBinderHandle?.dispose() - row.privateLayout.mHeadsUpBinderHandle = null - } - - // set the content model after disposal and before setting new rich ongoing view entry.setContentModel(result.contentModel) result.inflatedSmartReplyState?.let { row.privateLayout.setInflatedSmartReplyState(it) } - // set normal remote views (skipping rich ongoing states when that model exists) - val remoteViewsFlags = - getRemoteViewsFlags(reInflateFlags, result.contentModel.richOngoingContentModel) setContentViewsFromRemoteViews( - remoteViewsFlags, + reInflateFlags, entry, remoteViewCache, result, @@ -1538,7 +1395,6 @@ constructor( isMinimized, ) - // set single line view if ( AsyncHybridViewInflation.isEnabled && reInflateFlags and FLAG_CONTENT_VIEW_SINGLE_LINE != 0 @@ -1563,55 +1419,6 @@ constructor( } } - val hasRichOngoingViewHolder = - result.contractedRichOngoingNotificationViewHolder != null || - result.expandedRichOngoingNotificationViewHolder != null || - result.headsUpRichOngoingNotificationViewHolder != null - - if (hasRichOngoingViewHolder) { - // after updating the content model, set the view, then start the new binder - result.contractedRichOngoingNotificationViewHolder?.let { contractedViewHolder -> - if (contractedViewHolder is InflatedContentViewHolder) { - row.privateLayout.contractedChild = contractedViewHolder.view - row.privateLayout.mContractedBinderHandle = - contractedViewHolder.binder.setupContentViewBinder() - } else if (contractedViewHolder == NullContentView) { - row.privateLayout.contractedChild = null - } - } - - result.expandedRichOngoingNotificationViewHolder?.let { expandedViewHolder -> - if (expandedViewHolder is InflatedContentViewHolder) { - row.privateLayout.expandedChild = expandedViewHolder.view - row.privateLayout.mExpandedBinderHandle = - expandedViewHolder.binder.setupContentViewBinder() - } else if (expandedViewHolder == NullContentView) { - row.privateLayout.expandedChild = null - } - } - - result.headsUpRichOngoingNotificationViewHolder?.let { headsUpViewHolder -> - if (headsUpViewHolder is InflatedContentViewHolder) { - row.privateLayout.headsUpChild = headsUpViewHolder.view - row.privateLayout.mHeadsUpBinderHandle = - headsUpViewHolder.binder.setupContentViewBinder() - } else if (headsUpViewHolder == NullContentView) { - row.privateLayout.headsUpChild = null - } - } - - // clean remoteViewCache when we don't keep existing views. - remoteViewCache.removeCachedView(entry, FLAG_CONTENT_VIEW_CONTRACTED) - remoteViewCache.removeCachedView(entry, FLAG_CONTENT_VIEW_EXPANDED) - remoteViewCache.removeCachedView(entry, FLAG_CONTENT_VIEW_HEADS_UP) - - // Since RONs don't support smart reply, remove them from HUNs and Expanded. - row.privateLayout.setExpandedInflatedSmartReplies(null) - row.privateLayout.setHeadsUpInflatedSmartReplies(null) - - row.setExpandable(row.privateLayout.expandedChild != null) - } - Trace.endAsyncSection(APPLY_TRACE_METHOD, System.identityHashCode(row)) endListener?.onAsyncInflationFinished(entry) return true @@ -1775,21 +1582,6 @@ constructor( !oldView.hasFlags(RemoteViews.FLAG_REAPPLY_DISALLOWED) } - @InflationFlag - private fun getRemoteViewsFlags( - @InflationFlag reInflateFlags: Int, - richOngoingContentModel: RichOngoingContentModel? - ): Int = - if (richOngoingContentModel != null) { - reInflateFlags and CONTENT_VIEWS_TO_CREATE_RICH_ONGOING.inv() - } else { - reInflateFlags - } - - @InflationFlag - private const val CONTENT_VIEWS_TO_CREATE_RICH_ONGOING = - FLAG_CONTENT_VIEW_CONTRACTED or FLAG_CONTENT_VIEW_EXPANDED or FLAG_CONTENT_VIEW_HEADS_UP - private const val ASYNC_TASK_TRACE_METHOD = "NotificationRowContentBinderImpl.AsyncInflationTask" private const val APPLY_TRACE_METHOD = "NotificationRowContentBinderImpl#apply" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java index c630c4d43fba..84f2f6670839 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java @@ -18,8 +18,6 @@ package com.android.systemui.statusbar.notification.row; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor; -import com.android.systemui.statusbar.notification.row.shared.RichOngoingNotificationFlag; -import com.android.systemui.statusbar.notification.row.ui.viewmodel.RichOngoingViewModelComponent; import dagger.Binds; import dagger.Module; @@ -30,7 +28,7 @@ import javax.inject.Provider; /** * Dagger Module containing notification row and view inflation implementations. */ -@Module(subcomponents = {RichOngoingViewModelComponent.class}) +@Module public abstract class NotificationRowModule { /** @@ -49,25 +47,6 @@ public abstract class NotificationRowModule { } } - /** Provides ron content model extractor. */ - @Provides - @SysUISingleton - public static RichOngoingNotificationContentExtractor provideRonContentExtractor( - Provider<RichOngoingNotificationContentExtractorImpl> realImpl - ) { - if (RichOngoingNotificationFlag.isEnabled()) { - return realImpl.get(); - } else { - return new NoOpRichOngoingNotificationContentExtractor(); - } - } - - /** Provides ron view inflater. */ - @Binds - @SysUISingleton - public abstract RichOngoingNotificationViewInflater provideRonViewInflater( - RichOngoingNotificationViewInflaterImpl impl); - /** * Provides notification remote view cache instance. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationContentExtractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationContentExtractor.kt deleted file mode 100644 index ec5ebc3651ee..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationContentExtractor.kt +++ /dev/null @@ -1,218 +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.systemui.statusbar.notification.row - -import android.app.Notification -import android.app.PendingIntent -import android.content.Context -import android.util.Log -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.statusbar.notification.collection.NotificationEntry -import com.android.systemui.statusbar.notification.row.shared.EnRouteContentModel -import com.android.systemui.statusbar.notification.row.shared.IconModel -import com.android.systemui.statusbar.notification.row.shared.RichOngoingContentModel -import com.android.systemui.statusbar.notification.row.shared.RichOngoingNotificationFlag -import com.android.systemui.statusbar.notification.row.shared.TimerContentModel -import java.time.Duration -import java.time.LocalDate -import java.time.LocalDateTime -import java.time.LocalTime -import java.time.ZoneId -import javax.inject.Inject - -/** - * Interface which provides a [RichOngoingContentModel] for a given [Notification] when one is - * applicable to the given style. - */ -interface RichOngoingNotificationContentExtractor { - fun extractContentModel( - entry: NotificationEntry, - builder: Notification.Builder, - systemUIContext: Context, - packageContext: Context, - ): RichOngoingContentModel? -} - -class NoOpRichOngoingNotificationContentExtractor : RichOngoingNotificationContentExtractor { - override fun extractContentModel( - entry: NotificationEntry, - builder: Notification.Builder, - systemUIContext: Context, - packageContext: Context, - ): RichOngoingContentModel? = null -} - -@SysUISingleton -class RichOngoingNotificationContentExtractorImpl @Inject constructor() : - RichOngoingNotificationContentExtractor { - - init { - /* check if */ RichOngoingNotificationFlag.isUnexpectedlyInLegacyMode() - } - - override fun extractContentModel( - entry: NotificationEntry, - builder: Notification.Builder, - systemUIContext: Context, - packageContext: Context, - ): RichOngoingContentModel? { - val sbn = entry.sbn - val notification = sbn.notification - val icon = IconModel(notification.smallIcon) - - try { - return if (sbn.packageName == "com.google.android.deskclock") { - when (notification.channelId) { - "Timers v2" -> { - parseTimerNotification(notification, icon) - } - "Stopwatch v2" -> { - Log.i("RONs", "Can't process stopwatch yet") - null - } - else -> { - Log.i("RONs", "Can't process channel '${notification.channelId}'") - null - } - } - } else if (builder.style is Notification.ProgressStyle) { - parseEnRouteNotification(notification, icon) - } else null - } catch (e: Exception) { - Log.e("RONs", "Error parsing RON", e) - return null - } - } - - /** - * FOR PROTOTYPING ONLY: create a RON TimerContentModel using the time information available - * inside the sortKey of the clock app's timer notifications. - */ - private fun parseTimerNotification( - notification: Notification, - icon: IconModel, - ): TimerContentModel { - // sortKey=1 0|↺7|RUNNING|▶16:21:58.523|Σ0:05:00|Δ0:00:03|⏳0:04:57 - // sortKey=1 0|↺7|PAUSED|Σ0:05:00|Δ0:04:54|⏳0:00:06 - // sortKey=1 1|↺7|RUNNING|▶16:30:28.433|Σ0:04:05|Δ0:00:06|⏳0:03:59 - // sortKey=1 0|↺7|RUNNING|▶16:36:18.350|Σ0:05:00|Δ0:01:42|⏳0:03:18 - // sortKey=1 2|↺7|RUNNING|▶16:38:37.816|Σ0:02:00|Δ0:01:09|⏳0:00:51 - // ▶ = "current" time (when updated) - // Σ = total time - // Δ = time elapsed - // ⏳ = time remaining - val sortKey = notification.sortKey - val (_, _, state, extra) = sortKey.split("|", limit = 4) - return when (state) { - "PAUSED" -> { - val (total, _, remaining) = extra.split("|") - val timeRemaining = parseTimeDelta(remaining) - TimerContentModel( - icon = icon, - // TODO: b/352142761 - define and use a string resource rather than " Timer". - // (The UX isn't final so using " Timer" for now). - name = total.replace("Σ", "") + " Timer", - state = - TimerContentModel.TimerState.Paused( - timeRemaining = timeRemaining, - resumeIntent = notification.findStartIntent(), - addMinuteAction = notification.findAddMinuteAction(), - resetAction = notification.findResetAction(), - ), - ) - } - "RUNNING" -> { - val (current, total, _, remaining) = extra.split("|") - val finishTime = parseCurrentTime(current) + parseTimeDelta(remaining).toMillis() - TimerContentModel( - icon = icon, - // TODO: b/352142761 - define and use a string resource rather than " Timer". - // (The UX isn't final so using " Timer" for now). - name = total.replace("Σ", "") + " Timer", - state = - TimerContentModel.TimerState.Running( - finishTime = finishTime, - pauseIntent = notification.findPauseIntent(), - addMinuteAction = notification.findAddMinuteAction(), - resetAction = notification.findResetAction(), - ), - ) - } - else -> error("unknown state ($state) in sortKey=$sortKey") - } - } - - private fun Notification.findPauseIntent(): PendingIntent? { - return actions - .firstOrNull { it.actionIntent.intent?.action?.endsWith(".PAUSE_TIMER") == true } - ?.actionIntent - } - - private fun Notification.findStartIntent(): PendingIntent? { - return actions - .firstOrNull { it.actionIntent.intent?.action?.endsWith(".START_TIMER") == true } - ?.actionIntent - } - - // TODO: b/352142761 - switch to system attributes for label and icon. - // - We probably want a consistent look for the Reset button. (Double check with UX.) - // - Using the custom assets now since I couldn't an existing "Reset" icon. - private fun Notification.findResetAction(): Notification.Action? { - return actions.firstOrNull { - it.actionIntent.intent?.action?.endsWith(".RESET_TIMER") == true - } - } - - // TODO: b/352142761 - check with UX on whether this should be required. - // - Alternative is to allow for optional actions in addition to main and reset. - // - For optional actions, we should take the custom label and icon. - private fun Notification.findAddMinuteAction(): Notification.Action? { - return actions.firstOrNull { - it.actionIntent.intent?.action?.endsWith(".ADD_MINUTE_TIMER") == true - } - } - - private fun parseCurrentTime(current: String): Long { - val (hour, minute, second, millis) = current.replace("▶", "").split(":", ".") - // NOTE: this won't work correctly at/around midnight. It's just for prototyping. - val localDateTime = - LocalDateTime.of( - LocalDate.now(), - LocalTime.of(hour.toInt(), minute.toInt(), second.toInt(), millis.toInt() * 1000000), - ) - val offset = ZoneId.systemDefault().rules.getOffset(localDateTime) - return localDateTime.toInstant(offset).toEpochMilli() - } - - private fun parseTimeDelta(delta: String): Duration { - val (hour, minute, second) = delta.replace("Σ", "").replace("⏳", "").split(":") - return Duration.ofHours(hour.toLong()) - .plusMinutes(minute.toLong()) - .plusSeconds(second.toLong()) - } - - private fun parseEnRouteNotification( - notification: Notification, - icon: IconModel, - ): EnRouteContentModel { - return EnRouteContentModel( - smallIcon = icon, - title = notification.extras.getCharSequence(Notification.EXTRA_TITLE), - text = notification.extras.getCharSequence(Notification.EXTRA_TEXT), - ) - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationViewInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationViewInflater.kt deleted file mode 100644 index 77c4130482c8..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationViewInflater.kt +++ /dev/null @@ -1,226 +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.systemui.statusbar.notification.row - -import android.app.Notification -import android.content.Context -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.res.R -import com.android.systemui.statusbar.notification.collection.NotificationEntry -import com.android.systemui.statusbar.notification.row.ContentViewInflationResult.InflatedContentViewHolder -import com.android.systemui.statusbar.notification.row.ContentViewInflationResult.KeepExistingView -import com.android.systemui.statusbar.notification.row.ContentViewInflationResult.NullContentView -import com.android.systemui.statusbar.notification.row.shared.EnRouteContentModel -import com.android.systemui.statusbar.notification.row.shared.RichOngoingContentModel -import com.android.systemui.statusbar.notification.row.shared.RichOngoingNotificationFlag -import com.android.systemui.statusbar.notification.row.shared.TimerContentModel -import com.android.systemui.statusbar.notification.row.ui.view.EnRouteView -import com.android.systemui.statusbar.notification.row.ui.view.TimerView -import com.android.systemui.statusbar.notification.row.ui.viewbinder.EnRouteViewBinder -import com.android.systemui.statusbar.notification.row.ui.viewbinder.TimerViewBinder -import com.android.systemui.statusbar.notification.row.ui.viewmodel.EnRouteViewModel -import com.android.systemui.statusbar.notification.row.ui.viewmodel.RichOngoingViewModelComponent -import com.android.systemui.statusbar.notification.row.ui.viewmodel.TimerViewModel -import javax.inject.Inject -import kotlinx.coroutines.DisposableHandle - -fun interface DeferredContentViewBinder { - fun setupContentViewBinder(): DisposableHandle -} - -enum class RichOngoingNotificationViewType { - Contracted, - Expanded, - HeadsUp, -} - -/** - * * Supertype of the 3 different possible result types of - * [RichOngoingNotificationViewInflater.inflateView]. - */ -sealed interface ContentViewInflationResult { - - /** Indicates that the content view should be removed if present. */ - data object NullContentView : ContentViewInflationResult - - /** - * Indicates that the content view (which *must be* present) should be unmodified during this - * inflation. - */ - data object KeepExistingView : ContentViewInflationResult - - /** - * Contains the new view and binder that should replace any existing content view for this slot. - */ - data class InflatedContentViewHolder(val view: View, val binder: DeferredContentViewBinder) : - ContentViewInflationResult -} - -fun ContentViewInflationResult?.shouldDisposeViewBinder() = this !is KeepExistingView - -/** - * Interface which provides a [RichOngoingContentModel] for a given [Notification] when one is - * applicable to the given style. - */ -interface RichOngoingNotificationViewInflater { - fun inflateView( - contentModel: RichOngoingContentModel, - existingView: View?, - entry: NotificationEntry, - systemUiContext: Context, - parentView: ViewGroup, - viewType: RichOngoingNotificationViewType, - ): ContentViewInflationResult - - fun canKeepView( - contentModel: RichOngoingContentModel, - existingView: View?, - viewType: RichOngoingNotificationViewType - ): Boolean -} - -@SysUISingleton -class RichOngoingNotificationViewInflaterImpl -@Inject -constructor( - private val viewModelComponentFactory: RichOngoingViewModelComponent.Factory, -) : RichOngoingNotificationViewInflater { - - override fun inflateView( - contentModel: RichOngoingContentModel, - existingView: View?, - entry: NotificationEntry, - systemUiContext: Context, - parentView: ViewGroup, - viewType: RichOngoingNotificationViewType, - ): ContentViewInflationResult { - if (RichOngoingNotificationFlag.isUnexpectedlyInLegacyMode()) return NullContentView - val component = viewModelComponentFactory.create(entry) - return when (contentModel) { - is TimerContentModel -> - inflateTimerView( - existingView, - component::createTimerViewModel, - systemUiContext, - parentView, - viewType - ) - is EnRouteContentModel -> - inflateEnRouteView( - existingView, - component::createEnRouteViewModel, - systemUiContext, - parentView, - viewType - ) - else -> TODO("Not yet implemented") - } - } - - override fun canKeepView( - contentModel: RichOngoingContentModel, - existingView: View?, - viewType: RichOngoingNotificationViewType - ): Boolean { - if (RichOngoingNotificationFlag.isUnexpectedlyInLegacyMode()) return false - return when (contentModel) { - is TimerContentModel -> canKeepTimerView(contentModel, existingView, viewType) - is EnRouteContentModel -> canKeepEnRouteView(contentModel, existingView, viewType) - else -> TODO("Not yet implemented") - } - } - - private fun inflateTimerView( - existingView: View?, - createViewModel: () -> TimerViewModel, - systemUiContext: Context, - parentView: ViewGroup, - viewType: RichOngoingNotificationViewType, - ): ContentViewInflationResult { - if (existingView is TimerView && !existingView.isReinflateNeeded()) return KeepExistingView - - return when (viewType) { - RichOngoingNotificationViewType.Contracted -> { - val newView = - LayoutInflater.from(systemUiContext) - .inflate( - R.layout.rich_ongoing_timer_notification, - parentView, - /* attachToRoot= */ false - ) as TimerView - InflatedContentViewHolder(newView) { - TimerViewBinder.bindWhileAttached(newView, createViewModel()) - } - } - RichOngoingNotificationViewType.Expanded, - RichOngoingNotificationViewType.HeadsUp -> NullContentView - } - } - - private fun canKeepTimerView( - contentModel: TimerContentModel, - existingView: View?, - viewType: RichOngoingNotificationViewType - ): Boolean = true - - private fun inflateEnRouteView( - existingView: View?, - createViewModel: () -> EnRouteViewModel, - systemUiContext: Context, - parentView: ViewGroup, - viewType: RichOngoingNotificationViewType, - ): ContentViewInflationResult { - if (existingView is EnRouteView && !existingView.isReinflateNeeded()) - return KeepExistingView - return when (viewType) { - RichOngoingNotificationViewType.Contracted -> { - val newView = - LayoutInflater.from(systemUiContext) - .inflate( - R.layout.notification_template_en_route_contracted, - parentView, - /* attachToRoot= */ false - ) as EnRouteView - InflatedContentViewHolder(newView) { - EnRouteViewBinder.bindWhileAttached(newView, createViewModel()) - } - } - RichOngoingNotificationViewType.Expanded -> { - val newView = - LayoutInflater.from(systemUiContext) - .inflate( - R.layout.notification_template_en_route_expanded, - parentView, - /* attachToRoot= */ false - ) as EnRouteView - InflatedContentViewHolder(newView) { - EnRouteViewBinder.bindWhileAttached(newView, createViewModel()) - } - } - RichOngoingNotificationViewType.HeadsUp -> NullContentView - } - } - - private fun canKeepEnRouteView( - contentModel: EnRouteContentModel, - existingView: View?, - viewType: RichOngoingNotificationViewType - ): Boolean = true -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/data/repository/NotificationRowRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/data/repository/NotificationRowRepository.kt deleted file mode 100644 index bac887ba7f14..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/data/repository/NotificationRowRepository.kt +++ /dev/null @@ -1,29 +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.systemui.statusbar.notification.row.data.repository - -import com.android.systemui.statusbar.notification.row.shared.RichOngoingContentModel -import kotlinx.coroutines.flow.StateFlow - -/** A repository of states relating to a specific notification row. */ -interface NotificationRowRepository { - /** - * A flow of an immutable data class with the current state of the Rich Ongoing Notification - * content, if applicable. - */ - val richOngoingContentModel: StateFlow<RichOngoingContentModel?> -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/domain/interactor/NotificationRowInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/domain/interactor/NotificationRowInteractor.kt deleted file mode 100644 index 72823a760197..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/domain/interactor/NotificationRowInteractor.kt +++ /dev/null @@ -1,34 +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.systemui.statusbar.notification.row.domain.interactor - -import com.android.systemui.statusbar.notification.row.data.repository.NotificationRowRepository -import com.android.systemui.statusbar.notification.row.shared.EnRouteContentModel -import com.android.systemui.statusbar.notification.row.shared.TimerContentModel -import javax.inject.Inject -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.filterIsInstance - -/** Interactor specific to a particular notification row. */ -class NotificationRowInteractor @Inject constructor(repository: NotificationRowRepository) { - /** Content of a rich ongoing timer notification. */ - val timerContentModel: Flow<TimerContentModel> = - repository.richOngoingContentModel.filterIsInstance<TimerContentModel>() - - /** Content of a rich ongoing timer notification. */ - val enRouteContentModel: Flow<EnRouteContentModel> = - repository.richOngoingContentModel.filterIsInstance<EnRouteContentModel>() -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/IconModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/IconModel.kt deleted file mode 100644 index e61193892d10..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/IconModel.kt +++ /dev/null @@ -1,35 +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.systemui.statusbar.notification.row.shared - -import android.graphics.drawable.Drawable -import android.graphics.drawable.Icon - -// TODO: figure out how to support lazy resolution of the drawable, e.g. on unrelated text change -class IconModel(val icon: Icon) { - var drawable: Drawable? = null - - override fun equals(other: Any?): Boolean = - when (other) { - null -> false - (other === this) -> true - !is IconModel -> false - else -> other.icon.sameAs(icon) - } - - override fun toString(): String = "IconModel(icon=$icon, drawable=$drawable)" -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/NotificationContentModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/NotificationContentModel.kt index 0f9a5a30cbe5..004c66b64b9f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/NotificationContentModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/NotificationContentModel.kt @@ -22,7 +22,4 @@ data class NotificationContentModel( val headsUpStatusBarModel: HeadsUpStatusBarModel, val singleLineViewModel: SingleLineViewModel? = null, val publicSingleLineViewModel: SingleLineViewModel? = null, - val richOngoingContentModel: RichOngoingContentModel? = null, ) - -sealed interface RichOngoingContentModel diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/RichOngoingClock.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/RichOngoingClock.kt deleted file mode 100644 index 33b256456ca3..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/RichOngoingClock.kt +++ /dev/null @@ -1,103 +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.systemui.statusbar.notification.row.shared - -import android.app.Notification -import android.app.PendingIntent -import java.time.Duration - -/** - * Represents a simple timer that counts down to a time. - * - * @param name the label for the timer - * @param state state of the timer, including time and whether it is paused or running - */ -data class TimerContentModel( - val icon: IconModel, - val name: String, - val state: TimerState, -) : RichOngoingContentModel { - /** The state (paused or running) of the timer, and relevant time */ - sealed interface TimerState { - val addMinuteAction: Notification.Action? - val resetAction: Notification.Action? - - /** - * Indicates a running timer - * - * @param finishTime the time in ms since epoch that the timer will finish - * @param pauseIntent the action for pausing the timer - */ - data class Running( - val finishTime: Long, - val pauseIntent: PendingIntent?, - override val addMinuteAction: Notification.Action?, - override val resetAction: Notification.Action?, - ) : TimerState - - /** - * Indicates a paused timer - * - * @param timeRemaining the time in ms remaining on the paused timer - * @param resumeIntent the action for resuming the timer - */ - data class Paused( - val timeRemaining: Duration, - val resumeIntent: PendingIntent?, - override val addMinuteAction: Notification.Action?, - override val resetAction: Notification.Action?, - ) : TimerState - } -} - -/** - * Represents a simple stopwatch that counts up and allows tracking laps. - * - * @param state state of the stopwatch, including time and whether it is paused or running - * @param lapDurations a list of durations of each completed lap - */ -data class StopwatchContentModel( - val icon: IconModel, - val state: StopwatchState, - val lapDurations: List<Long>, -) : RichOngoingContentModel { - /** The state (paused or running) of the stopwatch, and relevant time */ - sealed interface StopwatchState { - /** - * Indicates a running stopwatch - * - * @param startTime the time in ms since epoch that the stopwatch started, plus any - * accumulated pause time - * @param pauseIntent the action for pausing the stopwatch - */ - data class Running( - val startTime: Long, - val pauseIntent: PendingIntent, - ) : StopwatchState - - /** - * Indicates a paused stopwatch - * - * @param timeElapsed the time in ms elapsed on the stopwatch - * @param resumeIntent the action for resuming the stopwatch - */ - data class Paused( - val timeElapsed: Duration, - val resumeIntent: PendingIntent, - ) : StopwatchState - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/RichOngoingNotificationFlag.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/RichOngoingNotificationFlag.kt deleted file mode 100644 index 4a7f7cd46ad1..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/RichOngoingNotificationFlag.kt +++ /dev/null @@ -1,53 +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.systemui.statusbar.notification.row.shared - -import android.app.Flags -import com.android.systemui.flags.FlagToken -import com.android.systemui.flags.RefactorFlagUtils - -/** Helper for reading or using the api rich ongoing flag state. */ -@Suppress("NOTHING_TO_INLINE") -object RichOngoingNotificationFlag { - /** The aconfig flag name */ - const val FLAG_NAME = Flags.FLAG_API_RICH_ONGOING - - /** A token used for dependency declaration */ - val token: FlagToken - get() = FlagToken(FLAG_NAME, isEnabled) - - /** Is the refactor enabled */ - @JvmStatic - inline val isEnabled - get() = Flags.apiRichOngoing() - - /** - * Called to ensure code is only run when the flag is enabled. This protects users from the - * unintended behaviors caused by accidentally running new logic, while also crashing on an eng - * build to ensure that the refactor author catches issues in testing. - */ - @JvmStatic - inline fun isUnexpectedlyInLegacyMode() = - RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME) - - /** - * Called to ensure code is only run when the flag is disabled. This will throw an exception if - * the flag is enabled to ensure that the refactor author catches issues in testing. - */ - @JvmStatic - inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME) -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/view/ConfigurationTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/view/ConfigurationTracker.kt deleted file mode 100644 index 95c507cb72a2..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/view/ConfigurationTracker.kt +++ /dev/null @@ -1,56 +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.systemui.statusbar.notification.row.ui.view - -import android.content.pm.ActivityInfo.CONFIG_ASSETS_PATHS -import android.content.pm.ActivityInfo.CONFIG_DENSITY -import android.content.pm.ActivityInfo.CONFIG_FONT_SCALE -import android.content.pm.ActivityInfo.CONFIG_LAYOUT_DIRECTION -import android.content.pm.ActivityInfo.CONFIG_LOCALE -import android.content.pm.ActivityInfo.CONFIG_UI_MODE -import android.content.res.Configuration -import android.content.res.Resources - -/** - * Tracks the active configuration when constructed and returns (when queried) whether the - * configuration has unhandled changes. - */ -class ConfigurationTracker( - private val resources: Resources, - private val unhandledConfigChanges: Int -) { - private val initialConfig = Configuration(resources.configuration) - - constructor( - resources: Resources, - handlesDensityFontScale: Boolean = false, - handlesTheme: Boolean = false, - handlesLocaleAndLayout: Boolean = true, - ) : this( - resources, - unhandledConfigChanges = - (if (handlesDensityFontScale) 0 else CONFIG_DENSITY or CONFIG_FONT_SCALE) or - (if (handlesTheme) 0 else CONFIG_ASSETS_PATHS or CONFIG_UI_MODE) or - (if (handlesLocaleAndLayout) 0 else CONFIG_LOCALE or CONFIG_LAYOUT_DIRECTION) - ) - - /** - * Whether the current configuration has unhandled changes relative to the initial configuration - */ - fun hasUnhandledConfigChange(): Boolean = - initialConfig.diff(resources.configuration) and unhandledConfigChanges != 0 -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/view/EnRouteView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/view/EnRouteView.kt deleted file mode 100644 index e5c2b5fff5e9..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/view/EnRouteView.kt +++ /dev/null @@ -1,68 +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.systemui.statusbar.notification.row.ui.view - -import android.content.Context -import android.graphics.drawable.Icon -import android.util.AttributeSet -import android.widget.FrameLayout -import android.widget.ImageView -import android.widget.TextView -import com.android.internal.R -import com.android.internal.widget.NotificationExpandButton - -class EnRouteView -@JvmOverloads -constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0, - defStyleRes: Int = 0, -) : FrameLayout(context, attrs, defStyleAttr, defStyleRes) { - - private val configTracker = ConfigurationTracker(resources) - - private lateinit var icon: ImageView - private lateinit var title: TextView - private lateinit var text: TextView - private lateinit var expandButton: NotificationExpandButton - - override fun onFinishInflate() { - super.onFinishInflate() - icon = requireViewById(R.id.icon) - title = requireViewById(R.id.title) - text = requireViewById(R.id.text) - - expandButton = requireViewById(R.id.expand_button) - expandButton.setExpanded(false) - } - - /** the resources configuration has changed such that the view needs to be reinflated */ - fun isReinflateNeeded(): Boolean = configTracker.hasUnhandledConfigChange() - - fun setIcon(icon: Icon?) { - this.icon.setImageIcon(icon) - } - - fun setTitle(title: CharSequence?) { - this.title.text = title - } - - fun setText(text: CharSequence?) { - this.text.text = text - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/view/TimerButtonView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/view/TimerButtonView.kt deleted file mode 100644 index 8c951877544c..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/view/TimerButtonView.kt +++ /dev/null @@ -1,47 +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.systemui.statusbar.notification.row.ui.view - -import android.annotation.DrawableRes -import android.content.Context -import android.graphics.BlendMode -import android.util.AttributeSet -import com.android.internal.widget.EmphasizedNotificationButton - -class TimerButtonView -@JvmOverloads -constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0, - defStyleRes: Int = 0, -) : EmphasizedNotificationButton(context, attrs, defStyleAttr, defStyleRes) { - - private val Int.dp: Int - get() = (this * context.resources.displayMetrics.density).toInt() - - fun setIcon(@DrawableRes icon: Int) { - val drawable = context.getDrawable(icon) - - drawable?.mutate() - drawable?.setTintList(textColors) - drawable?.setTintBlendMode(BlendMode.SRC_IN) - drawable?.setBounds(0, 0, 24.dp, 24.dp) - - setCompoundDrawablesRelative(drawable, null, null, null) - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/view/TimerView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/view/TimerView.kt deleted file mode 100644 index d481b50101c1..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/view/TimerView.kt +++ /dev/null @@ -1,96 +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.systemui.statusbar.notification.row.ui.view - -import android.content.Context -import android.graphics.drawable.Icon -import android.os.SystemClock -import android.util.AttributeSet -import android.widget.Chronometer -import android.widget.ImageView -import android.widget.TextView -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.core.view.isVisible -import com.android.systemui.res.R - -class TimerView -@JvmOverloads -constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0, - defStyleRes: Int = 0, -) : ConstraintLayout(context, attrs, defStyleAttr, defStyleRes) { - - private val configTracker = ConfigurationTracker(resources) - - private lateinit var icon: ImageView - private lateinit var label: TextView - private lateinit var chronometer: Chronometer - private lateinit var pausedTimeRemaining: TextView - lateinit var mainButton: TimerButtonView - private set - - lateinit var altButton: TimerButtonView - private set - - lateinit var resetButton: TimerButtonView - private set - - override fun onFinishInflate() { - super.onFinishInflate() - icon = requireViewById(R.id.icon) - label = requireViewById(R.id.label) - chronometer = requireViewById(R.id.chronoRemaining) - pausedTimeRemaining = requireViewById(R.id.pausedTimeRemaining) - mainButton = requireViewById(R.id.mainButton) - altButton = requireViewById(R.id.altButton) - resetButton = requireViewById(R.id.resetButton) - } - - /** the resources configuration has changed such that the view needs to be reinflated */ - fun isReinflateNeeded(): Boolean = configTracker.hasUnhandledConfigChange() - - fun setIcon(icon: Icon?) { - this.icon.setImageIcon(icon) - } - - fun setLabel(label: String) { - this.label.text = label - } - - fun setPausedTime(pausedTime: String?) { - if (pausedTime != null) { - pausedTimeRemaining.text = pausedTime - pausedTimeRemaining.isVisible = true - } else { - pausedTimeRemaining.isVisible = false - } - } - - fun setCountdownTime(countdownTimeMs: Long?) { - if (countdownTimeMs != null) { - chronometer.base = - countdownTimeMs - System.currentTimeMillis() + SystemClock.elapsedRealtime() - chronometer.isVisible = true - chronometer.start() - } else { - chronometer.isVisible = false - chronometer.stop() - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/EnRouteViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/EnRouteViewBinder.kt deleted file mode 100644 index 3b8957c092f2..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/EnRouteViewBinder.kt +++ /dev/null @@ -1,44 +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.systemui.statusbar.notification.row.ui.viewbinder - -import androidx.lifecycle.lifecycleScope -import com.android.systemui.lifecycle.repeatWhenAttached -import com.android.systemui.statusbar.notification.row.ui.view.EnRouteView -import com.android.systemui.statusbar.notification.row.ui.viewmodel.EnRouteViewModel -import kotlinx.coroutines.DisposableHandle -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch - -/** Binds a [EnRouteView] to its [view model][EnRouteViewModel]. */ -object EnRouteViewBinder { - fun bindWhileAttached( - view: EnRouteView, - viewModel: EnRouteViewModel, - ): DisposableHandle { - return view.repeatWhenAttached { lifecycleScope.launch { bind(view, viewModel) } } - } - - suspend fun bind( - view: EnRouteView, - viewModel: EnRouteViewModel, - ) = coroutineScope { - launch { viewModel.icon.collect { view.setIcon(it) } } - launch { viewModel.title.collect { view.setTitle(it) } } - launch { viewModel.text.collect { view.setText(it) } } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt index 3b0f1ee22be3..a17197c1f8ea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt @@ -24,14 +24,14 @@ import com.android.systemui.statusbar.notification.row.ui.viewmodel.SingleLineVi object SingleLineViewBinder { @JvmStatic fun bind(viewModel: SingleLineViewModel?, view: HybridNotificationView?) { - if (viewModel?.isConversation() == true && view is HybridConversationNotificationView) { + if (view is HybridConversationNotificationView) { if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return - viewModel.conversationData?.avatar?.let { view.setAvatar(it) } + viewModel?.conversationData?.avatar?.let { view.setAvatar(it) } view.setText( - viewModel.titleText, - viewModel.contentText, - viewModel.conversationData?.conversationSenderName + viewModel?.titleText, + viewModel?.contentText, + viewModel?.conversationData?.conversationSenderName, ) } else { // bind the title and content text views @@ -39,7 +39,7 @@ object SingleLineViewBinder { bind( /* title = */ viewModel?.titleText, /* text = */ viewModel?.contentText, - /* contentView = */ null + /* contentView = */ null, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/TimerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/TimerViewBinder.kt deleted file mode 100644 index 042d1bcfb2ee..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/TimerViewBinder.kt +++ /dev/null @@ -1,97 +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.systemui.statusbar.notification.row.ui.viewbinder - -import android.content.res.ColorStateList -import android.graphics.drawable.Icon -import android.view.View -import androidx.core.view.isGone -import androidx.lifecycle.lifecycleScope -import com.android.systemui.lifecycle.repeatWhenAttached -import com.android.systemui.statusbar.notification.row.ui.view.TimerButtonView -import com.android.systemui.statusbar.notification.row.ui.view.TimerView -import com.android.systemui.statusbar.notification.row.ui.viewmodel.TimerViewModel -import kotlinx.coroutines.DisposableHandle -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch - -/** Binds a [TimerView] to its [view model][TimerViewModel]. */ -object TimerViewBinder { - fun bindWhileAttached( - view: TimerView, - viewModel: TimerViewModel, - ): DisposableHandle { - return view.repeatWhenAttached { lifecycleScope.launch { bind(view, viewModel) } } - } - - suspend fun bind( - view: TimerView, - viewModel: TimerViewModel, - ) = coroutineScope { - launch { viewModel.icon.collect { view.setIcon(it) } } - launch { viewModel.label.collect { view.setLabel(it) } } - launch { viewModel.pausedTime.collect { view.setPausedTime(it) } } - launch { viewModel.countdownTime.collect { view.setCountdownTime(it) } } - launch { viewModel.mainButtonModel.collect { bind(view.mainButton, it) } } - launch { viewModel.altButtonModel.collect { bind(view.altButton, it) } } - launch { viewModel.resetButtonModel.collect { bind(view.resetButton, it) } } - } - - fun bind(buttonView: TimerButtonView, model: TimerViewModel.ButtonViewModel?) { - if (model != null) { - buttonView.setButtonBackground( - ColorStateList.valueOf( - buttonView.context.getColor(com.android.internal.R.color.system_accent2_100) - ) - ) - buttonView.setTextColor( - buttonView.context.getColor( - com.android.internal.R.color.notification_primary_text_color_light - ) - ) - - when (model) { - is TimerViewModel.ButtonViewModel.WithSystemAttrs -> { - buttonView.setIcon(model.iconRes) - buttonView.setText(model.labelRes) - } - is TimerViewModel.ButtonViewModel.WithCustomAttrs -> { - // TODO: b/352142761 - is there a better way to deal with TYPE_RESOURCE icons - // with empty resPackage? RemoteViews handles this by using a different - // `contextForResources` for inflation. - val icon = - if (model.icon.type == Icon.TYPE_RESOURCE && model.icon.resPackage == "") - Icon.createWithResource( - "com.google.android.deskclock", - model.icon.resId - ) - else model.icon - buttonView.setImageIcon(icon) - buttonView.text = model.label - } - } - - buttonView.setOnClickListener( - model.pendingIntent?.let { pendingIntent -> - View.OnClickListener { pendingIntent.send() } - } - ) - buttonView.isEnabled = model.pendingIntent != null - } - buttonView.isGone = model == null - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/EnRouteViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/EnRouteViewModel.kt deleted file mode 100644 index 307a9834ccc9..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/EnRouteViewModel.kt +++ /dev/null @@ -1,45 +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.systemui.statusbar.notification.row.ui.viewmodel - -import android.graphics.drawable.Icon -import com.android.systemui.dump.DumpManager -import com.android.systemui.statusbar.notification.row.domain.interactor.NotificationRowInteractor -import com.android.systemui.statusbar.notification.row.shared.RichOngoingNotificationFlag -import com.android.systemui.util.kotlin.FlowDumperImpl -import javax.inject.Inject -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.mapNotNull - -/** A view model for EnRoute notifications. */ -class EnRouteViewModel -@Inject -constructor( - dumpManager: DumpManager, - rowInteractor: NotificationRowInteractor, -) : FlowDumperImpl(dumpManager) { - init { - /* check if */ RichOngoingNotificationFlag.isUnexpectedlyInLegacyMode() - } - - val icon: Flow<Icon?> = rowInteractor.enRouteContentModel.mapNotNull { it.smallIcon.icon } - - val title: Flow<CharSequence?> = rowInteractor.enRouteContentModel.map { it.title } - - val text: Flow<CharSequence?> = rowInteractor.enRouteContentModel.map { it.text } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/TimerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/TimerViewModel.kt deleted file mode 100644 index 768a093e0b65..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/TimerViewModel.kt +++ /dev/null @@ -1,120 +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.systemui.statusbar.notification.row.ui.viewmodel - -import android.annotation.DrawableRes -import android.annotation.StringRes -import android.app.PendingIntent -import android.graphics.drawable.Icon -import com.android.systemui.dump.DumpManager -import com.android.systemui.statusbar.notification.row.domain.interactor.NotificationRowInteractor -import com.android.systemui.statusbar.notification.row.shared.RichOngoingNotificationFlag -import com.android.systemui.statusbar.notification.row.shared.TimerContentModel.TimerState -import com.android.systemui.util.kotlin.FlowDumperImpl -import java.time.Duration -import javax.inject.Inject -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.mapNotNull - -/** A view model for Timer notifications. */ -class TimerViewModel -@Inject -constructor( - dumpManager: DumpManager, - rowInteractor: NotificationRowInteractor, -) : FlowDumperImpl(dumpManager) { - init { - /* check if */ RichOngoingNotificationFlag.isUnexpectedlyInLegacyMode() - } - - private val state: Flow<TimerState> = rowInteractor.timerContentModel.mapNotNull { it.state } - - val icon: Flow<Icon?> = rowInteractor.timerContentModel.mapNotNull { it.icon.icon } - - val label: Flow<String> = rowInteractor.timerContentModel.mapNotNull { it.name } - - val countdownTime: Flow<Long?> = state.map { (it as? TimerState.Running)?.finishTime } - - val pausedTime: Flow<String?> = - state.map { (it as? TimerState.Paused)?.timeRemaining?.format() } - - val mainButtonModel: Flow<ButtonViewModel> = - state.map { - when (it) { - is TimerState.Paused -> - ButtonViewModel.WithSystemAttrs( - it.resumeIntent, - com.android.systemui.res.R.string.controls_media_resume, // "Resume", - com.android.systemui.res.R.drawable.ic_media_play - ) - is TimerState.Running -> - ButtonViewModel.WithSystemAttrs( - it.pauseIntent, - com.android.systemui.res.R.string.controls_media_button_pause, // "Pause", - com.android.systemui.res.R.drawable.ic_media_pause - ) - } - } - - val altButtonModel: Flow<ButtonViewModel?> = - state.map { - it.addMinuteAction?.let { action -> - ButtonViewModel.WithCustomAttrs( - action.actionIntent, - action.title, // "1:00", - action.getIcon() - ) - } - } - - val resetButtonModel: Flow<ButtonViewModel?> = - state.map { - it.resetAction?.let { action -> - ButtonViewModel.WithCustomAttrs( - action.actionIntent, - action.title, // "Reset", - action.getIcon() - ) - } - } - - sealed interface ButtonViewModel { - val pendingIntent: PendingIntent? - - data class WithSystemAttrs( - override val pendingIntent: PendingIntent?, - @StringRes val labelRes: Int, - @DrawableRes val iconRes: Int, - ) : ButtonViewModel - - data class WithCustomAttrs( - override val pendingIntent: PendingIntent?, - val label: CharSequence, - val icon: Icon, - ) : ButtonViewModel - } -} - -private fun Duration.format(): String { - val hours = this.toHours() - return if (hours > 0) { - String.format("%d:%02d:%02d", hours, toMinutesPart(), toSecondsPart()) - } else { - String.format("%d:%02d", toMinutes(), toSecondsPart()) - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java index b1083888ca7f..cfca8307e703 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java @@ -1704,6 +1704,7 @@ public class NotificationChildrenContainer extends ViewGroup + "visibility: " + getVisibility() + ", alpha: " + getAlpha() + ", translationY: " + getTranslationY() + + ", clipBounds: " + getClipBounds() + ", roundableState: " + getRoundableState().debugString() + "}"; } } 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 b466bf02387f..8ae6b7920674 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 @@ -113,6 +113,7 @@ import com.android.systemui.statusbar.notification.row.ActivatableNotificationVi import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableView; import com.android.systemui.statusbar.notification.row.StackScrollerDecorView; +import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization; import com.android.systemui.statusbar.notification.shared.NotificationHeadsUpCycling; import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun; import com.android.systemui.statusbar.notification.shared.NotificationsImprovedHunAnimation; @@ -1160,11 +1161,13 @@ public class NotificationStackScrollLayout @Override public void addHeadsUpHeightChangedListener(@NonNull Runnable runnable) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; mHeadsUpHeightChangedListeners.addIfAbsent(runnable); } @Override public void removeHeadsUpHeightChangedListener(@NonNull Runnable runnable) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; mHeadsUpHeightChangedListeners.remove(runnable); } @@ -1240,11 +1243,13 @@ public class NotificationStackScrollLayout @Override public void setScrolledToTop(boolean scrolledToTop) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; mScrollViewFields.setScrolledToTop(scrolledToTop); } @Override public void setStackTop(float stackTop) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; if (mAmbientState.getStackTop() != stackTop) { mAmbientState.setStackTop(stackTop); onTopPaddingChanged(/* animate = */ isAddOrRemoveAnimationPending()); @@ -1253,51 +1258,54 @@ public class NotificationStackScrollLayout @Override public void setStackCutoff(float stackCutoff) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; mAmbientState.setStackCutoff(stackCutoff); } @Override public void setHeadsUpTop(float headsUpTop) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; mAmbientState.setHeadsUpTop(headsUpTop); requestChildrenUpdate(); } @Override public void setHeadsUpBottom(float headsUpBottom) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; mAmbientState.setHeadsUpBottom(headsUpBottom); mStateAnimator.setHeadsUpAppearHeightBottom(Math.round(headsUpBottom)); } @Override public void closeGutsOnSceneTouch() { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; mController.closeControlsDueToOutsideTouch(); } @Override public void setSyntheticScrollConsumer(@Nullable Consumer<Float> consumer) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; mScrollViewFields.setSyntheticScrollConsumer(consumer); } @Override public void setCurrentGestureOverscrollConsumer(@Nullable Consumer<Boolean> consumer) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; mScrollViewFields.setCurrentGestureOverscrollConsumer(consumer); } @Override public void setCurrentGestureInGutsConsumer(@Nullable Consumer<Boolean> consumer) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; mScrollViewFields.setCurrentGestureInGutsConsumer(consumer); } @Override public void setRemoteInputRowBottomBoundConsumer(@Nullable Consumer<Float> consumer) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; mScrollViewFields.setRemoteInputRowBottomBoundConsumer(consumer); } - @Override - public void setHeadsUpHeightConsumer(@Nullable Consumer<Float> consumer) { - mScrollViewFields.setHeadsUpHeightConsumer(consumer); - } - /** * @param listener to be notified after the location of Notification children might have * changed. @@ -2621,11 +2629,13 @@ public class NotificationStackScrollLayout @Override public int getTopHeadsUpHeight() { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return 0; return getTopHeadsUpIntrinsicHeight(); } @Override public int getHeadsUpInset() { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return 0; return mHeadsUpInset; } @@ -4363,6 +4373,16 @@ public class NotificationStackScrollLayout } } + private void resetChildAlpha() { + for (int i = 0; i < getChildCount(); i++) { + ExpandableView child = getChildAtIndex(i); + if (child instanceof ExpandableNotificationRow row) { + if (row.isExpandAnimationRunning()) continue; + row.resetAllContentAlphas(); + } + } + } + private void logTransientNotificationRowTraversalCleaned( ExpandableNotificationRow transientView, String reason @@ -4406,6 +4426,9 @@ public class NotificationStackScrollLayout if (SceneContainerFlag.isEnabled()) { setHeadsUpAnimatingAway(false); } + if (NotificationContentAlphaOptimization.isEnabled()) { + resetChildAlpha(); + } } else { mGroupExpansionManager.collapseGroups(); mExpandHelper.cancelImmediately(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt index c08ed6120832..f6e8b8f0166b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt @@ -86,9 +86,6 @@ class ScrollViewFields { fun sendRemoteInputRowBottomBound(bottomY: Float?) = remoteInputRowBottomBoundConsumer?.accept(bottomY) - /** send the [headsUpHeight] to the [headsUpHeightConsumer], if present. */ - fun sendHeadsUpHeight(headsUpHeight: Float) = headsUpHeightConsumer?.accept(headsUpHeight) - fun dump(pw: IndentingPrintWriter) { pw.printSection("StackViewStates") { pw.println("scrimClippingShape", scrimClippingShape) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt index dbe81c10e2fd..6ad9f01ca4ff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt @@ -77,9 +77,6 @@ interface NotificationScrollView { /** Set a consumer for current remote input notification row bottom bound events */ fun setRemoteInputRowBottomBoundConsumer(consumer: Consumer<Float?>?) - /** Set a consumer for heads up height changed events */ - fun setHeadsUpHeightConsumer(consumer: Consumer<Float>?) - /** sets that scrolling is allowed */ fun setScrollingEnabled(enabled: Boolean) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt index 935e2a37b13c..38390e7bdb39 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt @@ -356,11 +356,23 @@ constructor( } } - val pinnedHeadsUpRows: Flow<Set<HeadsUpRowKey>> by lazy { + val activeHeadsUpRowKeys: Flow<Set<HeadsUpRowKey>> by lazy { if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { flowOf(emptySet()) } else { - headsUpNotificationInteractor.pinnedHeadsUpRows.dumpWhileCollecting("pinnedHeadsUpRows") + headsUpNotificationInteractor.activeHeadsUpRowKeys.dumpWhileCollecting( + "pinnedHeadsUpRows" + ) + } + } + + val pinnedHeadsUpRowKeys: Flow<Set<HeadsUpRowKey>> by lazy { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { + flowOf(emptySet()) + } else { + headsUpNotificationInteractor.pinnedHeadsUpRowKeys.dumpWhileCollecting( + "pinnedHeadsUpRows" + ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt index c9eaec7c5b85..aec81b0241a2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt @@ -84,9 +84,9 @@ constructor( private fun fullyExpandedDuringSceneChange(change: ChangeScene): Boolean { // The lockscreen stack is visible during all transitions away from the lockscreen, so keep // the stack expanded until those transitions finish. - return if (change.isFrom({ it == Scenes.Lockscreen }, to = { true })) { + return if (change.isTransitioning(from = Scenes.Lockscreen)) { true - } else if (change.isFrom({ it == Scenes.Shade }, to = { it == Scenes.Lockscreen })) { + } else if (change.isTransitioning(from = Scenes.Shade, to = Scenes.Lockscreen)) { false } else { (expandedInScene(change.fromScene) && expandedInScene(change.toScene)) @@ -101,11 +101,11 @@ constructor( return if (fullyExpandedDuringSceneChange(change)) { 1f } else if ( - change.isBetween({ it == Scenes.Gone }, { it == Scenes.Shade }) || - change.isFrom({ it == Scenes.Shade }, to = { it == Scenes.Lockscreen }) + change.isTransitioningBetween(Scenes.Gone, Scenes.Shade) || + change.isTransitioning(from = Scenes.Gone, to = Scenes.Lockscreen) ) { shadeExpansion - } else if (change.isBetween({ it == Scenes.Gone }, { it == Scenes.QuickSettings })) { + } else if (change.isTransitioningBetween(Scenes.Gone, Scenes.QuickSettings)) { // during QS expansion, increase fraction at same rate as scrim alpha, // but start when scrim alpha is at EXPANSION_FOR_DELAYED_STACK_FADE_IN. (qsExpansion / EXPANSION_FOR_MAX_SCRIM_ALPHA - EXPANSION_FOR_DELAYED_STACK_FADE_IN) @@ -213,7 +213,11 @@ constructor( private val qsAllowsClipping: Flow<Boolean> = combine(shadeInteractor.shadeMode, shadeInteractor.qsExpansion) { shadeMode, qsExpansion -> - qsExpansion < 0.5f || shadeMode != ShadeMode.Single + when (shadeMode) { + is ShadeMode.Dual -> false + is ShadeMode.Split -> true + is ShadeMode.Single -> qsExpansion < 0.5f + } } .distinctUntilChanged() @@ -325,9 +329,3 @@ constructor( fun create(): NotificationScrollViewModel } } - -private fun ChangeScene.isBetween(a: (SceneKey) -> Boolean, b: (SceneKey) -> Boolean): Boolean = - (a(fromScene) && b(toScene)) || (b(fromScene) && a(toScene)) - -private fun ChangeScene.isFrom(from: (SceneKey) -> Boolean, to: (SceneKey) -> Boolean): Boolean = - from(fromScene) && to(toScene) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ui/viewbinder/HeadsUpNotificationViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ui/viewbinder/HeadsUpNotificationViewBinder.kt index dc15970b318b..e2e5c5970ff5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ui/viewbinder/HeadsUpNotificationViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ui/viewbinder/HeadsUpNotificationViewBinder.kt @@ -26,6 +26,7 @@ import javax.inject.Inject import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch class HeadsUpNotificationViewBinder @@ -35,18 +36,21 @@ constructor(private val viewModel: NotificationListViewModel) { coroutineScope { launch { var previousKeys = emptySet<HeadsUpRowKey>() - viewModel.pinnedHeadsUpRows + combine(viewModel.pinnedHeadsUpRowKeys, viewModel.activeHeadsUpRowKeys, ::Pair) .sample(viewModel.headsUpAnimationsEnabled, ::Pair) .collect { (newKeys, animationsEnabled) -> - val added = newKeys - previousKeys - val removed = previousKeys - newKeys - previousKeys = newKeys + val pinned = newKeys.first + val all = newKeys.second + val added = all.union(pinned) - previousKeys + val removed = previousKeys - pinned + previousKeys = pinned + Pair(added, removed) if (animationsEnabled) { added.forEach { key -> parentView.generateHeadsUpAnimation( obtainView(key), - /* isHeadsUp = */ true + /* isHeadsUp = */ true, ) } removed.forEach { key -> 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 5ae24f76a9bf..479ffb728eb2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -55,6 +55,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.keyguard.KeyguardViewController; import com.android.keyguard.TrustGrantFlags; import com.android.keyguard.ViewMediatorCallback; +import com.android.systemui.DejankUtils; import com.android.systemui.Flags; import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor; import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor; @@ -1203,6 +1204,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public void hide(long startTime, long fadeoutDuration) { Trace.beginSection("StatusBarKeyguardViewManager#hide"); + if (Flags.checkLockscreenGoneTransition()) { + DejankUtils.notifyRendererOfExpensiveFrame( + mNotificationShadeWindowController.getWindowRootView(), + "StatusBarKeyguardViewManager#hide"); + } mKeyguardStateController.notifyKeyguardState(false, mKeyguardStateController.isOccluded()); launchPendingWakeupAction(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocationPublisher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocationPublisher.kt deleted file mode 100644 index 4e5ecfe3f623..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocationPublisher.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.statusbar.phone - -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.statusbar.policy.CallbackController -import java.lang.ref.WeakReference -import javax.inject.Inject - -/** - * Publishes updates to the status bar's margins. - * - * While the status bar view consumes the entire width of the device, the status bar - * contents are laid out with margins for rounded corners, padding from the absolute - * edges, and potentially display cutouts in the corner. - */ -@SysUISingleton -class StatusBarLocationPublisher @Inject constructor() -: CallbackController<StatusBarMarginUpdatedListener> { - private val listeners = mutableSetOf<WeakReference<StatusBarMarginUpdatedListener>>() - - var marginLeft: Int = 0 - private set - var marginRight: Int = 0 - private set - - override fun addCallback(listener: StatusBarMarginUpdatedListener) { - listeners.add(WeakReference(listener)) - } - - override fun removeCallback(listener: StatusBarMarginUpdatedListener) { - var toRemove: WeakReference<StatusBarMarginUpdatedListener>? = null - for (l in listeners) { - if (l.get() == listener) { - toRemove = l - } - } - - if (toRemove != null) { - listeners.remove(toRemove) - } - } - - fun updateStatusBarMargin(left: Int, right: Int) { - marginLeft = left - marginRight = right - - notifyListeners() - } - - private fun notifyListeners() { - var listenerList: List<WeakReference<StatusBarMarginUpdatedListener>> - synchronized(this) { - listenerList = listeners.toList() - } - - listenerList.forEach { wrapper -> - if (wrapper.get() == null) { - listeners.remove(wrapper) - } - - wrapper.get()?.onStatusBarMarginUpdated(marginLeft, marginRight) - } - } -} - -interface StatusBarMarginUpdatedListener { - fun onStatusBarMarginUpdated(marginLeft: Int, marginRight: Int) -}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index a8b4728bc982..c258095510c6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -65,7 +65,6 @@ import com.android.systemui.statusbar.phone.NotificationIconContainer; import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager; import com.android.systemui.statusbar.phone.StatusBarLocation; -import com.android.systemui.statusbar.phone.StatusBarLocationPublisher; import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent.Startable; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; @@ -140,7 +139,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private final OperatorNameViewController.Factory mOperatorNameViewControllerFactory; private final OngoingCallController mOngoingCallController; private final SystemStatusAnimationScheduler mAnimationScheduler; - private final StatusBarLocationPublisher mLocationPublisher; private final ShadeExpansionStateManager mShadeExpansionStateManager; private final StatusBarIconController mStatusBarIconController; private final CarrierConfigTracker mCarrierConfigTracker; @@ -243,7 +241,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory, OngoingCallController ongoingCallController, SystemStatusAnimationScheduler animationScheduler, - StatusBarLocationPublisher locationPublisher, ShadeExpansionStateManager shadeExpansionStateManager, StatusBarIconController statusBarIconController, DarkIconManager.Factory darkIconManagerFactory, @@ -267,7 +264,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory; mOngoingCallController = ongoingCallController; mAnimationScheduler = animationScheduler; - mLocationPublisher = locationPublisher; mShadeExpansionStateManager = shadeExpansionStateManager; mStatusBarIconController = statusBarIconController; mCollapsedStatusBarViewModel = collapsedStatusBarViewModel; @@ -349,9 +345,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue } mStatusBar = (PhoneStatusBarView) view; - View contents = mStatusBar.findViewById(R.id.status_bar_contents); - contents.addOnLayoutChangeListener(mStatusBarLayoutListener); - updateStatusBarLocation(contents.getLeft(), contents.getRight()); if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_PANEL_STATE)) { mStatusBar.restoreHierarchyState( savedInstanceState.getSparseParcelableArray(EXTRA_PANEL_STATE)); @@ -977,13 +970,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue }, /*isAnimationRunning*/ false); } - private void updateStatusBarLocation(int left, int right) { - int leftMargin = left - mStatusBar.getLeft(); - int rightMargin = mStatusBar.getRight() - right; - - mLocationPublisher.updateStatusBarMargin(leftMargin, rightMargin); - } - private final ContentObserver mVolumeSettingObserver = new ContentObserver(null) { @Override public void onChange(boolean selfChange) { @@ -991,14 +977,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue } }; - // Listen for view end changes of PhoneStatusBarView and publish that to the privacy dot - private View.OnLayoutChangeListener mStatusBarLayoutListener = - (view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { - if (left != oldLeft || right != oldRight) { - updateStatusBarLocation(left, right); - } - }; - @Override public void dump(PrintWriter printWriter, String[] args) { IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, /* singleIndent= */" "); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt index eea4c212e40e..9c168be0693f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt @@ -95,7 +95,8 @@ class CollapsedStatusBarViewBinderImpl @Inject constructor() : CollapsedStatusBa primaryChipView.show(shouldAnimateChange = true) is OngoingActivityChipModel.Hidden -> primaryChipView.hide( - shouldAnimateChange = primaryChipModel.shouldAnimate + state = View.GONE, + shouldAnimateChange = primaryChipModel.shouldAnimate, ) } } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureControllerExt.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureControllerExt.kt new file mode 100644 index 000000000000..441cbb33f821 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureControllerExt.kt @@ -0,0 +1,33 @@ +/* + * 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.statusbar.policy + +import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt +import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.onStart + +/** [DevicePostureController.getDevicePosture] as a [Flow]. */ +@DevicePostureInt +fun DevicePostureController.devicePosture(): Flow<Int> = + conflatedCallbackFlow { + val callback = DevicePostureController.Callback { posture -> trySend(posture) } + addCallback(callback) + awaitClose { removeCallback(callback) } + } + .onStart { emit(devicePosture) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java index e09e5777a9a3..0cba94016ffb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java @@ -16,8 +16,6 @@ package com.android.systemui.statusbar.policy; -import static com.android.systemui.Flags.registerZenModeContentObserverBackground; - import android.app.AlarmManager; import android.app.Flags; import android.app.NotificationManager; @@ -47,7 +45,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dumpable; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.settings.UserTracker; @@ -107,7 +104,6 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable { public ZenModeControllerImpl( Context context, @Main Handler handler, - @Background Handler bgHandler, BroadcastDispatcher broadcastDispatcher, DumpManager dumpManager, GlobalSettings globalSettings, @@ -138,17 +134,9 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable { } }; mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - if (registerZenModeContentObserverBackground()) { - bgHandler.post(() -> { - globalSettings.registerContentObserverSync(Global.ZEN_MODE, modeContentObserver); - globalSettings.registerContentObserverSync(Global.ZEN_MODE_CONFIG_ETAG, - configContentObserver); - }); - } else { - globalSettings.registerContentObserverSync(Global.ZEN_MODE, modeContentObserver); - globalSettings.registerContentObserverSync(Global.ZEN_MODE_CONFIG_ETAG, - configContentObserver); - } + globalSettings.registerContentObserverAsync(Global.ZEN_MODE, modeContentObserver); + globalSettings.registerContentObserverAsync(Global.ZEN_MODE_CONFIG_ETAG, + configContentObserver); updateZenMode(getModeSettingValueFromProvider()); updateZenModeConfig(); updateConsolidatedNotificationPolicy(); 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 6764839c32d3..4f595ed152e4 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 @@ -76,7 +76,7 @@ constructor( // can be manually toggled on mode.rule.isEnabled -> mode.isActive || mode.rule.isManualInvocationAllowed // Mode was created as disabled, or disabled by the app that owns it -> - // will be shown with a "Set up" text + // will be shown with a "Not set" text !mode.rule.isEnabled -> mode.status == ZenMode.Status.DISABLED_BY_OTHER else -> false } @@ -120,7 +120,7 @@ constructor( }, onLongClick = { openSettings(mode) }, onLongClickLabel = - context.resources.getString(R.string.accessibility_long_click_tile) + context.resources.getString(R.string.accessibility_long_click_tile), ) } } @@ -137,10 +137,10 @@ constructor( /** * Returns a description of the mode, which is: - * * a prompt to set up the mode if it is not enabled - * * if it cannot be manually activated, text that says so - * * otherwise, the trigger description of the mode if it exists... - * * ...or null if it doesn't + * * a prompt to set up the mode if it is not enabled + * * if it cannot be manually activated, text that says so + * * otherwise, the trigger description of the mode if it exists... + * * ...or null if it doesn't * * This description is used directly for the content description of a mode tile for screen * readers, and for the tile subtext will be augmented with the current status of the mode. @@ -174,7 +174,7 @@ constructor( context, R.style.Theme_SystemUI_Dialog, /* cancelIsNeutral= */ true, - zenDialogMetricsLogger + zenDialogMetricsLogger, ) .createDialog() SystemUIDialog.applyFlags(dialog) diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt index e1b89da392ea..72389cd45fe0 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt @@ -38,9 +38,9 @@ import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionSta import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig import com.android.systemui.touchpad.tutorial.ui.gesture.EasterEggGestureMonitor 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.GestureState.NOT_STARTED +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.Finished +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.InProgress +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NotStarted import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureMonitor @@ -76,9 +76,9 @@ class DistanceBasedGestureMonitorProvider( fun GestureState.toTutorialActionState(): TutorialActionState { return when (this) { - NOT_STARTED -> TutorialActionState.NOT_STARTED - IN_PROGRESS -> TutorialActionState.IN_PROGRESS - FINISHED -> TutorialActionState.FINISHED + NotStarted -> TutorialActionState.NotStarted + is InProgress -> TutorialActionState.InProgress() + Finished -> TutorialActionState.Finished } } @@ -90,7 +90,7 @@ fun GestureTutorialScreen( onBack: () -> Unit, ) { BackHandler(onBack = onBack) - var gestureState by remember { mutableStateOf(NOT_STARTED) } + var gestureState: GestureState by remember { mutableStateOf(NotStarted) } var easterEggTriggered by remember { mutableStateOf(false) } val gestureMonitor = gestureMonitorProvider.rememberGestureMonitor( @@ -143,7 +143,7 @@ private fun TouchpadGesturesHandlingBox( .pointerInteropFilter( onTouchEvent = { event -> // FINISHED is the final state so we don't need to process touches anymore - if (gestureState == FINISHED) { + if (gestureState == Finished) { false } else { gestureHandler.onMotionEvent(event) diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt index 6acc891e93d5..94e19deb0006 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt @@ -20,19 +20,27 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.outlined.ArrowBack import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp import com.android.systemui.inputdevice.tutorial.ui.composable.DoneButton import com.android.systemui.res.R @@ -47,20 +55,17 @@ fun TutorialSelectionScreen( Column( verticalArrangement = Arrangement.Center, modifier = - Modifier.background( - color = MaterialTheme.colorScheme.surfaceContainer, - ) - .fillMaxSize() + Modifier.background(color = MaterialTheme.colorScheme.surfaceContainer).fillMaxSize(), ) { TutorialSelectionButtons( onBackTutorialClicked = onBackTutorialClicked, onHomeTutorialClicked = onHomeTutorialClicked, onRecentAppsTutorialClicked = onRecentAppsTutorialClicked, - modifier = Modifier.padding(60.dp) + modifier = Modifier.padding(60.dp), ) DoneButton( onDoneButtonClicked = onDoneButtonClicked, - modifier = Modifier.padding(horizontal = 60.dp) + modifier = Modifier.padding(horizontal = 60.dp), ) } } @@ -70,30 +75,36 @@ private fun TutorialSelectionButtons( onBackTutorialClicked: () -> Unit, onHomeTutorialClicked: () -> Unit, onRecentAppsTutorialClicked: () -> Unit, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { Row( horizontalArrangement = Arrangement.spacedBy(20.dp), verticalAlignment = Alignment.CenterVertically, - modifier = modifier + modifier = modifier, ) { TutorialButton( text = stringResource(R.string.touchpad_tutorial_home_gesture_button), + icon = Icons.AutoMirrored.Outlined.ArrowBack, + iconColor = MaterialTheme.colorScheme.onPrimary, onClick = onHomeTutorialClicked, - color = MaterialTheme.colorScheme.primary, - modifier = Modifier.weight(1f) + backgroundColor = MaterialTheme.colorScheme.primary, + modifier = Modifier.weight(1f), ) TutorialButton( text = stringResource(R.string.touchpad_tutorial_back_gesture_button), + icon = ImageVector.vectorResource(id = R.drawable.touchpad_tutorial_home_icon), + iconColor = MaterialTheme.colorScheme.onTertiary, onClick = onBackTutorialClicked, - color = MaterialTheme.colorScheme.tertiary, - modifier = Modifier.weight(1f) + backgroundColor = MaterialTheme.colorScheme.tertiary, + modifier = Modifier.weight(1f), ) TutorialButton( text = stringResource(R.string.touchpad_tutorial_recent_apps_gesture_button), + icon = ImageVector.vectorResource(id = R.drawable.touchpad_tutorial_recents_icon), + iconColor = MaterialTheme.colorScheme.onSecondary, onClick = onRecentAppsTutorialClicked, - color = MaterialTheme.colorScheme.secondary, - modifier = Modifier.weight(1f) + backgroundColor = MaterialTheme.colorScheme.secondary, + modifier = Modifier.weight(1f), ) } } @@ -101,16 +112,30 @@ private fun TutorialSelectionButtons( @Composable private fun TutorialButton( text: String, + icon: ImageVector, + iconColor: Color, onClick: () -> Unit, - color: Color, - modifier: Modifier = Modifier + backgroundColor: Color, + modifier: Modifier = Modifier, ) { Button( onClick = onClick, shape = RoundedCornerShape(16.dp), - colors = ButtonDefaults.buttonColors(containerColor = color), - modifier = modifier.aspectRatio(0.66f) + colors = ButtonDefaults.buttonColors(containerColor = backgroundColor), + modifier = modifier.aspectRatio(0.66f), ) { - Text(text = text, style = MaterialTheme.typography.headlineLarge) + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Icon( + imageVector = icon, + contentDescription = text, + modifier = Modifier.width(30.dp).height(30.dp), + tint = iconColor, + ) + Spacer(modifier = Modifier.height(16.dp)) + Text(text = text, style = MaterialTheme.typography.headlineLarge) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureState.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureState.kt index 446875af66e7..b513c49371a4 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureState.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureState.kt @@ -16,8 +16,10 @@ package com.android.systemui.touchpad.tutorial.ui.gesture -enum class GestureState { - NOT_STARTED, - IN_PROGRESS, - FINISHED +sealed interface GestureState { + data object NotStarted : GestureState + + data object Finished : GestureState + + data class InProgress(val progress: Float = 0f) : GestureState } diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureMonitor.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureMonitor.kt index 58282393d4a6..ca3880a5dfe6 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureMonitor.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureMonitor.kt @@ -43,14 +43,14 @@ class RecentAppsGestureMonitor( if (isThreeFingerTouchpadSwipe(event)) { xStart = event.x yStart = event.y - gestureStateChangedCallback(GestureState.IN_PROGRESS) + gestureStateChangedCallback(GestureState.InProgress()) } } MotionEvent.ACTION_UP -> { if (isThreeFingerTouchpadSwipe(event) && isRecentAppsGesture(event)) { - gestureStateChangedCallback(GestureState.FINISHED) + gestureStateChangedCallback(GestureState.Finished) } else { - gestureStateChangedCallback(GestureState.NOT_STARTED) + gestureStateChangedCallback(GestureState.NotStarted) } velocityTracker.resetTracking() } diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/ThreeFingerDistanceBasedGestureMonitor.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/ThreeFingerDistanceBasedGestureMonitor.kt index 9bf0fe96624f..12bcaeac04dc 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/ThreeFingerDistanceBasedGestureMonitor.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/ThreeFingerDistanceBasedGestureMonitor.kt @@ -46,15 +46,15 @@ class ThreeFingerDistanceBasedGestureMonitor( if (isThreeFingerTouchpadSwipe(event)) { xStart = event.x yStart = event.y - gestureStateChangedCallback(GestureState.IN_PROGRESS) + gestureStateChangedCallback(GestureState.InProgress()) } } MotionEvent.ACTION_UP -> { if (isThreeFingerTouchpadSwipe(event)) { if (donePredicate.wasGestureDone(xStart, yStart, event.x, event.y)) { - gestureStateChangedCallback(GestureState.FINISHED) + gestureStateChangedCallback(GestureState.Finished) } else { - gestureStateChangedCallback(GestureState.NOT_STARTED) + gestureStateChangedCallback(GestureState.NotStarted) } } } diff --git a/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java index 947746c94198..4b2fe49c41b4 100644 --- a/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java @@ -45,8 +45,8 @@ import java.io.IOException; * This class should only be used in XML. * * @attr ref android.R.styleable#DrawableWrapper_drawable - * @attr ref R.styleable#AlphaTintDrawableWrapper_tint - * @attr ref R.styleable#AlphaTintDrawableWrapper_alpha + * @attr ref android.R.styleable#AlphaTintDrawableWrapper_tint + * @attr ref android.R.styleable#AlphaTintDrawableWrapper_alpha */ public class AlphaTintDrawableWrapper extends InsetDrawable { private ColorStateList mTint; diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/NewVolumeDialogPlugin.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/NewVolumeDialogPlugin.kt deleted file mode 100644 index b93714ae4fd4..000000000000 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/NewVolumeDialogPlugin.kt +++ /dev/null @@ -1,67 +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.systemui.volume.dialog - -import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.plugins.VolumeDialog -import com.android.systemui.volume.dialog.dagger.VolumeDialogComponent -import com.android.systemui.volume.dialog.dagger.VolumeDialogPluginComponent -import javax.inject.Inject -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.cancel -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch - -class NewVolumeDialogPlugin -@Inject -constructor( - @Application private val applicationCoroutineScope: CoroutineScope, - private val volumeDialogPluginComponentFactory: VolumeDialogPluginComponent.Factory, -) : VolumeDialog { - - private var volumeDialogPluginComponent: VolumeDialogPluginComponent? = null - private var job: Job? = null - - override fun init(windowType: Int, callback: VolumeDialog.Callback?) { - job = - applicationCoroutineScope.launch { - coroutineScope { - volumeDialogPluginComponent = volumeDialogPluginComponentFactory.create(this) - } - } - } - - private fun showDialog() { - val volumeDialogPluginComponent = - volumeDialogPluginComponent ?: error("Creating dialog before init was called") - volumeDialogPluginComponent.coroutineScope().launch { - coroutineScope { - val volumeDialogComponent: VolumeDialogComponent = - volumeDialogPluginComponent.volumeDialogComponentFactory().create(this) - with(volumeDialogComponent.volumeDialog()) { - setOnDismissListener { volumeDialogComponent.coroutineScope().cancel() } - show() - } - } - } - } - - override fun destroy() { - job?.cancel() - } -} diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt index 74e823e9f592..7476c6a279f3 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt @@ -20,15 +20,39 @@ import android.app.Dialog import android.content.Context import android.os.Bundle import android.view.ContextThemeWrapper +import android.view.MotionEvent import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.res.R +import com.android.systemui.volume.Events +import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogVisibilityInteractor +import com.android.systemui.volume.dialog.ui.binder.VolumeDialogBinder import javax.inject.Inject -class VolumeDialog @Inject constructor(@Application context: Context) : - Dialog(ContextThemeWrapper(context, R.style.volume_dialog_theme)) { +class VolumeDialog +@Inject +constructor( + @Application context: Context, + private val dialogBinder: VolumeDialogBinder, + private val visibilityInteractor: VolumeDialogVisibilityInteractor, +) : Dialog(ContextThemeWrapper(context, R.style.volume_dialog_theme)) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.volume_dialog) + dialogBinder.bind(this) + } + + /** + * NOTE: This will be called with ACTION_OUTSIDE MotionEvents for touches that occur outside of + * the touchable region of the volume dialog (as returned by [.onComputeInternalInsets]) even if + * those touches occurred within the bounds of the volume dialog. + */ + override fun onTouchEvent(event: MotionEvent): Boolean { + if (isShowing) { + if (event.action == MotionEvent.ACTION_OUTSIDE) { + visibilityInteractor.dismissDialog(Events.DISMISS_REASON_TOUCH_OUTSIDE) + return true + } + } + return false } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialogPlugin.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialogPlugin.kt index a2e81d942ae2..4b7a9782cc6b 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialogPlugin.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialogPlugin.kt @@ -18,12 +18,10 @@ package com.android.systemui.volume.dialog import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.plugins.VolumeDialog -import com.android.systemui.volume.dialog.dagger.VolumeDialogComponent import com.android.systemui.volume.dialog.dagger.VolumeDialogPluginComponent import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job -import kotlinx.coroutines.cancel import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch @@ -34,31 +32,17 @@ constructor( private val volumeDialogPluginComponentFactory: VolumeDialogPluginComponent.Factory, ) : VolumeDialog { - private var volumeDialogPluginComponent: VolumeDialogPluginComponent? = null private var job: Job? = null override fun init(windowType: Int, callback: VolumeDialog.Callback?) { job = applicationCoroutineScope.launch { coroutineScope { - volumeDialogPluginComponent = volumeDialogPluginComponentFactory.create(this) - } - } - } + val component = volumeDialogPluginComponentFactory.create(this) - private fun showDialog() { - val volumeDialogPluginComponent = - volumeDialogPluginComponent ?: error("Creating dialog before init was called") - volumeDialogPluginComponent.coroutineScope().launch { - coroutineScope { - val volumeDialogComponent: VolumeDialogComponent = - volumeDialogPluginComponent.volumeDialogComponentFactory().create(this) - with(volumeDialogComponent.volumeDialog()) { - setOnDismissListener { volumeDialogComponent.coroutineScope().cancel() } - show() + component.viewModel().activate() } } - } } override fun destroy() { diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/dagger/VolumeDialogPluginComponent.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/dagger/VolumeDialogPluginComponent.kt index 82612a79f6ce..4e0098ccdf99 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/dagger/VolumeDialogPluginComponent.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/dagger/VolumeDialogPluginComponent.kt @@ -19,6 +19,7 @@ package com.android.systemui.volume.dialog.dagger import com.android.systemui.volume.dialog.dagger.module.VolumeDialogPluginModule import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogPlugin import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogPluginScope +import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogPluginViewModel import dagger.BindsInstance import dagger.Subcomponent import kotlinx.coroutines.CoroutineScope @@ -31,15 +32,7 @@ import kotlinx.coroutines.CoroutineScope @Subcomponent(modules = [VolumeDialogPluginModule::class]) interface VolumeDialogPluginComponent { - /** - * Provides a coroutine scope to use inside [VolumeDialogPluginScope]. - * [com.android.systemui.volume.dialog.VolumeDialogPlugin] manages the lifecycle of this scope. - * It's cancelled when the dialog is disposed. This helps to free occupied resources when volume - * dialog is not shown. - */ - @VolumeDialogPlugin fun coroutineScope(): CoroutineScope - - fun volumeDialogComponentFactory(): VolumeDialogComponent.Factory + fun viewModel(): VolumeDialogPluginViewModel @Subcomponent.Factory interface Factory { diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogCallbacksInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogCallbacksInteractor.kt index ec7c6cee21ff..2e26fd6de410 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogCallbacksInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogCallbacksInteractor.kt @@ -20,7 +20,8 @@ import android.annotation.SuppressLint import android.os.Handler import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.plugins.VolumeDialogController -import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogPlugin +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogPluginScope import com.android.systemui.volume.dialog.domain.model.VolumeDialogEventModel import com.android.systemui.volume.dialog.domain.model.VolumeDialogStateModel import javax.inject.Inject @@ -40,12 +41,12 @@ private const val BUFFER_CAPACITY = 16 * * @see VolumeDialogController.Callbacks */ -@VolumeDialog +@VolumeDialogPluginScope class VolumeDialogCallbacksInteractor @Inject constructor( private val volumeDialogController: VolumeDialogController, - @VolumeDialog private val coroutineScope: CoroutineScope, + @VolumeDialogPlugin private val coroutineScope: CoroutineScope, @Background private val bgHandler: Handler, ) { diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogStateInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogStateInteractor.kt index dd511088cb06..4a709a44b42f 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogStateInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogStateInteractor.kt @@ -17,7 +17,8 @@ package com.android.systemui.volume.dialog.domain.interactor import com.android.systemui.plugins.VolumeDialogController -import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogPlugin +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogPluginScope import com.android.systemui.volume.dialog.domain.model.VolumeDialogEventModel import com.android.systemui.volume.dialog.domain.model.VolumeDialogStateModel import javax.inject.Inject @@ -35,13 +36,13 @@ import kotlinx.coroutines.flow.stateIn * * @see [VolumeDialogController] */ -@VolumeDialog +@VolumeDialogPluginScope class VolumeDialogStateInteractor @Inject constructor( volumeDialogCallbacksInteractor: VolumeDialogCallbacksInteractor, private val volumeDialogController: VolumeDialogController, - @VolumeDialog private val coroutineScope: CoroutineScope, + @VolumeDialogPlugin private val coroutineScope: CoroutineScope, ) { val volumeDialogState: Flow<VolumeDialogStateModel> = diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractor.kt new file mode 100644 index 000000000000..f7d6d90ef6f0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractor.kt @@ -0,0 +1,102 @@ +/* + * 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.dialog.domain.interactor + +import android.annotation.SuppressLint +import com.android.systemui.volume.Events +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogPlugin +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogPluginScope +import com.android.systemui.volume.dialog.domain.model.VolumeDialogEventModel +import com.android.systemui.volume.dialog.domain.model.VolumeDialogVisibilityModel +import javax.inject.Inject +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.mapLatest +import kotlinx.coroutines.flow.merge +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.update + +private val MAX_DIALOG_SHOW_TIME: Duration = 3.seconds + +/** + * Handles Volume Dialog visibility state. It might change from several sources: + * - [com.android.systemui.plugins.VolumeDialogController] requests visibility change; + * - it might be dismissed by the inactivity timeout; + * - it can be dismissed by the user; + */ +@OptIn(ExperimentalCoroutinesApi::class) +@VolumeDialogPluginScope +class VolumeDialogVisibilityInteractor +@Inject +constructor( + @VolumeDialogPlugin coroutineScope: CoroutineScope, + callbacksInteractor: VolumeDialogCallbacksInteractor, +) { + + @SuppressLint("SharedFlowCreation") + private val mutableDismissDialogEvents = MutableSharedFlow<Unit>() + private val mutableDialogVisibility = + MutableStateFlow<VolumeDialogVisibilityModel>(VolumeDialogVisibilityModel.Invisible) + + val dialogVisibility: Flow<VolumeDialogVisibilityModel> = mutableDialogVisibility.asStateFlow() + + init { + merge( + mutableDismissDialogEvents.mapLatest { + delay(MAX_DIALOG_SHOW_TIME) + VolumeDialogEventModel.DismissRequested(Events.DISMISS_REASON_TIMEOUT) + }, + callbacksInteractor.event, + ) + .onEach { event -> + VolumeDialogVisibilityModel.fromEvent(event)?.let { model -> + mutableDialogVisibility.value = model + if (model is VolumeDialogVisibilityModel.Visible) { + resetDismissTimeout() + } + } + } + .launchIn(coroutineScope) + } + + /** + * Dismisses the dialog with a given [reason]. The new state will be emitted in the + * [dialogVisibility]. + */ + fun dismissDialog(reason: Int) { + mutableDialogVisibility.update { + if (it is VolumeDialogVisibilityModel.Dismissed) { + it + } else { + VolumeDialogVisibilityModel.Dismissed(reason) + } + } + } + + /** Resets current dialog timeout. */ + suspend fun resetDismissTimeout() { + mutableDismissDialogEvents.emit(Unit) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/model/VolumeDialogVisibilityModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/model/VolumeDialogVisibilityModel.kt new file mode 100644 index 000000000000..646445d33f51 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/model/VolumeDialogVisibilityModel.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.dialog.domain.model + +/** Models current Volume Dialog visibility state. */ +sealed interface VolumeDialogVisibilityModel { + + /** Dialog is currently visible. */ + data class Visible(val reason: Int, val keyguardLocked: Boolean, val lockTaskModeState: Int) : + VolumeDialogVisibilityModel + + /** Dialog has never been shown. So it's just invisible. */ + interface Invisible : VolumeDialogVisibilityModel { + companion object : Invisible + } + + /** Dialog has been shown and then dismissed. */ + data class Dismissed(val reason: Int) : Invisible + + companion object { + + /** + * Creates [VolumeDialogVisibilityModel] from appropriate events and returns null otherwise. + */ + fun fromEvent(event: VolumeDialogEventModel): VolumeDialogVisibilityModel? { + return when (event) { + is VolumeDialogEventModel.DismissRequested -> Dismissed(event.reason) + is VolumeDialogEventModel.ShowRequested -> + Visible(event.reason, event.keyguardLocked, event.lockTaskModeState) + else -> null + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/domain/VolumeDialogSettingsButtonInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/domain/VolumeDialogSettingsButtonInteractor.kt new file mode 100644 index 000000000000..db196347d4a9 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/domain/VolumeDialogSettingsButtonInteractor.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.volume.dialog.settings.domain + +import android.app.ActivityManager +import com.android.app.tracing.coroutines.flow.map +import com.android.systemui.statusbar.policy.DeviceProvisionedController +import com.android.systemui.volume.Events +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope +import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogVisibilityInteractor +import com.android.systemui.volume.dialog.domain.model.VolumeDialogVisibilityModel +import com.android.systemui.volume.panel.domain.interactor.VolumePanelGlobalStateInteractor +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.filterIsInstance +import kotlinx.coroutines.flow.stateIn + +@VolumeDialogScope +class VolumeDialogSettingsButtonInteractor +@Inject +constructor( + @VolumeDialog private val coroutineScope: CoroutineScope, + private val deviceProvisionedController: DeviceProvisionedController, + private val volumePanelGlobalStateInteractor: VolumePanelGlobalStateInteractor, + private val visibilityInteractor: VolumeDialogVisibilityInteractor, +) { + + val isVisible: StateFlow<Boolean> = + visibilityInteractor.dialogVisibility + .filterIsInstance(VolumeDialogVisibilityModel.Visible::class) + .map { model -> + deviceProvisionedController.isCurrentUserSetup() && + model.lockTaskModeState == ActivityManager.LOCK_TASK_MODE_NONE + } + .stateIn(coroutineScope, SharingStarted.Eagerly, false) + + fun onButtonClicked() { + volumePanelGlobalStateInteractor.setVisible(true) + visibilityInteractor.dismissDialog(Events.DISMISS_REASON_SETTINGS_CLICKED) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/binder/VolumeDialogSettingsButtonViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/binder/VolumeDialogSettingsButtonViewBinder.kt new file mode 100644 index 000000000000..ba08876609ae --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/binder/VolumeDialogSettingsButtonViewBinder.kt @@ -0,0 +1,54 @@ +/* + * 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.dialog.settings.ui.binder + +import android.view.View +import com.android.systemui.lifecycle.WindowLifecycleState +import com.android.systemui.lifecycle.repeatWhenAttached +import com.android.systemui.lifecycle.setSnapshotBinding +import com.android.systemui.lifecycle.viewModel +import com.android.systemui.res.R +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope +import com.android.systemui.volume.dialog.settings.ui.viewmodel.VolumeDialogSettingsButtonViewModel +import javax.inject.Inject +import kotlinx.coroutines.awaitCancellation + +@VolumeDialogScope +class VolumeDialogSettingsButtonViewBinder +@Inject +constructor(private val viewModelFactory: VolumeDialogSettingsButtonViewModel.Factory) { + + fun bind(view: View) { + with(view) { + val button = requireViewById<View>(R.id.settings) + repeatWhenAttached { + viewModel( + traceName = "VolumeDialogViewBinder", + minWindowLifecycleState = WindowLifecycleState.ATTACHED, + factory = { viewModelFactory.create() }, + ) { viewModel -> + setSnapshotBinding { + visibility = if (viewModel.isVisible) View.VISIBLE else View.GONE + button.setOnClickListener { viewModel.onButtonClicked() } + } + + awaitCancellation() + } + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/viewmodel/VolumeDialogSettingsButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/viewmodel/VolumeDialogSettingsButtonViewModel.kt new file mode 100644 index 000000000000..2acc33b79656 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/viewmodel/VolumeDialogSettingsButtonViewModel.kt @@ -0,0 +1,49 @@ +/* + * 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.dialog.settings.ui.viewmodel + +import androidx.compose.runtime.getValue +import com.android.systemui.lifecycle.ExclusiveActivatable +import com.android.systemui.lifecycle.Hydrator +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope +import com.android.systemui.volume.dialog.settings.domain.VolumeDialogSettingsButtonInteractor +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +class VolumeDialogSettingsButtonViewModel +@AssistedInject +constructor(private val interactor: VolumeDialogSettingsButtonInteractor) : ExclusiveActivatable() { + + private val hydrator = Hydrator("VolumeDialog_settings_button") + + val isVisible by hydrator.hydratedStateOf("isVisible", interactor.isVisible) + + override suspend fun onActivated(): Nothing { + hydrator.activate() + } + + fun onButtonClicked() { + interactor.onButtonClicked() + } + + @VolumeDialogScope + @AssistedFactory + interface Factory { + + fun create(): VolumeDialogSettingsButtonViewModel + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/shared/VolumeDialogLogger.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/shared/VolumeDialogLogger.kt new file mode 100644 index 000000000000..59c38c019823 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/shared/VolumeDialogLogger.kt @@ -0,0 +1,46 @@ +/* + * 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.dialog.shared + +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.core.LogLevel +import com.android.systemui.log.dagger.VolumeLog +import com.android.systemui.volume.Events +import javax.inject.Inject + +private const val TAG = "SysUI_VolumeDialog" + +/** Logs events related to the Volume Panel. */ +class VolumeDialogLogger @Inject constructor(@VolumeLog private val logBuffer: LogBuffer) { + + fun onShow(reason: Int) { + logBuffer.log( + TAG, + LogLevel.DEBUG, + { int1 = reason }, + { "Show: ${Events.SHOW_REASONS[int1]}" }, + ) + } + + fun onDismiss(reason: Int) { + logBuffer.log( + TAG, + LogLevel.DEBUG, + { int1 = reason }, + { "Dismiss: ${Events.DISMISS_REASONS[int1]}" }, + ) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogBinder.kt new file mode 100644 index 000000000000..9c88303106ae --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogBinder.kt @@ -0,0 +1,82 @@ +/* + * 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.dialog.ui.binder + +import android.app.Dialog +import android.graphics.Color +import android.graphics.PixelFormat +import android.graphics.drawable.ColorDrawable +import android.view.ViewGroup +import android.view.Window +import android.view.WindowManager +import com.android.systemui.res.R +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope +import com.android.systemui.volume.dialog.settings.ui.binder.VolumeDialogSettingsButtonViewBinder +import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogGravityViewModel +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach + +@VolumeDialogScope +class VolumeDialogBinder +@Inject +constructor( + @VolumeDialog private val coroutineScope: CoroutineScope, + private val volumeDialogViewBinder: VolumeDialogViewBinder, + private val settingsButtonViewBinder: VolumeDialogSettingsButtonViewBinder, + private val gravityViewModel: VolumeDialogGravityViewModel, +) { + + fun bind(dialog: Dialog) { + with(dialog) { + setupWindow(window!!) + dialog.setContentView(R.layout.volume_dialog) + + settingsButtonViewBinder.bind(dialog.requireViewById(R.id.settings_container)) + volumeDialogViewBinder.bind(dialog.requireViewById(R.id.volume_dialog_container)) + } + } + + /** Configures [Window] for the [Dialog]. */ + private fun setupWindow(window: Window) = + with(window) { + clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) + addFlags( + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or + WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or + WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED + ) + addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY) + + requestFeature(Window.FEATURE_NO_TITLE) + setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY) + setWindowAnimations(-1) + setFormat(PixelFormat.TRANSLUCENT) + + attributes = + attributes.apply { + title = "VolumeDialog" // Not the same as Window#setTitle + } + setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + + gravityViewModel.dialogGravity.onEach { window.setGravity(it) }.launchIn(coroutineScope) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt index 700225d521c8..600d17603964 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt @@ -21,15 +21,17 @@ import com.android.systemui.lifecycle.WindowLifecycleState import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.lifecycle.setSnapshotBinding import com.android.systemui.lifecycle.viewModel +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogViewModel import javax.inject.Inject import kotlinx.coroutines.awaitCancellation +@VolumeDialogScope class VolumeDialogViewBinder @Inject constructor(private val volumeDialogViewModelFactory: VolumeDialogViewModel.Factory) { - suspend fun bind(view: View) { + fun bind(view: View) { view.repeatWhenAttached { view.viewModel( traceName = "VolumeDialogViewBinder", diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogGravityViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogGravityViewModel.kt new file mode 100644 index 000000000000..df6523c9d750 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogGravityViewModel.kt @@ -0,0 +1,92 @@ +/* + * 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.dialog.ui.viewmodel + +import android.content.Context +import android.content.res.Configuration +import android.view.Gravity +import androidx.annotation.GravityInt +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.UiBackground +import com.android.systemui.res.R +import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.statusbar.policy.DevicePostureController +import com.android.systemui.statusbar.policy.devicePosture +import com.android.systemui.statusbar.policy.onConfigChanged +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope +import javax.inject.Inject +import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.withContext + +@VolumeDialogScope +class VolumeDialogGravityViewModel +@Inject +constructor( + @Application private val context: Context, + @VolumeDialog private val coroutineScope: CoroutineScope, + @UiBackground private val uiBackgroundCoroutineContext: CoroutineContext, + configurationController: ConfigurationController, + private val devicePostureController: DevicePostureController, +) { + + @GravityInt private var originalGravity: Int = context.getAbsoluteGravity() + + val dialogGravity: Flow<Int> = + combine( + devicePostureController.devicePosture(), + configurationController.onConfigChanged.onEach { onConfigurationChanged() }, + ) { devicePosture, configuration -> + context.calculateGravity(devicePosture, configuration) + } + .stateIn( + scope = coroutineScope, + started = SharingStarted.Eagerly, + context.calculateGravity(), + ) + + private suspend fun onConfigurationChanged() { + withContext(uiBackgroundCoroutineContext) { originalGravity = context.getAbsoluteGravity() } + } + + @GravityInt + private fun Context.calculateGravity( + devicePosture: Int = devicePostureController.devicePosture, + config: Configuration = resources.configuration, + ): Int { + val isLandscape = config.orientation == Configuration.ORIENTATION_LANDSCAPE + val isHalfOpen = devicePosture == DevicePostureController.DEVICE_POSTURE_HALF_OPENED + val gravity = + if (isLandscape && isHalfOpen) { + originalGravity or Gravity.TOP + } else { + originalGravity + } + return getAbsoluteGravity(gravity) + } +} + +@GravityInt +private fun Context.getAbsoluteGravity( + gravity: Int = resources.getInteger(R.integer.volume_dialog_gravity) +): Int = with(resources) { Gravity.getAbsoluteGravity(gravity, configuration.layoutDirection) } diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogPluginViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogPluginViewModel.kt new file mode 100644 index 000000000000..8aa0d09157ad --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogPluginViewModel.kt @@ -0,0 +1,92 @@ +/* + * 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.dialog.ui.viewmodel + +import android.app.Dialog +import com.android.systemui.lifecycle.ExclusiveActivatable +import com.android.systemui.plugins.VolumeDialogController +import com.android.systemui.volume.Events +import com.android.systemui.volume.dialog.dagger.VolumeDialogComponent +import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogPluginScope +import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogVisibilityInteractor +import com.android.systemui.volume.dialog.domain.model.VolumeDialogVisibilityModel +import com.android.systemui.volume.dialog.shared.VolumeDialogLogger +import javax.inject.Inject +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.cancel +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.mapLatest +import kotlinx.coroutines.launch +import kotlinx.coroutines.suspendCancellableCoroutine + +@OptIn(ExperimentalCoroutinesApi::class) +@VolumeDialogPluginScope +class VolumeDialogPluginViewModel +@Inject +constructor( + private val componentFactory: VolumeDialogComponent.Factory, + private val dialogVisibilityInteractor: VolumeDialogVisibilityInteractor, + private val controller: VolumeDialogController, + private val logger: VolumeDialogLogger, +) : ExclusiveActivatable() { + + override suspend fun onActivated(): Nothing { + coroutineScope { + dialogVisibilityInteractor.dialogVisibility + .mapLatest { visibilityModel -> + with(visibilityModel) { + if (this is VolumeDialogVisibilityModel.Visible) { + showDialog(reason, keyguardLocked) + } + if (this is VolumeDialogVisibilityModel.Dismissed) { + Events.writeEvent(Events.EVENT_DISMISS_DIALOG, reason) + logger.onDismiss(reason) + } + } + } + .launchIn(this) + } + awaitCancellation() + } + + suspend fun showDialog(reason: Int, keyguardLocked: Boolean): Unit = coroutineScope { + logger.onShow(reason) + + controller.notifyVisible(true) + + val volumeDialogComponent: VolumeDialogComponent = componentFactory.create(this) + val dialog = + volumeDialogComponent.volumeDialog().apply { + setOnDismissListener { + volumeDialogComponent.coroutineScope().cancel() + dialogVisibilityInteractor.dismissDialog(Events.DISMISS_REASON_UNKNOWN) + } + } + launch { dialog.awaitShow() } + + Events.writeEvent(Events.EVENT_SHOW_DIALOG, reason, keyguardLocked) + } +} + +/** Shows [Dialog] until suspend function is cancelled. */ +private suspend fun Dialog.awaitShow() = + suspendCancellableCoroutine<Unit> { + show() + it.invokeOnCancellation { dismiss() } + } diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt index f9e91aee4922..30c8c15387eb 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt @@ -19,11 +19,12 @@ package com.android.systemui.volume.dialog.ui.viewmodel import com.android.systemui.lifecycle.ExclusiveActivatable import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import kotlinx.coroutines.awaitCancellation class VolumeDialogViewModel @AssistedInject constructor() : ExclusiveActivatable() { override suspend fun onActivated(): Nothing { - TODO("Not yet implemented") + awaitCancellation() } @AssistedFactory diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index 5f6ad9205ec7..02d0b577feb1 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -61,7 +61,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.kotlin.JavaAdapter; import com.android.wm.shell.desktopmode.DesktopMode; -import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.onehanded.OneHandedEventCallback; import com.android.wm.shell.onehanded.OneHandedTransitionCallback; @@ -393,7 +393,7 @@ public final class WMShell implements void initDesktopMode(DesktopMode desktopMode) { desktopMode.addVisibleTasksListener( - new DesktopModeTaskRepository.VisibleTasksListener() { + new DesktopRepository.VisibleTasksListener() { @Override public void onTasksVisibilityChanged(int displayId, int visibleTasksCount) { if (displayId == Display.DEFAULT_DISPLAY) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java index 8075d117a58a..6061063db903 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java @@ -19,6 +19,7 @@ package com.android.systemui.clipboardoverlay; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static com.android.systemui.Flags.FLAG_CLIPBOARD_SHARED_TRANSITIONS; +import static com.android.systemui.Flags.FLAG_CLIPBOARD_USE_DESCRIPTION_MIMETYPE; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_SHOWN; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISS_TAPPED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_EXPANDED_FROM_MINIMIZED; @@ -166,6 +167,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { } @Test + @DisableFlags(FLAG_CLIPBOARD_USE_DESCRIPTION_MIMETYPE) public void test_setClipData_invalidImageData_legacy() { initController(); @@ -238,6 +240,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { } @Test + @DisableFlags(FLAG_CLIPBOARD_USE_DESCRIPTION_MIMETYPE) public void test_setClipData_invalidImageData() { initController(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt index ca518f9bc5d7..c7da03dbbf30 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.qs.tiles import android.os.Handler +import android.os.Looper import android.service.quicksettings.Tile import android.testing.TestableLooper import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -31,9 +32,10 @@ import com.android.systemui.qs.QSHost import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor +import com.android.systemui.recordissue.IssueRecordingServiceConnection import com.android.systemui.recordissue.IssueRecordingState import com.android.systemui.recordissue.RecordIssueDialogDelegate -import com.android.systemui.recordissue.TraceurMessageSender +import com.android.systemui.recordissue.TraceurConnection import com.android.systemui.res.R import com.android.systemui.screenrecord.RecordingController import com.android.systemui.settings.UserContextProvider @@ -75,13 +77,14 @@ class RecordIssueTileTest : SysuiTestCase() { @Mock private lateinit var panelInteractor: PanelInteractor @Mock private lateinit var userContextProvider: UserContextProvider @Mock private lateinit var issueRecordingState: IssueRecordingState - @Mock private lateinit var traceurMessageSender: TraceurMessageSender @Mock private lateinit var delegateFactory: RecordIssueDialogDelegate.Factory @Mock private lateinit var dialogDelegate: RecordIssueDialogDelegate @Mock private lateinit var dialog: SystemUIDialog private lateinit var testableLooper: TestableLooper private lateinit var tile: RecordIssueTile + private lateinit var irsConnProvider: IssueRecordingServiceConnection.Provider + private lateinit var traceurConnProvider: TraceurConnection.Provider @Before fun setUp() { @@ -90,6 +93,10 @@ class RecordIssueTileTest : SysuiTestCase() { whenever(delegateFactory.create(any())).thenReturn(dialogDelegate) whenever(dialogDelegate.createDialog()).thenReturn(dialog) + irsConnProvider = IssueRecordingServiceConnection.Provider(userContextProvider) + traceurConnProvider = + TraceurConnection.Provider(userContextProvider, Looper.getMainLooper()) + testableLooper = TestableLooper.get(this) tile = RecordIssueTile( @@ -107,7 +114,8 @@ class RecordIssueTileTest : SysuiTestCase() { dialogLauncherAnimator, panelInteractor, userContextProvider, - traceurMessageSender, + irsConnProvider, + traceurConnProvider, Executors.newSingleThreadExecutor(), issueRecordingState, delegateFactory, @@ -169,7 +177,7 @@ class RecordIssueTileTest : SysuiTestCase() { .executeWhenUnlocked( isA(ActivityStarter.OnDismissAction::class.java), eq(false), - eq(true) + eq(true), ) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java index 2f8f45cb0197..0b9c06f2dbe2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java @@ -901,7 +901,7 @@ public class InternetDialogDelegateControllerTest extends SysuiTestCase { // 1st time is onStart(), 2nd time is getActiveAutoSwitchNonDdsSubId() verify(mTelephonyManager, times(2)).registerTelephonyCallback(any(), any()); - assertThat(mInternetDialogController.mSubIdTelephonyCallbackMap.size() == 2); + assertThat(mInternetDialogController.mSubIdTelephonyCallbackMap.size()).isEqualTo(2); // Adds non DDS subId again doReturn(SUB_ID2).when(info).getSubscriptionId(); @@ -912,7 +912,7 @@ public class InternetDialogDelegateControllerTest extends SysuiTestCase { // Does not add due to cached subInfo in mSubIdTelephonyCallbackMap. verify(mTelephonyManager, times(2)).registerTelephonyCallback(any(), any()); - assertThat(mInternetDialogController.mSubIdTelephonyCallbackMap.size() == 2); + assertThat(mInternetDialogController.mSubIdTelephonyCallbackMap.size()).isEqualTo(2); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt index 148a2e56f2a5..52266eee24e8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt @@ -29,7 +29,6 @@ import com.google.common.truth.Truth.assertThat import java.util.UUID import kotlin.test.Test import kotlinx.coroutines.test.runTest -import org.junit.Before import org.junit.runner.RunWith import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.kotlin.any @@ -47,16 +46,11 @@ class DefaultScreenshotActionsProviderTest : SysuiTestCase() { private val uiEventLogger = mock<UiEventLogger>() private val actionsCallback = mock<ScreenshotActionsController.ActionsCallback>() - private val request = ScreenshotData.forTesting() + private val request = ScreenshotData.forTesting(userHandle = UserHandle.OWNER) private val validResult = ScreenshotSavedResult(Uri.EMPTY, Process.myUserHandle(), 0) private lateinit var actionsProvider: ScreenshotActionsProvider - @Before - fun setUp() { - request.userHandle = UserHandle.OWNER - } - @Test fun previewActionAccessed_beforeScreenshotCompleted_doesNothing() { actionsProvider = createActionsProvider() diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt index 15da77dfe33d..4000d6cde2fd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt @@ -47,7 +47,7 @@ class MessageContainerControllerTest : SysuiTestCase() { lateinit var screenshotView: ViewGroup val userHandle = UserHandle.of(5) - val screenshotData = ScreenshotData.forTesting() + val screenshotData = ScreenshotData.forTesting(userHandle = userHandle) val appName = "app name" lateinit var workProfileData: WorkProfileMessageController.WorkProfileFirstRunData @@ -61,7 +61,7 @@ class MessageContainerControllerTest : SysuiTestCase() { workProfileMessageController, profileMessageController, screenshotDetectionController, - TestScope(UnconfinedTestDispatcher()) + TestScope(UnconfinedTestDispatcher()), ) screenshotView = ConstraintLayout(mContext) workProfileData = WorkProfileMessageController.WorkProfileFirstRunData(appName, icon) @@ -83,8 +83,6 @@ class MessageContainerControllerTest : SysuiTestCase() { container.addView(detectionNoticeView) messageContainer.setView(screenshotView) - - screenshotData.userHandle = userHandle } @Test @@ -92,7 +90,7 @@ class MessageContainerControllerTest : SysuiTestCase() { val profileData = ProfileMessageController.ProfileFirstRunData( LabeledIcon(appName, icon), - ProfileMessageController.FirstRunProfile.PRIVATE + ProfileMessageController.FirstRunProfile.PRIVATE, ) whenever(profileMessageController.onScreenshotTaken(eq(userHandle))).thenReturn(profileData) messageContainer.onScreenshotTaken(screenshotData) diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDataTest.kt index 3ed09770b189..1d74e8b3002c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDataTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDataTest.kt @@ -17,12 +17,12 @@ package com.android.systemui.screenshot import android.content.ComponentName -import androidx.test.ext.junit.runners.AndroidJUnit4 import android.graphics.Insets import android.graphics.Rect import android.os.UserHandle import android.view.Display import android.view.WindowManager +import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.internal.util.ScreenshotRequest import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -71,15 +71,6 @@ class ScreenshotDataTest { } @Test - fun testNegativeUserId() { - val request = ScreenshotRequest.Builder(type, source).setUserId(-1).build() - - val data = ScreenshotData.fromRequest(request) - - assertThat(data.userHandle).isNull() - } - - @Test fun testPackageNameAsString() { val request = ScreenshotRequest.Builder(type, source).setTopComponent(component).build() diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt index 1538c72f8df8..c50702868025 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt @@ -61,8 +61,8 @@ class ScreenshotDetectionControllerTest { @Test fun testMaybeNotifyOfScreenshot_ignoresOverview() { - val data = ScreenshotData.forTesting() - data.source = WindowManager.ScreenshotSource.SCREENSHOT_OVERVIEW + val data = + ScreenshotData.forTesting(source = WindowManager.ScreenshotSource.SCREENSHOT_OVERVIEW) val list = controller.maybeNotifyOfScreenshot(data) @@ -72,8 +72,8 @@ class ScreenshotDetectionControllerTest { @Test fun testMaybeNotifyOfScreenshot_emptySet() { - val data = ScreenshotData.forTesting() - data.source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD + val data = + ScreenshotData.forTesting(source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD) whenever(windowManager.notifyScreenshotListeners(eq(Display.DEFAULT_DISPLAY))) .thenReturn(listOf()) @@ -85,8 +85,8 @@ class ScreenshotDetectionControllerTest { @Test fun testMaybeNotifyOfScreenshot_oneApp() { - val data = ScreenshotData.forTesting() - data.source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD + val data = + ScreenshotData.forTesting(source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD) val component = ComponentName("package1", "class1") val appName = "app name" @@ -95,7 +95,7 @@ class ScreenshotDetectionControllerTest { whenever( packageManager.getActivityInfo( eq(component), - any(PackageManager.ComponentInfoFlags::class.java) + any(PackageManager.ComponentInfoFlags::class.java), ) ) .thenReturn(activityInfo) @@ -112,8 +112,8 @@ class ScreenshotDetectionControllerTest { @Test fun testMaybeNotifyOfScreenshot_multipleApps() { - val data = ScreenshotData.forTesting() - data.source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD + val data = + ScreenshotData.forTesting(source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD) val component1 = ComponentName("package1", "class1") val component2 = ComponentName("package2", "class2") @@ -129,21 +129,21 @@ class ScreenshotDetectionControllerTest { whenever( packageManager.getActivityInfo( eq(component1), - any(PackageManager.ComponentInfoFlags::class.java) + any(PackageManager.ComponentInfoFlags::class.java), ) ) .thenReturn(activityInfo1) whenever( packageManager.getActivityInfo( eq(component2), - any(PackageManager.ComponentInfoFlags::class.java) + any(PackageManager.ComponentInfoFlags::class.java), ) ) .thenReturn(activityInfo2) whenever( packageManager.getActivityInfo( eq(component3), - any(PackageManager.ComponentInfoFlags::class.java) + any(PackageManager.ComponentInfoFlags::class.java), ) ) .thenReturn(activityInfo3) @@ -165,11 +165,13 @@ class ScreenshotDetectionControllerTest { private fun includesFlagBits(@PackageManager.ComponentInfoFlagsBits mask: Int) = ComponentInfoFlagMatcher(mask, mask) + private fun excludesFlagBits(@PackageManager.ComponentInfoFlagsBits mask: Int) = ComponentInfoFlagMatcher(mask, 0) private class ComponentInfoFlagMatcher( - @PackageManager.ComponentInfoFlagsBits val mask: Int, val value: Int + @PackageManager.ComponentInfoFlagsBits val mask: Int, + val value: Int, ) : ArgumentMatcher<PackageManager.ComponentInfoFlags> { override fun matches(flags: PackageManager.ComponentInfoFlags?): Boolean { return flags != null && (mask.toLong() and flags.value) == value.toLong() @@ -182,26 +184,28 @@ class ScreenshotDetectionControllerTest { @Test fun testMaybeNotifyOfScreenshot_disabledApp() { - val data = ScreenshotData.forTesting() - data.source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD + val data = + ScreenshotData.forTesting(source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD) val component = ComponentName("package1", "class1") val appName = "app name" val activityInfo = mock(ActivityInfo::class.java) whenever( - packageManager.getActivityInfo( - eq(component), - argThat(includesFlagBits(MATCH_DISABLED_COMPONENTS or MATCH_ANY_USER)) + packageManager.getActivityInfo( + eq(component), + argThat(includesFlagBits(MATCH_DISABLED_COMPONENTS or MATCH_ANY_USER)), + ) ) - ).thenReturn(activityInfo) + .thenReturn(activityInfo) whenever( - packageManager.getActivityInfo( - eq(component), - argThat(excludesFlagBits(MATCH_DISABLED_COMPONENTS)) + packageManager.getActivityInfo( + eq(component), + argThat(excludesFlagBits(MATCH_DISABLED_COMPONENTS)), + ) ) - ).thenThrow(PackageManager.NameNotFoundException::class.java) + .thenThrow(PackageManager.NameNotFoundException::class.java) whenever(windowManager.notifyScreenshotListeners(eq(Display.DEFAULT_DISPLAY))) .thenReturn(listOf(component)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt index 0bea56007a01..27e9f07af168 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotExecutorTest.kt @@ -20,6 +20,7 @@ import com.android.internal.util.ScreenshotRequest import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.display.data.repository.FakeDisplayRepository +import com.android.systemui.display.data.repository.FakeFocusedDisplayRepository import com.android.systemui.display.data.repository.display import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq @@ -58,6 +59,7 @@ class TakeScreenshotExecutorTest : SysuiTestCase() { private val testScope = TestScope(UnconfinedTestDispatcher()) private val eventLogger = UiEventLoggerFake() private val headlessHandler = mock<HeadlessScreenshotHandler>() + private val focusedDisplayRepository = FakeFocusedDisplayRepository() private val screenshotExecutor = TakeScreenshotExecutorImpl( @@ -68,6 +70,7 @@ class TakeScreenshotExecutorTest : SysuiTestCase() { eventLogger, notificationControllerFactory, headlessHandler, + focusedDisplayRepository, ) @Before @@ -309,6 +312,59 @@ class TakeScreenshotExecutorTest : SysuiTestCase() { } @Test + @EnableFlags(Flags.FLAG_SCREENSHOT_MULTIDISPLAY_FOCUS_CHANGE) + fun executeScreenshots_keyOther_usesFocusedDisplay() = + testScope.runTest { + val displayId = 1 + setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = displayId)) + val onSaved = { _: Uri? -> } + focusedDisplayRepository.emit(displayId) + + screenshotExecutor.executeScreenshots( + createScreenshotRequest( + source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER + ), + onSaved, + callback, + ) + + val dataCaptor = ArgumentCaptor<ScreenshotData>() + + verify(controller).handleScreenshot(dataCaptor.capture(), any(), any()) + + assertThat(dataCaptor.value.displayId).isEqualTo(displayId) + + screenshotExecutor.onDestroy() + } + + @Test + @EnableFlags(Flags.FLAG_SCREENSHOT_MULTIDISPLAY_FOCUS_CHANGE) + fun executeScreenshots_keyOtherInvalidDisplay_usesDefault() = + testScope.runTest { + setDisplays( + display(TYPE_INTERNAL, id = Display.DEFAULT_DISPLAY), + display(TYPE_EXTERNAL, id = 1), + ) + focusedDisplayRepository.emit(5) // invalid display + val onSaved = { _: Uri? -> } + screenshotExecutor.executeScreenshots( + createScreenshotRequest( + source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER + ), + onSaved, + callback, + ) + + val dataCaptor = ArgumentCaptor<ScreenshotData>() + + verify(controller).handleScreenshot(dataCaptor.capture(), any(), any()) + + assertThat(dataCaptor.value.displayId).isEqualTo(Display.DEFAULT_DISPLAY) + + screenshotExecutor.onDestroy() + } + + @Test fun onDestroy_propagatedToControllers() = testScope.runTest { setDisplays(display(TYPE_INTERNAL, id = 0), display(TYPE_EXTERNAL, id = 1)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PolicyRequestProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PolicyRequestProcessorTest.kt index bab9bbbfde4f..2fcacb9880dd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PolicyRequestProcessorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PolicyRequestProcessorTest.kt @@ -58,13 +58,13 @@ class PolicyRequestProcessorTest { ScreenshotData( TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD, - null, + UserHandle.CURRENT, topComponent = null, screenBounds = Rect(0, 0, 1, 1), taskId = -1, insets = Insets.NONE, bitmap = null, - displayId = DEFAULT_DISPLAY + displayId = DEFAULT_DISPLAY, ) /* Create a policy request processor with no capture policies */ @@ -75,7 +75,7 @@ class PolicyRequestProcessorTest { policies = emptyList(), defaultOwner = UserHandle.of(PERSONAL), defaultComponent = ComponentName("default", "Component"), - displayTasks = fullScreenWork + displayTasks = fullScreenWork, ) val result = runBlocking { requestProcessor.process(request) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java index f5a901963f05..0e9ef06aa1b9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java @@ -556,11 +556,13 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase { return null; }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class)); - // Dreaming->Lockscreen + // Any edge transition when(mKeyguardTransitionInteractor.transition(any())) .thenReturn(emptyFlow()); when(mKeyguardTransitionInteractor.transition(any(), any())) .thenReturn(emptyFlow()); + + // Dreaming->Lockscreen when(mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha()) .thenReturn(emptyFlow()); when(mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt())) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java index 98315d0ca3c9..83dbfa0682ad 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java @@ -95,6 +95,7 @@ import org.mockito.MockitoSession; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class NetworkControllerBaseTest extends SysuiTestCase { @@ -332,10 +333,15 @@ public class NetworkControllerBaseTest extends SysuiTestCase { } public void setConnectivityViaCallbackInNetworkControllerForVcn( - int networkType, boolean validated, boolean isConnected, VcnTransportInfo info) { + int networkType, + boolean validated, + boolean isConnected, + VcnTransportInfo info, + Network underlyingNetwork) { final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(mNetCapabilities); - builder.setTransportInfo(info); + builder.setTransportInfo(info) + .setUnderlyingNetworks(Collections.singletonList(underlyingNetwork)); setConnectivityCommon(builder, networkType, validated, isConnected); mDefaultCallbackInNetworkController.onCapabilitiesChanged( mock(Network.class), builder.build()); @@ -385,10 +391,15 @@ public class NetworkControllerBaseTest extends SysuiTestCase { } public void setConnectivityViaCallbackInWifiTrackerForVcn( - int networkType, boolean validated, boolean isConnected, VcnTransportInfo info) { + int networkType, + boolean validated, + boolean isConnected, + VcnTransportInfo info, + Network underlyingNetwork) { final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(mNetCapabilities); - builder.setTransportInfo(info); + builder.setTransportInfo(info) + .setUnderlyingNetworks(Collections.singletonList(underlyingNetwork)); setConnectivityCommon(builder, networkType, validated, isConnected); if (networkType == NetworkCapabilities.TRANSPORT_CELLULAR) { if (isConnected) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java index 6c80a97625a7..6febb91db992 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.connectivity; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static junit.framework.Assert.assertEquals; @@ -250,6 +251,17 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { assertEquals(testSsid, mNetworkController.mWifiSignalController.mCurrentState.ssid); } + private Network newWifiNetwork(WifiInfo wifiInfo) { + final Network network = mock(Network.class); + final NetworkCapabilities wifiCaps = + new NetworkCapabilities.Builder() + .addTransportType(TRANSPORT_WIFI) + .setTransportInfo(wifiInfo) + .build(); + when(mMockCm.getNetworkCapabilities(network)).thenReturn(wifiCaps); + return network; + } + @Test public void testVcnWithUnderlyingWifi() { String testSsid = "Test VCN SSID"; @@ -266,11 +278,19 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { setWifiLevelForVcn(testLevel); setConnectivityViaCallbackInNetworkControllerForVcn( - NetworkCapabilities.TRANSPORT_CELLULAR, true, true, mVcnTransportInfo); + NetworkCapabilities.TRANSPORT_CELLULAR, + true, + true, + mVcnTransportInfo, + newWifiNetwork(mWifiInfo)); verifyLastMobileDataIndicatorsForVcn(true, testLevel, TelephonyIcons.ICON_CWF, true); setConnectivityViaCallbackInNetworkControllerForVcn( - NetworkCapabilities.TRANSPORT_CELLULAR, false, true, mVcnTransportInfo); + NetworkCapabilities.TRANSPORT_CELLULAR, + false, + true, + mVcnTransportInfo, + newWifiNetwork(mWifiInfo)); verifyLastMobileDataIndicatorsForVcn(true, testLevel, TelephonyIcons.ICON_CWF, false); } } @@ -391,13 +411,15 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { } protected void setWifiLevelForVcn(int level) { - when(mVcnTransportInfo.getWifiInfo()).thenReturn(mWifiInfo); - when(mVcnTransportInfo.makeCopy(anyLong())).thenReturn(mVcnTransportInfo); when(mWifiInfo.getRssi()).thenReturn(calculateRssiForLevel(level)); when(mWifiInfo.isCarrierMerged()).thenReturn(true); when(mWifiInfo.getSubscriptionId()).thenReturn(1); setConnectivityViaCallbackInWifiTrackerForVcn( - NetworkCapabilities.TRANSPORT_CELLULAR, false, true, mVcnTransportInfo); + NetworkCapabilities.TRANSPORT_CELLULAR, + false, + true, + mVcnTransportInfo, + newWifiNetwork(mWifiInfo)); } private int calculateRssiForLevel(int level) { @@ -409,13 +431,15 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { } protected void setWifiStateForVcn(boolean connected, String ssid) { - when(mVcnTransportInfo.getWifiInfo()).thenReturn(mWifiInfo); - when(mVcnTransportInfo.makeCopy(anyLong())).thenReturn(mVcnTransportInfo); when(mWifiInfo.getSSID()).thenReturn(ssid); when(mWifiInfo.isCarrierMerged()).thenReturn(true); when(mWifiInfo.getSubscriptionId()).thenReturn(1); setConnectivityViaCallbackInWifiTrackerForVcn( - NetworkCapabilities.TRANSPORT_CELLULAR, false, connected, mVcnTransportInfo); + NetworkCapabilities.TRANSPORT_CELLULAR, + false, + connected, + mVcnTransportInfo, + newWifiNetwork(mWifiInfo)); } protected void verifyLastQsDataDirection(boolean in, boolean out) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt index 7d5278ed1601..d717fe4c1e04 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt @@ -48,7 +48,7 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { private val kosmos = testKosmos().apply { fakeKeyguardTransitionRepository = - FakeKeyguardTransitionRepository(initInLockscreen = false) + FakeKeyguardTransitionRepository(initInLockscreen = false, testScope = testScope) } private val testScope = kosmos.testScope private val faceAuthRepository by lazy { kosmos.fakeDeviceEntryFaceAuthRepository } @@ -146,9 +146,17 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test + fun activeRows_noRows_isEmpty() = + testScope.runTest { + val activeHeadsUpRows by collectLastValue(underTest.activeHeadsUpRowKeys) + + assertThat(activeHeadsUpRows).isEmpty() + } + + @Test fun pinnedRows_noRows_isEmpty() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) assertThat(pinnedHeadsUpRows).isEmpty() } @@ -156,7 +164,7 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { @Test fun pinnedRows_noPinnedRows_isEmpty() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) // WHEN no rows are pinned headsUpRepository.setNotifications( fakeHeadsUpRowRepository("key 0"), @@ -170,9 +178,27 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test + fun activeRows_noPinnedRows_containsAllRows() = + testScope.runTest { + val activeHeadsUpRows by collectLastValue(underTest.activeHeadsUpRowKeys) + // WHEN no rows are pinned + val rows = + arrayListOf( + fakeHeadsUpRowRepository("key 0"), + fakeHeadsUpRowRepository("key 1"), + fakeHeadsUpRowRepository("key 2"), + ) + headsUpRepository.setNotifications(rows) + runCurrent() + + // THEN all rows are present + assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) + } + + @Test fun pinnedRows_hasPinnedRows_containsPinnedRows() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) // WHEN some rows are pinned val rows = arrayListOf( @@ -188,9 +214,27 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test + fun pinnedRows_hasPinnedRows_containsAllRows() = + testScope.runTest { + val activeHeadsUpRows by collectLastValue(underTest.activeHeadsUpRowKeys) + // WHEN no rows are pinned + val rows = + arrayListOf( + fakeHeadsUpRowRepository("key 0", isPinned = true), + fakeHeadsUpRowRepository("key 1", isPinned = true), + fakeHeadsUpRowRepository("key 2"), + ) + headsUpRepository.setNotifications(rows) + runCurrent() + + // THEN all rows are present + assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) + } + + @Test fun pinnedRows_rowGetsPinned_containsPinnedRows() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) // GIVEN some rows are pinned val rows = arrayListOf( @@ -210,9 +254,34 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test + fun activeRows_rowGetsPinned_containsAllRows() = + testScope.runTest { + val activeHeadsUpRows by collectLastValue(underTest.activeHeadsUpRowKeys) + // GIVEN some rows are pinned + val rows = + arrayListOf( + fakeHeadsUpRowRepository("key 0", isPinned = true), + fakeHeadsUpRowRepository("key 1", isPinned = true), + fakeHeadsUpRowRepository("key 2"), + ) + headsUpRepository.setNotifications(rows) + runCurrent() + + // THEN all rows are present + assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) + + // WHEN all rows gets pinned + rows[2].isPinned.value = true + runCurrent() + + // THEN no change + assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) + } + + @Test fun pinnedRows_allRowsPinned_containsAllRows() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) // WHEN all rows are pinned val rows = arrayListOf( @@ -228,9 +297,27 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test + fun activeRows_allRowsPinned_containsAllRows() = + testScope.runTest { + val activeHeadsUpRows by collectLastValue(underTest.activeHeadsUpRowKeys) + // WHEN all rows are pinned + val rows = + arrayListOf( + fakeHeadsUpRowRepository("key 0", isPinned = true), + fakeHeadsUpRowRepository("key 1", isPinned = true), + fakeHeadsUpRowRepository("key 2", isPinned = true), + ) + headsUpRepository.setNotifications(rows) + runCurrent() + + // THEN no rows are filtered + assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) + } + + @Test fun pinnedRows_rowGetsUnPinned_containsPinnedRows() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) // GIVEN all rows are pinned val rows = arrayListOf( @@ -250,9 +337,31 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test + fun activeRows_rowGetsUnPinned_containsAllRows() = + testScope.runTest { + val activeHeadsUpRows by collectLastValue(underTest.activeHeadsUpRowKeys) + // GIVEN all rows are pinned + val rows = + arrayListOf( + fakeHeadsUpRowRepository("key 0", isPinned = true), + fakeHeadsUpRowRepository("key 1", isPinned = true), + fakeHeadsUpRowRepository("key 2", isPinned = true), + ) + headsUpRepository.setNotifications(rows) + runCurrent() + + // WHEN a row gets unpinned + rows[0].isPinned.value = false + runCurrent() + + // THEN all rows are still present + assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) + } + + @Test fun pinnedRows_rowGetsPinnedAndUnPinned_containsTheSameInstance() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) val rows = arrayListOf( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt index a099c9dc6442..48608ebd6de0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt @@ -35,9 +35,6 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.res.R import com.android.systemui.statusbar.notification.ConversationNotificationProcessor import com.android.systemui.statusbar.notification.collection.NotificationEntry -import com.android.systemui.statusbar.notification.row.ContentViewInflationResult.InflatedContentViewHolder -import com.android.systemui.statusbar.notification.row.ContentViewInflationResult.KeepExistingView -import com.android.systemui.statusbar.notification.row.ContentViewInflationResult.NullContentView import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.BindParams import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED @@ -51,33 +48,23 @@ import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedac import com.android.systemui.statusbar.notification.row.shared.NewRemoteViews import com.android.systemui.statusbar.notification.row.shared.NotificationContentModel import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor -import com.android.systemui.statusbar.notification.row.shared.RichOngoingContentModel -import com.android.systemui.statusbar.notification.row.shared.TimerContentModel import com.android.systemui.statusbar.policy.InflatedSmartReplyState import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder import com.android.systemui.statusbar.policy.SmartReplyStateInflater -import com.google.common.truth.Truth.assertThat import java.util.concurrent.CountDownLatch import java.util.concurrent.Executor import java.util.concurrent.TimeUnit -import kotlinx.coroutines.DisposableHandle import org.junit.Assert import org.junit.Before import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any -import org.mockito.kotlin.argThat -import org.mockito.kotlin.clearInvocations -import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq -import org.mockito.kotlin.inOrder import org.mockito.kotlin.mock -import org.mockito.kotlin.never import org.mockito.kotlin.spy import org.mockito.kotlin.times import org.mockito.kotlin.verify -import org.mockito.kotlin.verifyNoMoreInteractions import org.mockito.kotlin.whenever @SmallTest @@ -118,45 +105,6 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { } } - private var fakeRonContentModel: RichOngoingContentModel? = null - private val fakeRonExtractor = - object : RichOngoingNotificationContentExtractor { - override fun extractContentModel( - entry: NotificationEntry, - builder: Notification.Builder, - systemUIContext: Context, - packageContext: Context - ): RichOngoingContentModel? = fakeRonContentModel - } - - private var fakeContractedRonViewHolder: ContentViewInflationResult = NullContentView - private var fakeExpandedRonViewHolder: ContentViewInflationResult = NullContentView - private var fakeHeadsUpRonViewHolder: ContentViewInflationResult = NullContentView - private var fakeRonViewInflater = - spy( - object : RichOngoingNotificationViewInflater { - override fun inflateView( - contentModel: RichOngoingContentModel, - existingView: View?, - entry: NotificationEntry, - systemUiContext: Context, - parentView: ViewGroup, - viewType: RichOngoingNotificationViewType - ): ContentViewInflationResult = - when (viewType) { - RichOngoingNotificationViewType.Contracted -> fakeContractedRonViewHolder - RichOngoingNotificationViewType.Expanded -> fakeExpandedRonViewHolder - RichOngoingNotificationViewType.HeadsUp -> fakeHeadsUpRonViewHolder - } - - override fun canKeepView( - contentModel: RichOngoingContentModel, - existingView: View?, - viewType: RichOngoingNotificationViewType - ): Boolean = false - } - ) - @Before fun setUp() { allowTestableLooperAsMainThread() @@ -167,15 +115,12 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { .setContentText("Text") .setStyle(Notification.BigTextStyle().bigText("big text")) testHelper = NotificationTestHelper(mContext, mDependency) - testHelper.setDefaultInflationFlags(FLAG_CONTENT_VIEW_ALL) row = spy(testHelper.createRow(builder.build())) notificationInflater = NotificationRowContentBinderImpl( cache, mock(), mock<ConversationNotificationProcessor>(), - fakeRonExtractor, - fakeRonViewInflater, mock(), smartReplyStateInflater, layoutInflaterFactoryProvider, @@ -405,496 +350,6 @@ class NotificationRowContentBinderImplTest : SysuiTestCase() { } @Test - fun testRonModelRequiredForRonView() { - fakeRonContentModel = null - val contractedRonView = View(context) - val expandedRonView = View(context) - val headsUpRonView = View(context) - fakeContractedRonViewHolder = - InflatedContentViewHolder(view = contractedRonView, binder = mock()) - fakeExpandedRonViewHolder = - InflatedContentViewHolder(view = expandedRonView, binder = mock()) - fakeHeadsUpRonViewHolder = InflatedContentViewHolder(view = headsUpRonView, binder = mock()) - - // WHEN inflater inflates - val contentToInflate = - FLAG_CONTENT_VIEW_CONTRACTED or FLAG_CONTENT_VIEW_EXPANDED or FLAG_CONTENT_VIEW_HEADS_UP - inflateAndWait(notificationInflater, contentToInflate, row) - verifyNoMoreInteractions(fakeRonViewInflater) - } - - @Test - fun testRonModelCleansUpRemoteViews() { - val ronView = View(context) - - val entry = row.entry - - fakeRonContentModel = mock<TimerContentModel>() - fakeContractedRonViewHolder = - InflatedContentViewHolder(view = ronView, binder = mock<DeferredContentViewBinder>()) - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_CONTRACTED, row) - - // VERIFY - verify(cache).removeCachedView(eq(entry), eq(FLAG_CONTENT_VIEW_CONTRACTED)) - verify(cache).removeCachedView(eq(entry), eq(FLAG_CONTENT_VIEW_EXPANDED)) - verify(cache).removeCachedView(eq(entry), eq(FLAG_CONTENT_VIEW_HEADS_UP)) - } - - @Test - fun testRonModelCleansUpSmartReplies() { - val ronView = View(context) - - val privateLayout = spy(row.privateLayout) - - row.privateLayout = privateLayout - - fakeRonContentModel = mock<TimerContentModel>() - fakeContractedRonViewHolder = InflatedContentViewHolder(view = ronView, binder = mock()) - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_CONTRACTED, row) - - // VERIFY - verify(privateLayout).setExpandedInflatedSmartReplies(eq(null)) - verify(privateLayout).setHeadsUpInflatedSmartReplies(eq(null)) - } - - @Test - fun testRonModelTriggersInflationOfContractedRonView() { - val mockRonModel = mock<TimerContentModel>() - val ronView = View(context) - val mockBinder = mock<DeferredContentViewBinder>() - - val entry = row.entry - val privateLayout = row.privateLayout - - fakeRonContentModel = mockRonModel - fakeContractedRonViewHolder = InflatedContentViewHolder(view = ronView, binder = mockBinder) - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_CONTRACTED, row) - - // VERIFY that the inflater is invoked - verify(fakeRonViewInflater) - .inflateView( - eq(mockRonModel), - any(), - eq(entry), - any(), - eq(privateLayout), - eq(RichOngoingNotificationViewType.Contracted) - ) - assertThat(row.privateLayout.contractedChild).isSameInstanceAs(ronView) - verify(mockBinder).setupContentViewBinder() - } - - @Test - fun testRonModelTriggersInflationOfExpandedRonView() { - val mockRonModel = mock<TimerContentModel>() - val ronView = View(context) - val mockBinder = mock<DeferredContentViewBinder>() - - val entry = row.entry - val privateLayout = row.privateLayout - - fakeRonContentModel = mockRonModel - fakeExpandedRonViewHolder = InflatedContentViewHolder(view = ronView, binder = mockBinder) - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_EXPANDED, row) - - // VERIFY that the inflater is invoked - verify(fakeRonViewInflater) - .inflateView( - eq(mockRonModel), - any(), - eq(entry), - any(), - eq(privateLayout), - eq(RichOngoingNotificationViewType.Expanded) - ) - assertThat(row.privateLayout.expandedChild).isSameInstanceAs(ronView) - verify(mockBinder).setupContentViewBinder() - } - - @Test - fun testRonModelTriggersInflationOfHeadsUpRonView() { - val mockRonModel = mock<TimerContentModel>() - val ronView = View(context) - val mockBinder = mock<DeferredContentViewBinder>() - - val entry = row.entry - val privateLayout = row.privateLayout - - fakeRonContentModel = mockRonModel - fakeHeadsUpRonViewHolder = InflatedContentViewHolder(view = ronView, binder = mockBinder) - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_HEADS_UP, row) - - // VERIFY that the inflater is invoked - verify(fakeRonViewInflater) - .inflateView( - eq(mockRonModel), - any(), - eq(entry), - any(), - eq(privateLayout), - eq(RichOngoingNotificationViewType.HeadsUp) - ) - assertThat(row.privateLayout.headsUpChild).isSameInstanceAs(ronView) - verify(mockBinder).setupContentViewBinder() - } - - @Test - fun keepExistingViewForContractedRonNotChangingContractedChild() { - val oldHandle = mock<DisposableHandle>() - val mockRonModel = mock<TimerContentModel>() - - row.privateLayout.mContractedBinderHandle = oldHandle - val entry = spy(row.entry) - row.entry = entry - val privateLayout = spy(row.privateLayout) - row.privateLayout = privateLayout - - fakeRonContentModel = mockRonModel - fakeContractedRonViewHolder = KeepExistingView - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_CONTRACTED, row) - - // THEN do not dispose old contracted binder handle and change contracted child - verify(entry).setContentModel(argThat { richOngoingContentModel === mockRonModel }) - verifyNoMoreInteractions(oldHandle) - verify(privateLayout, never()).setContractedChild(any()) - } - - @Test - fun keepExistingViewForExpandedRonNotChangingExpandedChild() { - val oldHandle = mock<DisposableHandle>() - val mockRonModel = mock<TimerContentModel>() - - row.privateLayout.mExpandedBinderHandle = oldHandle - val entry = spy(row.entry) - row.entry = entry - val privateLayout = spy(row.privateLayout) - row.privateLayout = privateLayout - - fakeRonContentModel = mockRonModel - fakeExpandedRonViewHolder = KeepExistingView - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_EXPANDED, row) - - // THEN do not dispose old expanded binder handle and change expanded child - verify(entry).setContentModel(argThat { richOngoingContentModel === mockRonModel }) - verifyNoMoreInteractions(oldHandle) - verify(privateLayout, never()).setExpandedChild(any()) - } - - @Test - fun keepExistingViewForHeadsUpRonNotChangingHeadsUpChild() { - val oldHandle = mock<DisposableHandle>() - val mockRonModel = mock<TimerContentModel>() - - row.privateLayout.mHeadsUpBinderHandle = oldHandle - val entry = spy(row.entry) - row.entry = entry - val privateLayout = spy(row.privateLayout) - row.privateLayout = privateLayout - - fakeRonContentModel = mockRonModel - fakeHeadsUpRonViewHolder = KeepExistingView - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_HEADS_UP, row) - - // THEN - do not dispose old heads up binder handle and change heads up child - verify(entry).setContentModel(argThat { richOngoingContentModel === mockRonModel }) - verifyNoMoreInteractions(oldHandle) - verify(privateLayout, never()).setHeadsUpChild(any()) - } - - @Test - fun nullContentViewForContractedRonAppliesElementsInOrder() { - val oldHandle = mock<DisposableHandle>() - val mockRonModel = mock<TimerContentModel>() - - row.privateLayout.mContractedBinderHandle = oldHandle - val entry = spy(row.entry) - row.entry = entry - val privateLayout = spy(row.privateLayout) - row.privateLayout = privateLayout - - fakeRonContentModel = mockRonModel - fakeContractedRonViewHolder = NullContentView - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_CONTRACTED, row) - - // Validate that these 4 steps happen in this precise order - inOrder(oldHandle, entry, privateLayout, cache) { - verify(oldHandle).dispose() - verify(entry).setContentModel(argThat { richOngoingContentModel === mockRonModel }) - verify(privateLayout).setContractedChild(eq(null)) - } - } - - @Test - fun nullContentViewForExpandedRonAppliesElementsInOrder() { - val oldHandle = mock<DisposableHandle>() - val mockRonModel = mock<TimerContentModel>() - - row.privateLayout.mExpandedBinderHandle = oldHandle - val entry = spy(row.entry) - row.entry = entry - val privateLayout = spy(row.privateLayout) - row.privateLayout = privateLayout - - fakeRonContentModel = mockRonModel - fakeExpandedRonViewHolder = NullContentView - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_EXPANDED, row) - - // Validate that these 4 steps happen in this precise order - inOrder(oldHandle, entry, privateLayout, cache) { - verify(oldHandle).dispose() - verify(entry).setContentModel(argThat { richOngoingContentModel === mockRonModel }) - verify(privateLayout).setExpandedChild(eq(null)) - } - } - - @Test - fun nullContentViewForHeadsUpRonAppliesElementsInOrder() { - val oldHandle = mock<DisposableHandle>() - val mockRonModel = mock<TimerContentModel>() - - row.privateLayout.mHeadsUpBinderHandle = oldHandle - val entry = spy(row.entry) - row.entry = entry - val privateLayout = spy(row.privateLayout) - row.privateLayout = privateLayout - - fakeRonContentModel = mockRonModel - fakeHeadsUpRonViewHolder = NullContentView - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_HEADS_UP, row) - - // Validate that these 4 steps happen in this precise order - inOrder(oldHandle, entry, privateLayout, cache) { - verify(oldHandle).dispose() - verify(entry).setContentModel(argThat { richOngoingContentModel === mockRonModel }) - verify(privateLayout).setHeadsUpChild(eq(null)) - } - } - - @Test - fun contractedRonViewAppliesElementsInOrder() { - val oldHandle = mock<DisposableHandle>() - val mockRonModel = mock<TimerContentModel>() - val ronView = View(context) - val mockBinder = mock<DeferredContentViewBinder>() - - row.privateLayout.mContractedBinderHandle = oldHandle - val entry = spy(row.entry) - row.entry = entry - val privateLayout = spy(row.privateLayout) - row.privateLayout = privateLayout - - fakeRonContentModel = mockRonModel - fakeContractedRonViewHolder = InflatedContentViewHolder(view = ronView, binder = mockBinder) - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_CONTRACTED, row) - - // Validate that these 4 steps happen in this precise order - inOrder(oldHandle, entry, privateLayout, mockBinder) { - verify(oldHandle).dispose() - verify(entry).setContentModel(argThat { richOngoingContentModel === mockRonModel }) - verify(privateLayout).setContractedChild(eq(ronView)) - verify(mockBinder).setupContentViewBinder() - } - } - - @Test - fun expandedRonViewAppliesElementsInOrder() { - val oldHandle = mock<DisposableHandle>() - val mockRonModel = mock<TimerContentModel>() - val ronView = View(context) - val mockBinder = mock<DeferredContentViewBinder>() - - row.privateLayout.mExpandedBinderHandle = oldHandle - val entry = spy(row.entry) - row.entry = entry - val privateLayout = spy(row.privateLayout) - row.privateLayout = privateLayout - - fakeRonContentModel = mockRonModel - fakeExpandedRonViewHolder = InflatedContentViewHolder(view = ronView, binder = mockBinder) - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_EXPANDED, row) - - // Validate that these 4 steps happen in this precise order - inOrder(oldHandle, entry, privateLayout, mockBinder) { - verify(oldHandle).dispose() - verify(entry).setContentModel(argThat { richOngoingContentModel === mockRonModel }) - verify(privateLayout).setExpandedChild(eq(ronView)) - verify(mockBinder).setupContentViewBinder() - } - } - - @Test - fun headsUpRonViewAppliesElementsInOrder() { - val oldHandle = mock<DisposableHandle>() - val mockRonModel = mock<TimerContentModel>() - val ronView = View(context) - val mockBinder = mock<DeferredContentViewBinder>() - - row.privateLayout.mHeadsUpBinderHandle = oldHandle - val entry = spy(row.entry) - row.entry = entry - val privateLayout = spy(row.privateLayout) - row.privateLayout = privateLayout - - fakeRonContentModel = mockRonModel - fakeHeadsUpRonViewHolder = InflatedContentViewHolder(view = ronView, binder = mockBinder) - - // WHEN inflater inflates - inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_HEADS_UP, row) - - // Validate that these 4 steps happen in this precise order - inOrder(oldHandle, entry, privateLayout, mockBinder) { - verify(oldHandle).dispose() - verify(entry).setContentModel(argThat { richOngoingContentModel === mockRonModel }) - verify(privateLayout).setHeadsUpChild(eq(ronView)) - verify(mockBinder).setupContentViewBinder() - } - } - - @Test - fun testRonNotReinflating() { - val oldContractedBinderHandle = mock<DisposableHandle>() - val oldExpandedBinderHandle = mock<DisposableHandle>() - val oldHeadsUpBinderHandle = mock<DisposableHandle>() - - val contractedBinderHandle = mock<DisposableHandle>() - val expandedBinderHandle = mock<DisposableHandle>() - val headsUpBinderHandle = mock<DisposableHandle>() - - val contractedRonView = View(context) - val expandedRonView = View(context) - val headsUpRonView = View(context) - - val mockRonModel1 = mock<TimerContentModel>() - val mockRonModel2 = mock<TimerContentModel>() - - val mockContractedViewBinder = mock<DeferredContentViewBinder>() - val mockExpandedViewBinder = mock<DeferredContentViewBinder>() - val mockHeadsUpViewBinder = mock<DeferredContentViewBinder>() - - doReturn(contractedBinderHandle).whenever(mockContractedViewBinder).setupContentViewBinder() - doReturn(expandedBinderHandle).whenever(mockExpandedViewBinder).setupContentViewBinder() - doReturn(headsUpBinderHandle).whenever(mockHeadsUpViewBinder).setupContentViewBinder() - - row.privateLayout.mContractedBinderHandle = oldContractedBinderHandle - row.privateLayout.mExpandedBinderHandle = oldExpandedBinderHandle - row.privateLayout.mHeadsUpBinderHandle = oldHeadsUpBinderHandle - val entry = spy(row.entry) - row.entry = entry - val privateLayout = spy(row.privateLayout) - row.privateLayout = privateLayout - - // WHEN inflater inflates both a model and a view - fakeRonContentModel = mockRonModel1 - fakeContractedRonViewHolder = - InflatedContentViewHolder(view = contractedRonView, binder = mockContractedViewBinder) - fakeExpandedRonViewHolder = - InflatedContentViewHolder(view = expandedRonView, binder = mockExpandedViewBinder) - fakeHeadsUpRonViewHolder = - InflatedContentViewHolder(view = headsUpRonView, binder = mockHeadsUpViewBinder) - - val contentToInflate = - FLAG_CONTENT_VIEW_CONTRACTED or FLAG_CONTENT_VIEW_EXPANDED or FLAG_CONTENT_VIEW_HEADS_UP - inflateAndWait(notificationInflater, contentToInflate, row) - - // Validate that these 4 steps happen in this precise order - inOrder( - oldContractedBinderHandle, - oldExpandedBinderHandle, - oldHeadsUpBinderHandle, - entry, - privateLayout, - mockContractedViewBinder, - mockExpandedViewBinder, - mockHeadsUpViewBinder, - contractedBinderHandle, - expandedBinderHandle, - headsUpBinderHandle - ) { - verify(oldContractedBinderHandle).dispose() - verify(oldExpandedBinderHandle).dispose() - verify(oldHeadsUpBinderHandle).dispose() - - verify(entry).setContentModel(argThat { richOngoingContentModel === mockRonModel1 }) - - verify(privateLayout).setContractedChild(eq(contractedRonView)) - verify(mockContractedViewBinder).setupContentViewBinder() - - verify(privateLayout).setExpandedChild(eq(expandedRonView)) - verify(mockExpandedViewBinder).setupContentViewBinder() - - verify(privateLayout).setHeadsUpChild(eq(headsUpRonView)) - verify(mockHeadsUpViewBinder).setupContentViewBinder() - - verify(contractedBinderHandle, never()).dispose() - verify(expandedBinderHandle, never()).dispose() - verify(headsUpBinderHandle, never()).dispose() - } - - clearInvocations( - oldContractedBinderHandle, - oldExpandedBinderHandle, - oldHeadsUpBinderHandle, - entry, - privateLayout, - mockContractedViewBinder, - mockExpandedViewBinder, - mockHeadsUpViewBinder, - contractedBinderHandle, - expandedBinderHandle, - headsUpBinderHandle - ) - - // THEN when the inflater inflates just a model - fakeRonContentModel = mockRonModel2 - fakeContractedRonViewHolder = KeepExistingView - fakeExpandedRonViewHolder = KeepExistingView - fakeHeadsUpRonViewHolder = KeepExistingView - - inflateAndWait(notificationInflater, contentToInflate, row) - - // Validate that for reinflation, the only thing we do us update the model - verify(contractedBinderHandle, never()).dispose() - verify(expandedBinderHandle, never()).dispose() - verify(headsUpBinderHandle, never()).dispose() - verify(entry).setContentModel(argThat { richOngoingContentModel === mockRonModel2 }) - verify(privateLayout, never()).setContractedChild(any()) - verify(privateLayout, never()).setExpandedChild(any()) - verify(privateLayout, never()).setHeadsUpChild(any()) - verify(mockContractedViewBinder, never()).setupContentViewBinder() - verify(mockExpandedViewBinder, never()).setupContentViewBinder() - verify(mockHeadsUpViewBinder, never()).setupContentViewBinder() - verify(contractedBinderHandle, never()).dispose() - verify(expandedBinderHandle, never()).dispose() - verify(headsUpBinderHandle, never()).dispose() - } - - @Test fun testNotificationViewHeightTooSmallFailsValidation() { val validationError = getValidationError( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java index 75376e62f192..2340d0289db4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java @@ -200,8 +200,6 @@ public class NotificationTestHelper { mock(NotifRemoteViewCache.class), mock(NotificationRemoteInputManager.class), mock(ConversationNotificationProcessor.class), - mock(RichOngoingNotificationContentExtractor.class), - mock(RichOngoingNotificationViewInflater.class), mock(Executor.class), new MockSmartReplyInflater(), mock(NotifLayoutInflaterFactory.Provider.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt index 6b3fb5b4a2eb..503fa789cb80 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt @@ -29,12 +29,13 @@ import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.in import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.inflatePublicSingleLineView import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineViewBinder -import com.android.systemui.util.mockito.mock import kotlin.test.assertEquals import kotlin.test.assertNotNull +import kotlin.test.assertNull import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.kotlin.mock @SmallTest @RunWith(AndroidJUnit4::class) @@ -69,7 +70,7 @@ class SingleLineViewBinderTest : SysuiTestCase() { reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE, entry = row.entry, context = context, - logger = mock() + logger = mock(), ) val publicView = @@ -78,7 +79,7 @@ class SingleLineViewBinderTest : SysuiTestCase() { reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE, entry = row.entry, context = context, - logger = mock() + logger = mock(), ) assertNotNull(publicView) @@ -114,7 +115,7 @@ class SingleLineViewBinderTest : SysuiTestCase() { .addMessage( "How about lunch?", System.currentTimeMillis(), - Person.Builder().setName("user2").build() + Person.Builder().setName("user2").build(), ) .setGroupConversation(true) notificationBuilder.setStyle(style).setShortcutId(SHORTCUT_ID) @@ -127,7 +128,7 @@ class SingleLineViewBinderTest : SysuiTestCase() { reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE, entry = row.entry, context = context, - logger = mock() + logger = mock(), ) as HybridConversationNotificationView @@ -137,7 +138,7 @@ class SingleLineViewBinderTest : SysuiTestCase() { reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE, entry = row.entry, context = context, - logger = mock() + logger = mock(), ) as HybridConversationNotificationView assertNotNull(publicView) @@ -150,10 +151,7 @@ class SingleLineViewBinderTest : SysuiTestCase() { systemUiContext = context, ) // WHEN: binds the view - SingleLineViewBinder.bind( - viewModel, - view, - ) + SingleLineViewBinder.bind(viewModel, view) // THEN: the single-line conversation view should be bound with view model's corresponding // fields @@ -161,10 +159,55 @@ class SingleLineViewBinderTest : SysuiTestCase() { assertEquals(viewModel.contentText, view.textView.text) assertEquals( viewModel.conversationData?.conversationSenderName, - view.conversationSenderNameView.text + view.conversationSenderNameView.text, ) } + @Test + @EnableFlags(AsyncHybridViewInflation.FLAG_NAME) + fun bindConversationSingleLineView_nonConversationViewModel() { + // GIVEN: a ConversationSingleLineView, and a nonConversationViewModel + val style = Notification.BigTextStyle().bigText(CONTENT_TEXT) + notificationBuilder.setStyle(style) + val notification = notificationBuilder.build() + val row: ExpandableNotificationRow = helper.createRow(notification) + + val view = + inflatePrivateSingleLineView( + isConversation = true, + reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE, + entry = row.entry, + context = context, + logger = mock(), + ) + + val publicView = + inflatePublicSingleLineView( + isConversation = true, + reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE, + entry = row.entry, + context = context, + logger = mock(), + ) + assertNotNull(publicView) + + val viewModel = + SingleLineViewInflater.inflateSingleLineViewModel( + notification = notification, + messagingStyle = null, + builder = notificationBuilder, + systemUiContext = context, + ) + // WHEN: binds the view with the view model + SingleLineViewBinder.bind(viewModel, view) + + // THEN: the single-line view should be bound with view model's corresponding + // fields as a normal non-conversation single-line view + assertEquals(viewModel.titleText, view?.titleView?.text) + assertEquals(viewModel.contentText, view?.textView?.text) + assertNull(viewModel.conversationData) + } + private companion object { const val CHANNEL_ID = "CHANNEL_ID" const val CONTENT_TITLE = "A Cool New Feature" diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java index 63a560ffd2c1..e57e8d108529 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java @@ -66,7 +66,6 @@ import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder; import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager; -import com.android.systemui.statusbar.phone.StatusBarLocationPublisher; import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.ui.DarkIconManager; @@ -98,7 +97,6 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { private ShadeExpansionStateManager mShadeExpansionStateManager; private OngoingCallController mOngoingCallController; private SystemStatusAnimationScheduler mAnimationScheduler; - private StatusBarLocationPublisher mLocationPublisher; // Set in instantiate() private StatusBarIconController mStatusBarIconController; private KeyguardStateController mKeyguardStateController; @@ -1181,7 +1179,6 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { setUpDaggerComponent(); mOngoingCallController = mock(OngoingCallController.class); mAnimationScheduler = mock(SystemStatusAnimationScheduler.class); - mLocationPublisher = mock(StatusBarLocationPublisher.class); mStatusBarIconController = mock(StatusBarIconController.class); mStatusBarStateController = mock(StatusBarStateController.class); mKeyguardStateController = mock(KeyguardStateController.class); @@ -1200,7 +1197,6 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { mStatusBarFragmentComponentFactory, mOngoingCallController, mAnimationScheduler, - mLocationPublisher, mShadeExpansionStateManager, mStatusBarIconController, mIconManagerFactory, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java deleted file mode 100644 index 637a0f16cd5d..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package com.android.systemui.statusbar.policy; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; - -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.NotificationManager; -import android.os.Handler; -import android.provider.Settings; -import android.service.notification.ZenModeConfig; -import android.testing.TestableLooper; -import android.testing.TestableLooper.RunWithLooper; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import com.android.systemui.SysuiTestCase; -import com.android.systemui.broadcast.BroadcastDispatcher; -import com.android.systemui.dump.DumpManager; -import com.android.systemui.settings.UserTracker; -import com.android.systemui.statusbar.policy.ZenModeController.Callback; -import com.android.systemui.util.settings.FakeGlobalSettings; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -@SmallTest -@RunWith(AndroidJUnit4.class) -@RunWithLooper -public class ZenModeControllerImplTest extends SysuiTestCase { - - private Callback mCallback; - @Mock - NotificationManager mNm; - @Mock - ZenModeConfig mConfig; - @Mock - BroadcastDispatcher mBroadcastDispatcher; - @Mock - DumpManager mDumpManager; - @Mock - UserTracker mUserTracker; - private ZenModeControllerImpl mController; - - private final FakeGlobalSettings mGlobalSettings = new FakeGlobalSettings(); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mContext.addMockSystemService(NotificationManager.class, mNm); - when(mNm.getZenModeConfig()).thenReturn(mConfig); - - mController = new ZenModeControllerImpl( - mContext, - Handler.createAsync(TestableLooper.get(this).getLooper()), - Handler.createAsync(TestableLooper.get(this).getLooper()), - mBroadcastDispatcher, - mDumpManager, - mGlobalSettings, - mUserTracker); - } - - @Test - public void testRemoveDuringCallback() { - mCallback = new Callback() { - @Override - public void onConfigChanged(ZenModeConfig config) { - mController.removeCallback(mCallback); - } - }; - mController.addCallback(mCallback); - Callback mockCallback = mock(Callback.class); - mController.addCallback(mockCallback); - mController.fireConfigChanged(null); - verify(mockCallback).onConfigChanged(eq(null)); - } - - @Test - public void testAreNotificationsHiddenInShade_zenOffShadeSuppressed() { - mConfig.suppressedVisualEffects = - NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST; - mController.updateZenMode(Settings.Global.ZEN_MODE_OFF); - mController.updateZenModeConfig(); - - assertFalse(mController.areNotificationsHiddenInShade()); - } - - @Test - public void testAreNotificationsHiddenInShade_zenOnShadeNotSuppressed() { - NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0, - NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR); - when(mNm.getConsolidatedNotificationPolicy()).thenReturn(policy); - mController.updateConsolidatedNotificationPolicy(); - mController.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS); - - assertFalse(mController.areNotificationsHiddenInShade()); - } - - @Test - public void testAreNotificationsHiddenInShade_zenOnShadeSuppressed() { - NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0, - NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST); - when(mNm.getConsolidatedNotificationPolicy()).thenReturn(policy); - mController.updateConsolidatedNotificationPolicy(); - mController.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS); - - assertTrue(mController.areNotificationsHiddenInShade()); - } - - @Test - public void testModeChange() { - List<Integer> states = List.of( - Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, - Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, - Settings.Global.ZEN_MODE_ALARMS, - Settings.Global.ZEN_MODE_ALARMS - ); - - for (Integer state : states) { - mGlobalSettings.putInt(Settings.Global.ZEN_MODE, state); - TestableLooper.get(this).processAllMessages(); - assertEquals(state.intValue(), mController.getZen()); - } - } - - @Test - public void testModeChange_callbackNotified() { - final AtomicInteger currentState = new AtomicInteger(-1); - - ZenModeController.Callback callback = new Callback() { - @Override - public void onZenChanged(int zen) { - currentState.set(zen); - } - }; - - mController.addCallback(callback); - - List<Integer> states = List.of( - Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, - Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, - Settings.Global.ZEN_MODE_ALARMS, - Settings.Global.ZEN_MODE_ALARMS - ); - - for (Integer state : states) { - mGlobalSettings.putInt(Settings.Global.ZEN_MODE, state); - TestableLooper.get(this).processAllMessages(); - assertEquals(state.intValue(), currentState.get()); - } - - } - - @Test - public void testCallbackRemovedWhileDispatching_doesntCrash() { - final AtomicBoolean remove = new AtomicBoolean(false); - mGlobalSettings.putInt(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF); - TestableLooper.get(this).processAllMessages(); - final ZenModeController.Callback callback = new ZenModeController.Callback() { - @Override - public void onZenChanged(int zen) { - if (remove.get()) { - mController.removeCallback(this); - } - } - }; - mController.addCallback(callback); - mController.addCallback(new ZenModeController.Callback() {}); - - remove.set(true); - - mGlobalSettings.putInt(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_NO_INTERRUPTIONS); - TestableLooper.get(this).processAllMessages(); - } -} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt index 1302faaf82ca..62d221dd9790 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt @@ -6,6 +6,7 @@ import android.content.pm.ActivityInfo import android.content.pm.ApplicationInfo import android.graphics.Bitmap import android.os.UserHandle +import com.android.systemui.communal.shared.model.CommunalContentSize import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import com.android.systemui.communal.widgets.WidgetConfigurator import kotlinx.coroutines.CoroutineScope @@ -23,6 +24,10 @@ class FakeCommunalWidgetRepository(private val coroutineScope: CoroutineScope) : private var nextWidgetId = 1 + private fun updateListFromDatabase() { + _communalWidgets.value = fakeDatabase.values.sortedWith(compareBy { it.rank }).toList() + } + fun setCommunalWidgets(inventory: List<CommunalWidgetContentModel>) { _communalWidgets.value = inventory } @@ -49,6 +54,7 @@ class FakeCommunalWidgetRepository(private val coroutineScope: CoroutineScope) : rank: Int = 0, category: Int = AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD, userId: Int = 0, + spanY: Int = CommunalContentSize.HALF.span, ) { fakeDatabase[appWidgetId] = CommunalWidgetContentModel.Available( @@ -66,8 +72,9 @@ class FakeCommunalWidgetRepository(private val coroutineScope: CoroutineScope) : } } }, + spanY = spanY, ) - _communalWidgets.value = fakeDatabase.values.toList() + updateListFromDatabase() } fun addPendingWidget( @@ -84,8 +91,9 @@ class FakeCommunalWidgetRepository(private val coroutineScope: CoroutineScope) : componentName = ComponentName.unflattenFromString(componentName)!!, icon = icon, user = UserHandle(userId), + spanY = CommunalContentSize.HALF.span, ) - _communalWidgets.value = fakeDatabase.values.toList() + updateListFromDatabase() } override fun deleteWidget(widgetId: Int) { @@ -93,28 +101,54 @@ class FakeCommunalWidgetRepository(private val coroutineScope: CoroutineScope) : _communalWidgets.value = fakeDatabase.values.toList() } - override fun updateWidgetSpanY(widgetId: Int, spanY: Int) { - coroutineScope.launch { - fakeDatabase[widgetId]?.let { widget -> + private fun reorderDatabase(widgetIdToRankMap: Map<Int, Int>) { + for ((id, rank) in widgetIdToRankMap) { + val widget = fakeDatabase[id] ?: continue + fakeDatabase[id] = when (widget) { is CommunalWidgetContentModel.Available -> { - fakeDatabase[widgetId] = widget.copy(spanY = spanY) + widget.copy(rank = rank) } is CommunalWidgetContentModel.Pending -> { - fakeDatabase[widgetId] = widget.copy(spanY = spanY) + widget.copy(rank = rank) } } - _communalWidgets.value = fakeDatabase.values.toList() - } } } + override fun updateWidgetOrder(widgetIdToRankMap: Map<Int, Int>) { + reorderDatabase(widgetIdToRankMap) + updateListFromDatabase() + } + + override fun resizeWidget(appWidgetId: Int, spanY: Int, widgetIdToRankMap: Map<Int, Int>) { + val widget = fakeDatabase[appWidgetId] ?: return + + fakeDatabase[appWidgetId] = + when (widget) { + is CommunalWidgetContentModel.Available -> { + widget.copy(spanY = spanY) + } + is CommunalWidgetContentModel.Pending -> { + widget.copy(spanY = spanY) + } + } + reorderDatabase(widgetIdToRankMap) + updateListFromDatabase() + } + override fun restoreWidgets(oldToNewWidgetIdMap: Map<Int, Int>) {} override fun abortRestoreWidgets() {} private fun onConfigured(id: Int, providerInfo: AppWidgetProviderInfo, rank: Int) { - _communalWidgets.value += - listOf(CommunalWidgetContentModel.Available(id, providerInfo, rank)) + fakeDatabase[id] = + CommunalWidgetContentModel.Available( + appWidgetId = id, + providerInfo = providerInfo, + rank = rank, + spanY = CommunalContentSize.HALF.span, + ) + updateListFromDatabase() } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/ResizeableItemFrameViewModelKosmos.kt index 15ed1b372db4..8422942a727a 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/data/repository/SystemGestureExclusionRepositoryKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/ResizeableItemFrameViewModelKosmos.kt @@ -14,12 +14,8 @@ * limitations under the License. */ -package com.android.systemui.scene.data.repository +package com.android.systemui.communal.ui.viewmodel -import android.view.windowManagerService import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.Kosmos.Fixture -val Kosmos.systemGestureExclusionRepository by Fixture { - SystemGestureExclusionRepository(windowManager = windowManagerService) -} +val Kosmos.resizeableItemFrameViewModel by Kosmos.Fixture { ResizeableItemFrameViewModel() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeFocusedDisplayRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeFocusedDisplayRepository.kt new file mode 100644 index 000000000000..83df5d874ad6 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeFocusedDisplayRepository.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.display.data.repository + +import android.view.Display +import com.android.systemui.dagger.SysUISingleton +import dagger.Binds +import dagger.Module +import javax.inject.Inject +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow + +@SysUISingleton +/** Fake [FocusedDisplayRepository] for testing. */ +class FakeFocusedDisplayRepository @Inject constructor() : FocusedDisplayRepository { + private val flow = MutableStateFlow<Int>(Display.DEFAULT_DISPLAY) + + override val focusedDisplayId: StateFlow<Int> + get() = flow.asStateFlow() + + suspend fun emit(focusedDisplay: Int) = flow.emit(focusedDisplay) +} + +@Module +interface FakeFocusedDisplayRepositoryModule { + @Binds fun bindFake(fake: FakeFocusedDisplayRepository): FocusedDisplayRepository +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt index 4d0e603aadd6..70b4f79131a7 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt @@ -48,13 +48,35 @@ import kotlinx.coroutines.test.runCurrent * with OFF -> GONE. Construct with initInLockscreen = false if your test requires this behavior. */ @SysUISingleton -class FakeKeyguardTransitionRepository(private val initInLockscreen: Boolean = true) : - KeyguardTransitionRepository { +class FakeKeyguardTransitionRepository( + private val initInLockscreen: Boolean = true, + + /** + * If true, calls to [startTransition] will automatically emit STARTED, RUNNING, and FINISHED + * transition steps from/to the given states. + * + * [startTransition] is what the From*TransitionInteractors call, so this more closely emulates + * the behavior of the real KeyguardTransitionRepository, and reduces the work needed to + * manually set up the repository state in each test. For example, setting dreaming=true will + * automatically cause FromDreamingTransitionInteractor to call startTransition(DREAMING), and + * then we'll send STARTED/RUNNING/FINISHED DREAMING TransitionSteps. + * + * If your test needs to make assertions at specific points between STARTED/FINISHED, or if it's + * difficult to set up all of the conditions to make the transition interactors actually call + * startTransition, then construct a FakeKeyguardTransitionRepository with this value false. + */ + private val sendTransitionStepsOnStartTransition: Boolean = true, + private val testScope: TestScope, +) : KeyguardTransitionRepository { + private val _transitions = MutableSharedFlow<TransitionStep>(replay = 3, onBufferOverflow = BufferOverflow.DROP_OLDEST) override val transitions: SharedFlow<TransitionStep> = _transitions - @Inject constructor() : this(initInLockscreen = true) + @Inject + constructor( + testScope: TestScope + ) : this(initInLockscreen = true, sendTransitionStepsOnStartTransition = true, testScope) private val _currentTransitionInfo: MutableStateFlow<TransitionInfo> = MutableStateFlow( @@ -287,6 +309,11 @@ class FakeKeyguardTransitionRepository(private val initInLockscreen: Boolean = t override suspend fun startTransition(info: TransitionInfo): UUID? { _currentTransitionInfo.value = info + + if (sendTransitionStepsOnStartTransition) { + sendTransitionSteps(from = info.from, to = info.to, testScope = testScope) + } + return if (info.animator == null) UUID.randomUUID() else null } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt index f26bb83ed3f0..805a710a2cf3 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt @@ -35,6 +35,8 @@ class FakeLightRevealScrimRepository : LightRevealScrimRepository { private val _revealAmount: MutableStateFlow<Float> = MutableStateFlow(0.0f) override val revealAmount: Flow<Float> = _revealAmount + val revealAnimatorRequests: MutableList<RevealAnimatorRequest> = arrayListOf() + override val isAnimating: Boolean get() = false @@ -44,5 +46,12 @@ class FakeLightRevealScrimRepository : LightRevealScrimRepository { } else { _revealAmount.value = 0.0f } + + revealAnimatorRequests.add(RevealAnimatorRequest(reveal, duration)) } + + data class RevealAnimatorRequest( + val reveal: Boolean, + val duration: Long + ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryKosmos.kt index 3e69e875cd0d..e9eea83d54df 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryKosmos.kt @@ -18,9 +18,14 @@ package com.android.systemui.keyguard.data.repository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.kosmos.testScope +import org.mockito.Mockito.spy var Kosmos.keyguardTransitionRepository: KeyguardTransitionRepository by Kosmos.Fixture { fakeKeyguardTransitionRepository } -var Kosmos.fakeKeyguardTransitionRepository by Kosmos.Fixture { FakeKeyguardTransitionRepository() } +var Kosmos.fakeKeyguardTransitionRepository by + Kosmos.Fixture { FakeKeyguardTransitionRepository(testScope = testScope) } +var Kosmos.fakeKeyguardTransitionRepositorySpy: FakeKeyguardTransitionRepository by + Kosmos.Fixture { spy(fakeKeyguardTransitionRepository) } var Kosmos.realKeyguardTransitionRepository: KeyguardTransitionRepository by Kosmos.Fixture { KeyguardTransitionRepositoryImpl(testDispatcher) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt index ef789d1b29ff..93a59eb8ca0c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt @@ -17,7 +17,7 @@ package com.android.systemui.keyguard.domain.interactor import com.android.systemui.deviceentry.data.repository.deviceEntryRepository -import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.testDispatcher @@ -27,7 +27,7 @@ import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInterac val Kosmos.fromAodTransitionInteractor by Kosmos.Fixture { FromAodTransitionInteractor( - transitionRepository = fakeKeyguardTransitionRepository, + transitionRepository = keyguardTransitionRepository, transitionInteractor = keyguardTransitionInteractor, internalTransitionInteractor = internalKeyguardTransitionInteractor, scope = applicationCoroutineScope, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorKosmos.kt index c694114a0f47..700d7e9c5608 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorKosmos.kt @@ -18,8 +18,8 @@ package com.android.systemui.keyguard.domain.interactor import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.keyguard.data.repository.biometricSettingsRepository -import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.keyguardRepository +import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.testDispatcher @@ -29,7 +29,7 @@ import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInterac val Kosmos.fromGoneTransitionInteractor by Kosmos.Fixture { FromGoneTransitionInteractor( - transitionRepository = fakeKeyguardTransitionRepository, + transitionRepository = keyguardTransitionRepository, transitionInteractor = keyguardTransitionInteractor, internalTransitionInteractor = internalKeyguardTransitionInteractor, scope = applicationCoroutineScope, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelKosmos.kt new file mode 100644 index 000000000000..fc4f3a553d51 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelKosmos.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.keyguard.ui.viewmodel + +import android.content.applicationContext +import com.android.systemui.common.ui.domain.interactor.configurationInteractor +import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import kotlinx.coroutines.ExperimentalCoroutinesApi + +@ExperimentalCoroutinesApi +val Kosmos.deviceEntryBackgroundViewModel by Fixture { + DeviceEntryBackgroundViewModel( + context = applicationContext, + deviceEntryIconViewModel = deviceEntryIconViewModel, + configurationInteractor = configurationInteractor, + keyguardTransitionInteractor = keyguardTransitionInteractor, + alternateBouncerToAodTransitionViewModel = alternateBouncerToAodTransitionViewModel, + alternateBouncerToDozingTransitionViewModel = alternateBouncerToDozingTransitionViewModel, + aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel, + dozingToLockscreenTransitionViewModel = dozingToLockscreenTransitionViewModel, + dreamingToAodTransitionViewModel = dreamingToAodTransitionViewModel, + dreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel, + goneToAodTransitionViewModel = goneToAodTransitionViewModel, + goneToDozingTransitionViewModel = goneToDozingTransitionViewModel, + goneToLockscreenTransitionViewModel = goneToLockscreenTransitionViewModel, + lockscreenToAodTransitionViewModel = lockscreenToAodTransitionViewModel, + occludedToAodTransitionViewModel = occludedToAodTransitionViewModel, + occludedToDozingTransitionViewModel = occludedToDozingTransitionViewModel, + occludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel, + offToLockscreenTransitionViewModel = offToLockscreenTransitionViewModel, + primaryBouncerToAodTransitionViewModel = primaryBouncerToAodTransitionViewModel, + primaryBouncerToDozingTransitionViewModel = primaryBouncerToDozingTransitionViewModel, + primaryBouncerToLockscreenTransitionViewModel = + primaryBouncerToLockscreenTransitionViewModel, + lockscreenToDozingTransitionViewModel = lockscreenToDozingTransitionViewModel, + ) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/FakeVolumeDialogController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/FakeVolumeDialogController.kt new file mode 100644 index 000000000000..e4a2a874b848 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/FakeVolumeDialogController.kt @@ -0,0 +1,195 @@ +/* + * 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.plugins + +import android.media.AudioManager +import android.media.AudioManager.CsdWarning +import android.os.Handler +import android.os.VibrationEffect +import androidx.core.util.getOrElse +import java.util.concurrent.CopyOnWriteArraySet + +class FakeVolumeDialogController(private val audioManager: AudioManager) : VolumeDialogController { + + var isVisible: Boolean = false + private set + + var hasScheduledTouchFeedback: Boolean = false + private set + + var vibrationEffect: VibrationEffect? = null + private set + + var hasUserActivity: Boolean = false + private set + + private var hasVibrator: Boolean = true + + private val state = VolumeDialogController.State() + private val callbacks = CopyOnWriteArraySet<VolumeDialogController.Callbacks>() + + override fun setActiveStream(stream: Int) { + // ensure streamState existence for the active stream + state.states.getOrElse(stream) { + VolumeDialogController.StreamState().also { streamState -> + state.states.put(stream, streamState) + } + } + state.activeStream = stream + } + + override fun setStreamVolume(stream: Int, userLevel: Int) { + val streamState = + state.states.getOrElse(stream) { + VolumeDialogController.StreamState().also { streamState -> + state.states.put(stream, streamState) + } + } + streamState.level = userLevel.coerceIn(streamState.levelMin, streamState.levelMax) + } + + override fun setRingerMode(ringerModeNormal: Int, external: Boolean) { + if (external) { + state.ringerModeExternal = ringerModeNormal + } else { + state.ringerModeInternal = ringerModeNormal + } + } + + fun setHasVibrator(hasVibrator: Boolean) { + this.hasVibrator = hasVibrator + } + + override fun hasVibrator(): Boolean = hasVibrator + + override fun vibrate(effect: VibrationEffect) { + vibrationEffect = effect + } + + override fun scheduleTouchFeedback() { + hasScheduledTouchFeedback = true + } + + fun resetScheduledTouchFeedback() { + hasScheduledTouchFeedback = false + } + + override fun getAudioManager(): AudioManager = audioManager + + override fun notifyVisible(visible: Boolean) { + isVisible = visible + } + + override fun addCallback(callbacks: VolumeDialogController.Callbacks?, handler: Handler?) { + this.callbacks.add(callbacks) + } + + override fun removeCallback(callbacks: VolumeDialogController.Callbacks?) { + this.callbacks.remove(callbacks) + } + + override fun userActivity() { + hasUserActivity = true + } + + fun resetUserActivity() { + hasUserActivity = false + } + + override fun getState() { + callbacks.sendEvent { it.onStateChanged(state) } + } + + /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onShowRequested */ + fun onShowRequested(reason: Int, keyguardLocked: Boolean, lockTaskModeState: Int) { + callbacks.sendEvent { it.onShowRequested(reason, keyguardLocked, lockTaskModeState) } + } + + /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onDismissRequested */ + fun onDismissRequested(reason: Int) { + callbacks.sendEvent { it.onDismissRequested(reason) } + } + + /** + * @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onLayoutDirectionChanged + */ + fun onLayoutDirectionChanged(layoutDirection: Int) { + callbacks.sendEvent { it.onLayoutDirectionChanged(layoutDirection) } + } + + /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onConfigurationChanged */ + fun onConfigurationChanged() { + callbacks.sendEvent { it.onConfigurationChanged() } + } + + /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onShowVibrateHint */ + fun onShowVibrateHint() { + callbacks.sendEvent { it.onShowVibrateHint() } + } + + /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onShowSilentHint */ + fun onShowSilentHint() { + callbacks.sendEvent { it.onShowSilentHint() } + } + + /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onScreenOff */ + fun onScreenOff() { + callbacks.sendEvent { it.onScreenOff() } + } + + /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onShowSafetyWarning */ + fun onShowSafetyWarning(flags: Int) { + callbacks.sendEvent { it.onShowSafetyWarning(flags) } + } + + /** + * @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onAccessibilityModeChanged + */ + fun onAccessibilityModeChanged(showA11yStream: Boolean?) { + callbacks.sendEvent { it.onAccessibilityModeChanged(showA11yStream) } + } + + /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onShowCsdWarning */ + fun onShowCsdWarning(@CsdWarning csdWarning: Int, durationMs: Int) { + callbacks.sendEvent { it.onShowCsdWarning(csdWarning, durationMs) } + } + + /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onVolumeChangedFromKey */ + fun onVolumeChangedFromKey() { + callbacks.sendEvent { it.onVolumeChangedFromKey() } + } + + override fun getCaptionsEnabledState(checkForSwitchState: Boolean) { + error("Unsupported for the new Volume Dialog") + } + + override fun setCaptionsEnabledState(enabled: Boolean) { + error("Unsupported for the new Volume Dialog") + } + + override fun getCaptionsComponentState(fromTooltip: Boolean) { + error("Unsupported for the new Volume Dialog") + } +} + +private inline fun CopyOnWriteArraySet<VolumeDialogController.Callbacks>.sendEvent( + event: (callback: VolumeDialogController.Callbacks) -> Unit +) { + for (callback in this) { + event(callback) + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/domain/interactor/NotificationRowInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/VolumeDialogControllerKosmos.kt index 3a7d7ba064d0..2f6d4fa32e65 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/domain/interactor/NotificationRowInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/plugins/VolumeDialogControllerKosmos.kt @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.android.systemui.statusbar.notification.row.domain.interactor +package com.android.systemui.plugins import com.android.systemui.kosmos.Kosmos -import com.android.systemui.statusbar.notification.row.data.repository.NotificationRowRepository +import org.mockito.kotlin.mock -fun Kosmos.getNotificationRowInteractor(repository: NotificationRowRepository) = - NotificationRowInteractor(repository = repository) +val Kosmos.fakeVolumeDialogController by Kosmos.Fixture { FakeVolumeDialogController(mock {}) } +var Kosmos.volumeDialogController: VolumeDialogController by + Kosmos.Fixture { fakeVolumeDialogController } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt index dbb3e386cc71..c218ff6ba966 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModelKosmos.kt @@ -24,6 +24,7 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.qs.footerActionsController import com.android.systemui.qs.footerActionsViewModelFactory import com.android.systemui.qs.panels.domain.interactor.tileSquishinessInteractor +import com.android.systemui.qs.panels.ui.viewmodel.paginatedGridViewModel import com.android.systemui.qs.ui.viewmodel.quickSettingsContainerViewModel import com.android.systemui.shade.largeScreenHeaderHelper import com.android.systemui.shade.transition.largeScreenShadeInterpolator @@ -48,6 +49,7 @@ val Kosmos.qsFragmentComposeViewModelFactory by configurationInteractor, largeScreenHeaderHelper, tileSquishinessInteractor, + paginatedGridViewModel, lifecycleScope, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt index f842db4c0026..4f414d995aab 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt @@ -8,17 +8,14 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor -import com.android.systemui.scene.domain.interactor.systemGestureExclusionInteractor import com.android.systemui.scene.shared.logger.sceneLogger import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.FakeOverlay -import com.android.systemui.scene.ui.viewmodel.SceneContainerGestureFilter import com.android.systemui.scene.ui.viewmodel.SceneContainerHapticsViewModel import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel import com.android.systemui.scene.ui.viewmodel.splitEdgeDetector -import com.android.systemui.settings.displayTracker import com.android.systemui.shade.domain.interactor.shadeInteractor import kotlinx.coroutines.flow.MutableStateFlow import org.mockito.kotlin.mock @@ -31,6 +28,7 @@ var Kosmos.sceneKeys by Fixture { Scenes.Bouncer, Scenes.Gone, Scenes.Communal, + Scenes.Dream, ) } @@ -52,9 +50,10 @@ var Kosmos.sceneContainerConfig by Fixture { Scenes.Gone to 0, Scenes.Lockscreen to 0, Scenes.Communal to 1, - Scenes.Shade to 2, - Scenes.QuickSettings to 3, - Scenes.Bouncer to 4, + Scenes.Dream to 2, + Scenes.Shade to 3, + Scenes.QuickSettings to 4, + Scenes.Bouncer to 5, ) SceneContainerConfig( @@ -72,16 +71,15 @@ val Kosmos.transitionState by Fixture { } val Kosmos.sceneContainerViewModel by Fixture { - sceneContainerViewModelFactory.create(mock<View>(), displayTracker.defaultDisplayId, {}).apply { - setTransitionState(transitionState) - } + sceneContainerViewModelFactory + .create(mock<View>()) {} + .apply { setTransitionState(transitionState) } } val Kosmos.sceneContainerViewModelFactory by Fixture { object : SceneContainerViewModel.Factory { override fun create( view: View, - displayId: Int, motionEventHandlerReceiver: (SceneContainerViewModel.MotionEventHandler?) -> Unit, ): SceneContainerViewModel = SceneContainerViewModel( @@ -91,26 +89,13 @@ val Kosmos.sceneContainerViewModelFactory by Fixture { shadeInteractor = shadeInteractor, splitEdgeDetector = splitEdgeDetector, logger = sceneLogger, - gestureFilterFactory = sceneContainerGestureFilterFactory, hapticsViewModelFactory = sceneContainerHapticsViewModelFactory, view = view, - displayId = displayId, motionEventHandlerReceiver = motionEventHandlerReceiver, ) } } -val Kosmos.sceneContainerGestureFilterFactory by Fixture { - object : SceneContainerGestureFilter.Factory { - override fun create(displayId: Int): SceneContainerGestureFilter { - return SceneContainerGestureFilter( - interactor = systemGestureExclusionInteractor, - displayId = displayId, - ) - } - } -} - val Kosmos.sceneContainerHapticsViewModelFactory by Fixture { object : SceneContainerHapticsViewModel.Factory { override fun create(view: View): SceneContainerHapticsViewModel { diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt index 8fdb948e2d1d..ca33a8663a51 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.emptyshade.ui.viewmodel import android.content.applicationContext import com.android.systemui.dump.dumpManager import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testDispatcher import com.android.systemui.shared.notifications.domain.interactor.notificationSettingsInteractor import com.android.systemui.statusbar.notification.domain.interactor.seenNotificationsInteractor import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor @@ -30,6 +31,7 @@ val Kosmos.emptyShadeViewModel by zenModeInteractor, seenNotificationsInteractor, notificationSettingsInteractor, + testDispatcher, dumpManager, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt index 2eb1573dc3d7..fc4f05df26ed 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt @@ -222,8 +222,6 @@ class ExpandableNotificationRowBuilder( Mockito.mock(NotifRemoteViewCache::class.java, STUB_ONLY), remoteInputManager, conversationProcessor, - Mockito.mock(RichOngoingNotificationContentExtractor::class.java, STUB_ONLY), - Mockito.mock(RichOngoingNotificationViewInflater::class.java, STUB_ONLY), Mockito.mock(Executor::class.java, STUB_ONLY), smartReplyStateInflater, notifLayoutInflaterFactoryProvider, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/EnRouteViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/EnRouteViewModelKosmos.kt deleted file mode 100644 index 7e511355372b..000000000000 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/EnRouteViewModelKosmos.kt +++ /dev/null @@ -1,28 +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.systemui.statusbar.notification.row.ui.viewmodel - -import com.android.systemui.dump.dumpManager -import com.android.systemui.kosmos.Kosmos -import com.android.systemui.statusbar.notification.row.data.repository.NotificationRowRepository -import com.android.systemui.statusbar.notification.row.domain.interactor.getNotificationRowInteractor - -fun Kosmos.getEnRouteViewModel(repository: NotificationRowRepository) = - EnRouteViewModel( - dumpManager = dumpManager, - rowInteractor = getNotificationRowInteractor(repository), - ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/TimerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/TimerViewModelKosmos.kt deleted file mode 100644 index 00f45b220654..000000000000 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/TimerViewModelKosmos.kt +++ /dev/null @@ -1,28 +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.systemui.statusbar.notification.row.ui.viewmodel - -import com.android.systemui.dump.dumpManager -import com.android.systemui.kosmos.Kosmos -import com.android.systemui.statusbar.notification.row.data.repository.NotificationRowRepository -import com.android.systemui.statusbar.notification.row.domain.interactor.getNotificationRowInteractor - -fun Kosmos.getTimerViewModel(repository: NotificationRowRepository) = - TimerViewModel( - dumpManager = dumpManager, - rowInteractor = getNotificationRowInteractor(repository), - ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/data/repository/NotificationRowRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogCallbacksInteractorKosmos.kt index 84ef4b5c21c3..db9c48d9be6f 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/data/repository/NotificationRowRepositoryKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogCallbacksInteractorKosmos.kt @@ -14,15 +14,19 @@ * limitations under the License. */ -package com.android.systemui.statusbar.notification.row.data.repository +package com.android.systemui.volume.dialog.domain.interactor +import android.os.Handler +import android.os.looper import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.Kosmos.Fixture -import com.android.systemui.statusbar.notification.row.shared.RichOngoingContentModel -import kotlinx.coroutines.flow.MutableStateFlow +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.plugins.volumeDialogController -val Kosmos.fakeNotificationRowRepository by Fixture { FakeNotificationRowRepository() } - -class FakeNotificationRowRepository : NotificationRowRepository { - override val richOngoingContentModel = MutableStateFlow<RichOngoingContentModel?>(null) -} +val Kosmos.volumeDialogCallbacksInteractor: VolumeDialogCallbacksInteractor by + Kosmos.Fixture { + VolumeDialogCallbacksInteractor( + volumeDialogController = volumeDialogController, + coroutineScope = applicationCoroutineScope, + bgHandler = Handler(looper), + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractorKosmos.kt index 3e46c3f90b73..e73539eac6f1 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SystemGestureExclusionInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogVisibilityInteractorKosmos.kt @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.android.systemui.scene.domain.interactor +package com.android.systemui.volume.dialog.domain.interactor import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.Kosmos.Fixture -import com.android.systemui.scene.data.repository.systemGestureExclusionRepository +import com.android.systemui.kosmos.applicationCoroutineScope -val Kosmos.systemGestureExclusionInteractor by Fixture { - SystemGestureExclusionInteractor(repository = systemGestureExclusionRepository) -} +val Kosmos.volumeDialogVisibilityInteractor by + Kosmos.Fixture { + VolumeDialogVisibilityInteractor(applicationCoroutineScope, volumeDialogCallbacksInteractor) + } diff --git a/packages/SystemUI/frp/Android.bp b/packages/SystemUI/utils/kairos/Android.bp index c3381db7a0e3..1442591eab99 100644 --- a/packages/SystemUI/frp/Android.bp +++ b/packages/SystemUI/utils/kairos/Android.bp @@ -20,9 +20,9 @@ package { } java_library { - name: "kt-frp", + name: "kairos", host_supported: true, - kotlincflags: ["-opt-in=com.android.systemui.experimental.frp.ExperimentalFrpApi"], + kotlincflags: ["-opt-in=com.android.systemui.kairos.ExperimentalFrpApi"], srcs: ["src/**/*.kt"], static_libs: [ "kotlin-stdlib", @@ -31,7 +31,7 @@ java_library { } java_test { - name: "kt-frp-test", + name: "kairos-test", optimize: { enabled: false, }, @@ -39,7 +39,7 @@ java_test { "test/**/*.kt", ], static_libs: [ - "kt-frp", + "kairos", "junit", "kotlin-stdlib", "kotlin-test", diff --git a/packages/SystemUI/frp/OWNERS b/packages/SystemUI/utils/kairos/OWNERS index 8876ad6f6224..8876ad6f6224 100644 --- a/packages/SystemUI/frp/OWNERS +++ b/packages/SystemUI/utils/kairos/OWNERS diff --git a/packages/SystemUI/frp/README.md b/packages/SystemUI/utils/kairos/README.md index 9c5bdb036c45..85f622ca05f3 100644 --- a/packages/SystemUI/frp/README.md +++ b/packages/SystemUI/utils/kairos/README.md @@ -1,4 +1,4 @@ -# kt-frp +# Kairos A functional reactive programming (FRP) library for Kotlin. @@ -13,12 +13,12 @@ FRP exposes an API that should be familiar to those versed in Kotlin `Flow`. ### Details for nerds -`kt-frp` implements an applicative / monadic flavor of FRP, using a push-pull +`Kairos` implements an applicative / monadic flavor of FRP, using a push-pull methodology to allow for efficient updates. "Real" functional reactive programming should be specified with denotational semantics ([wikipedia](https://en.wikipedia.org/wiki/Denotational_semantics)): -you can view the semantics for `kt-frp` [here](docs/semantics.md). +you can view the semantics for `Kairos` [here](docs/semantics.md). ## Usage @@ -61,4 +61,4 @@ will tear-down all effects and obervers running within the lambda. ## Resources -- [Cheatsheet for those coming from Kotlin Flow](docs/flow-to-frp-cheatsheet.md) +- [Cheatsheet for those coming from Kotlin Flow](docs/flow-to-kairos-cheatsheet.md) diff --git a/packages/SystemUI/frp/docs/flow-to-frp-cheatsheet.md b/packages/SystemUI/utils/kairos/docs/flow-to-kairos-cheatsheet.md index e20f3e6c7461..9f7fd022f019 100644 --- a/packages/SystemUI/frp/docs/flow-to-frp-cheatsheet.md +++ b/packages/SystemUI/utils/kairos/docs/flow-to-kairos-cheatsheet.md @@ -1,27 +1,27 @@ -# From Flows to FRP +# From Flows to Kairos ## Key differences -* FRP evaluates all events (`TFlow` emissions + observers) in a transaction. +* Kairos evaluates all events (`TFlow` emissions + observers) in a transaction. -* FRP splits `Flow` APIs into two distinct types: `TFlow` and `TState` +* Kairos splits `Flow` APIs into two distinct types: `TFlow` and `TState` * `TFlow` is roughly equivalent to `SharedFlow` w/ a replay cache that - exists for the duration of the current FRP transaction and shared with + exists for the duration of the current Kairos transaction and shared with `SharingStarted.WhileSubscribed()` * `TState` is roughly equivalent to `StateFlow` shared with `SharingStarted.Eagerly`, but the current value can only be queried within - a FRP transaction, and the value is only updated at the end of the + a Kairos transaction, and the value is only updated at the end of the transaction -* FRP further divides `Flow` APIs based on how they internally use state: +* Kairos further divides `Flow` APIs based on how they internally use state: * **FrpTransactionScope:** APIs that internally query some state need to be - performed within an FRP transaction + performed within an Kairos transaction * this scope is available from the other scopes, and from most lambdas - passed to other FRP APIs + passed to other Kairos APIs * **FrpStateScope:** APIs that internally accumulate state in reaction to events need to be performed within an FRP State scope (akin to a @@ -126,8 +126,8 @@ has emitted at least once. This often bites developers. As a workaround, developers generally append `.onStart { emit(initialValue) }` to the `Flows` that don't immediately emit. -FRP avoids this gotcha by forcing usage of `TState` for `combine`, thus ensuring -that there is always a current value to be combined for each input. +Kairos avoids this gotcha by forcing usage of `TState` for `combine`, thus +ensuring that there is always a current value to be combined for each input. ## collect { … } @@ -158,8 +158,8 @@ tFlow.map { tState.sample() } #### Explanation To keep all state-reads consistent, the current value of a TState can only be -queried within an FRP transaction, modeled with `FrpTransactionScope`. Note that -both `FrpStateScope` and `FrpBuildScope` extend `FrpTransactionScope`. +queried within a Kairos transaction, modeled with `FrpTransactionScope`. Note +that both `FrpStateScope` and `FrpBuildScope` extend `FrpTransactionScope`. ### I want to sample a TFlow @@ -198,7 +198,7 @@ simultaneous emissions within the same transaction. #### Explanation -Under FRP's rules, a `TFlow` may only emit up to once per transaction. This +Under Kairos's rules, a `TFlow` may only emit up to once per transaction. This means that if we are merging two or more `TFlows` that are emitting at the same time (within the same transaction), the resulting merged `TFlow` must emit a single value. The lambda argument allows the developer to decide what to do in diff --git a/packages/SystemUI/frp/docs/semantics.md b/packages/SystemUI/utils/kairos/docs/semantics.md index b533190e687d..d43bb4447061 100644 --- a/packages/SystemUI/frp/docs/semantics.md +++ b/packages/SystemUI/utils/kairos/docs/semantics.md @@ -1,11 +1,11 @@ # FRP Semantics -`kt-frp`'s pure API is based off of the following denotational semantics +`Kairos`'s pure API is based off of the following denotational semantics ([wikipedia](https://en.wikipedia.org/wiki/Denotational_semantics)). -The semantics model `kt-frp` types as time-varying values; by making `Time` a +The semantics model `Kairos` types as time-varying values; by making `Time` a first-class value, we can define a referentially-transparent API that allows us -to reason about the behavior of the pure FRP combinators. This is +to reason about the behavior of the pure `Kairos` combinators. This is implementation-agnostic; we can compare the behavior of any implementation with expected behavior denoted by these semantics to identify bugs. diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/Combinators.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Combinators.kt index 298c071a4229..8bf3a43765ae 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/Combinators.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Combinators.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp +package com.android.systemui.kairos -import com.android.systemui.experimental.frp.util.These -import com.android.systemui.experimental.frp.util.just -import com.android.systemui.experimental.frp.util.none +import com.android.systemui.kairos.util.These +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.none import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.channelFlow import kotlinx.coroutines.flow.conflate diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/FrpBuildScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpBuildScope.kt index 6e4c9eba90bf..4de6deb3dc53 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/FrpBuildScope.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpBuildScope.kt @@ -16,11 +16,11 @@ @file:OptIn(ExperimentalCoroutinesApi::class) -package com.android.systemui.experimental.frp +package com.android.systemui.kairos -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.just -import com.android.systemui.experimental.frp.util.map +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.map import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.RestrictsSuspension diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/FrpEffectScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpEffectScope.kt index a8ec98fdc6c9..be2eb4312476 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/FrpEffectScope.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpEffectScope.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp +package com.android.systemui.kairos import kotlin.coroutines.RestrictsSuspension import kotlinx.coroutines.CoroutineScope diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/FrpNetwork.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpNetwork.kt index acc76d93f928..b688eafe12e9 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/FrpNetwork.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpNetwork.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp +package com.android.systemui.kairos -import com.android.systemui.experimental.frp.internal.BuildScopeImpl -import com.android.systemui.experimental.frp.internal.Network -import com.android.systemui.experimental.frp.internal.StateScopeImpl -import com.android.systemui.experimental.frp.internal.util.awaitCancellationAndThen -import com.android.systemui.experimental.frp.internal.util.childScope +import com.android.systemui.kairos.internal.BuildScopeImpl +import com.android.systemui.kairos.internal.Network +import com.android.systemui.kairos.internal.StateScopeImpl +import com.android.systemui.kairos.internal.util.awaitCancellationAndThen +import com.android.systemui.kairos.internal.util.childScope import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.coroutineContext diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/FrpScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpScope.kt index a5a7977f2177..ad6b2c8d04eb 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/FrpScope.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpScope.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp +package com.android.systemui.kairos import kotlin.coroutines.RestrictsSuspension import kotlin.coroutines.resume diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/FrpStateScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpStateScope.kt index 61336f4f4608..c7ea6808a53e 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/FrpStateScope.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpStateScope.kt @@ -14,20 +14,20 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp - -import com.android.systemui.experimental.frp.combine as combinePure -import com.android.systemui.experimental.frp.map as mapPure -import com.android.systemui.experimental.frp.util.Just -import com.android.systemui.experimental.frp.util.Left -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.Right -import com.android.systemui.experimental.frp.util.WithPrev -import com.android.systemui.experimental.frp.util.just -import com.android.systemui.experimental.frp.util.map -import com.android.systemui.experimental.frp.util.none -import com.android.systemui.experimental.frp.util.partitionEithers -import com.android.systemui.experimental.frp.util.zipWith +package com.android.systemui.kairos + +import com.android.systemui.kairos.combine as combinePure +import com.android.systemui.kairos.map as mapPure +import com.android.systemui.kairos.util.Just +import com.android.systemui.kairos.util.Left +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.Right +import com.android.systemui.kairos.util.WithPrev +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.map +import com.android.systemui.kairos.util.none +import com.android.systemui.kairos.util.partitionEithers +import com.android.systemui.kairos.util.zipWith import kotlin.coroutines.RestrictsSuspension typealias FrpStateful<R> = suspend FrpStateScope.() -> R @@ -715,7 +715,7 @@ interface FrpStateScope : FrpTransactionScope { stateB: TState<B>, transform: suspend FrpTransactionScope.(A, B) -> Z, ): TState<Z> = - com.android.systemui.experimental.frp + com.android.systemui.kairos .combine(stateA, stateB) { a, b -> transactionally { transform(a, b) } } .sampleTransactionals() @@ -733,7 +733,7 @@ interface FrpStateScope : FrpTransactionScope { stateD: TState<D>, transform: suspend FrpTransactionScope.(A, B, C, D) -> Z, ): TState<Z> = - com.android.systemui.experimental.frp + com.android.systemui.kairos .combine(stateA, stateB, stateC, stateD) { a, b, c, d -> transactionally { transform(a, b, c, d) } } diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/FrpTransactionScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpTransactionScope.kt index b0b9dbcbe8c1..a7ae1d9646b3 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/FrpTransactionScope.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpTransactionScope.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp +package com.android.systemui.kairos import kotlin.coroutines.RestrictsSuspension diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/TFlow.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TFlow.kt index cca6c9a623f2..7ba1aca31eae 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/TFlow.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TFlow.kt @@ -14,36 +14,36 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp - -import com.android.systemui.experimental.frp.internal.DemuxImpl -import com.android.systemui.experimental.frp.internal.Init -import com.android.systemui.experimental.frp.internal.InitScope -import com.android.systemui.experimental.frp.internal.InputNode -import com.android.systemui.experimental.frp.internal.Network -import com.android.systemui.experimental.frp.internal.NoScope -import com.android.systemui.experimental.frp.internal.TFlowImpl -import com.android.systemui.experimental.frp.internal.activated -import com.android.systemui.experimental.frp.internal.cached -import com.android.systemui.experimental.frp.internal.constInit -import com.android.systemui.experimental.frp.internal.filterNode -import com.android.systemui.experimental.frp.internal.init -import com.android.systemui.experimental.frp.internal.map -import com.android.systemui.experimental.frp.internal.mapImpl -import com.android.systemui.experimental.frp.internal.mapMaybeNode -import com.android.systemui.experimental.frp.internal.mergeNodes -import com.android.systemui.experimental.frp.internal.mergeNodesLeft -import com.android.systemui.experimental.frp.internal.neverImpl -import com.android.systemui.experimental.frp.internal.switchDeferredImplSingle -import com.android.systemui.experimental.frp.internal.switchPromptImpl -import com.android.systemui.experimental.frp.internal.util.hashString -import com.android.systemui.experimental.frp.util.Either -import com.android.systemui.experimental.frp.util.Left -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.Right -import com.android.systemui.experimental.frp.util.just -import com.android.systemui.experimental.frp.util.map -import com.android.systemui.experimental.frp.util.toMaybe +package com.android.systemui.kairos + +import com.android.systemui.kairos.internal.DemuxImpl +import com.android.systemui.kairos.internal.Init +import com.android.systemui.kairos.internal.InitScope +import com.android.systemui.kairos.internal.InputNode +import com.android.systemui.kairos.internal.Network +import com.android.systemui.kairos.internal.NoScope +import com.android.systemui.kairos.internal.TFlowImpl +import com.android.systemui.kairos.internal.activated +import com.android.systemui.kairos.internal.cached +import com.android.systemui.kairos.internal.constInit +import com.android.systemui.kairos.internal.filterNode +import com.android.systemui.kairos.internal.init +import com.android.systemui.kairos.internal.map +import com.android.systemui.kairos.internal.mapImpl +import com.android.systemui.kairos.internal.mapMaybeNode +import com.android.systemui.kairos.internal.mergeNodes +import com.android.systemui.kairos.internal.mergeNodesLeft +import com.android.systemui.kairos.internal.neverImpl +import com.android.systemui.kairos.internal.switchDeferredImplSingle +import com.android.systemui.kairos.internal.switchPromptImpl +import com.android.systemui.kairos.internal.util.hashString +import com.android.systemui.kairos.util.Either +import com.android.systemui.kairos.util.Left +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.Right +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.map +import com.android.systemui.kairos.util.toMaybe import java.util.concurrent.atomic.AtomicReference import kotlin.reflect.KProperty import kotlinx.coroutines.CompletableDeferred diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/TState.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TState.kt index a5ec503e5c8d..a4c695657f8d 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/TState.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TState.kt @@ -14,29 +14,29 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp - -import com.android.systemui.experimental.frp.internal.DerivedMapCheap -import com.android.systemui.experimental.frp.internal.Init -import com.android.systemui.experimental.frp.internal.InitScope -import com.android.systemui.experimental.frp.internal.Network -import com.android.systemui.experimental.frp.internal.NoScope -import com.android.systemui.experimental.frp.internal.Schedulable -import com.android.systemui.experimental.frp.internal.TFlowImpl -import com.android.systemui.experimental.frp.internal.TStateImpl -import com.android.systemui.experimental.frp.internal.TStateSource -import com.android.systemui.experimental.frp.internal.activated -import com.android.systemui.experimental.frp.internal.cached -import com.android.systemui.experimental.frp.internal.constInit -import com.android.systemui.experimental.frp.internal.constS -import com.android.systemui.experimental.frp.internal.filterNode -import com.android.systemui.experimental.frp.internal.flatMap -import com.android.systemui.experimental.frp.internal.init -import com.android.systemui.experimental.frp.internal.map -import com.android.systemui.experimental.frp.internal.mapCheap -import com.android.systemui.experimental.frp.internal.mapImpl -import com.android.systemui.experimental.frp.internal.util.hashString -import com.android.systemui.experimental.frp.internal.zipStates +package com.android.systemui.kairos + +import com.android.systemui.kairos.internal.DerivedMapCheap +import com.android.systemui.kairos.internal.Init +import com.android.systemui.kairos.internal.InitScope +import com.android.systemui.kairos.internal.Network +import com.android.systemui.kairos.internal.NoScope +import com.android.systemui.kairos.internal.Schedulable +import com.android.systemui.kairos.internal.TFlowImpl +import com.android.systemui.kairos.internal.TStateImpl +import com.android.systemui.kairos.internal.TStateSource +import com.android.systemui.kairos.internal.activated +import com.android.systemui.kairos.internal.cached +import com.android.systemui.kairos.internal.constInit +import com.android.systemui.kairos.internal.constS +import com.android.systemui.kairos.internal.filterNode +import com.android.systemui.kairos.internal.flatMap +import com.android.systemui.kairos.internal.init +import com.android.systemui.kairos.internal.map +import com.android.systemui.kairos.internal.mapCheap +import com.android.systemui.kairos.internal.mapImpl +import com.android.systemui.kairos.internal.util.hashString +import com.android.systemui.kairos.internal.zipStates import kotlin.reflect.KProperty import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Deferred diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/Transactional.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Transactional.kt index 0e7b420afd51..6b1c8c8fc3e5 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/Transactional.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Transactional.kt @@ -14,14 +14,14 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp +package com.android.systemui.kairos -import com.android.systemui.experimental.frp.internal.InitScope -import com.android.systemui.experimental.frp.internal.NoScope -import com.android.systemui.experimental.frp.internal.TransactionalImpl -import com.android.systemui.experimental.frp.internal.init -import com.android.systemui.experimental.frp.internal.transactionalImpl -import com.android.systemui.experimental.frp.internal.util.hashString +import com.android.systemui.kairos.internal.InitScope +import com.android.systemui.kairos.internal.NoScope +import com.android.systemui.kairos.internal.TransactionalImpl +import com.android.systemui.kairos.internal.init +import com.android.systemui.kairos.internal.transactionalImpl +import com.android.systemui.kairos.internal.util.hashString import kotlinx.coroutines.CompletableDeferred /** diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/debug/Debug.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/debug/Debug.kt index 806234184d81..4f302a14ff00 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/debug/Debug.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/debug/Debug.kt @@ -14,25 +14,25 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.debug - -import com.android.systemui.experimental.frp.MutableTState -import com.android.systemui.experimental.frp.TState -import com.android.systemui.experimental.frp.TStateInit -import com.android.systemui.experimental.frp.TStateLoop -import com.android.systemui.experimental.frp.internal.DerivedFlatten -import com.android.systemui.experimental.frp.internal.DerivedMap -import com.android.systemui.experimental.frp.internal.DerivedMapCheap -import com.android.systemui.experimental.frp.internal.DerivedZipped -import com.android.systemui.experimental.frp.internal.Init -import com.android.systemui.experimental.frp.internal.TStateDerived -import com.android.systemui.experimental.frp.internal.TStateImpl -import com.android.systemui.experimental.frp.internal.TStateSource -import com.android.systemui.experimental.frp.util.Just -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.None -import com.android.systemui.experimental.frp.util.none -import com.android.systemui.experimental.frp.util.orElseGet +package com.android.systemui.kairos.debug + +import com.android.systemui.kairos.MutableTState +import com.android.systemui.kairos.TState +import com.android.systemui.kairos.TStateInit +import com.android.systemui.kairos.TStateLoop +import com.android.systemui.kairos.internal.DerivedFlatten +import com.android.systemui.kairos.internal.DerivedMap +import com.android.systemui.kairos.internal.DerivedMapCheap +import com.android.systemui.kairos.internal.DerivedZipped +import com.android.systemui.kairos.internal.Init +import com.android.systemui.kairos.internal.TStateDerived +import com.android.systemui.kairos.internal.TStateImpl +import com.android.systemui.kairos.internal.TStateSource +import com.android.systemui.kairos.util.Just +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.None +import com.android.systemui.kairos.util.none +import com.android.systemui.kairos.util.orElseGet // object IdGen { // private val counter = AtomicLong() diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/BuildScopeImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/BuildScopeImpl.kt index 127abd857fb3..90f1aea3e42f 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/BuildScopeImpl.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/BuildScopeImpl.kt @@ -14,34 +14,34 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.CoalescingMutableTFlow -import com.android.systemui.experimental.frp.FrpBuildScope -import com.android.systemui.experimental.frp.FrpCoalescingProducerScope -import com.android.systemui.experimental.frp.FrpDeferredValue -import com.android.systemui.experimental.frp.FrpEffectScope -import com.android.systemui.experimental.frp.FrpNetwork -import com.android.systemui.experimental.frp.FrpProducerScope -import com.android.systemui.experimental.frp.FrpSpec -import com.android.systemui.experimental.frp.FrpStateScope -import com.android.systemui.experimental.frp.FrpTransactionScope -import com.android.systemui.experimental.frp.GroupedTFlow -import com.android.systemui.experimental.frp.LocalFrpNetwork -import com.android.systemui.experimental.frp.MutableTFlow -import com.android.systemui.experimental.frp.TFlow -import com.android.systemui.experimental.frp.TFlowInit -import com.android.systemui.experimental.frp.groupByKey -import com.android.systemui.experimental.frp.init -import com.android.systemui.experimental.frp.internal.util.childScope -import com.android.systemui.experimental.frp.internal.util.launchOnCancel -import com.android.systemui.experimental.frp.internal.util.mapValuesParallel -import com.android.systemui.experimental.frp.launchEffect -import com.android.systemui.experimental.frp.util.Just -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.None -import com.android.systemui.experimental.frp.util.just -import com.android.systemui.experimental.frp.util.map +import com.android.systemui.kairos.CoalescingMutableTFlow +import com.android.systemui.kairos.FrpBuildScope +import com.android.systemui.kairos.FrpCoalescingProducerScope +import com.android.systemui.kairos.FrpDeferredValue +import com.android.systemui.kairos.FrpEffectScope +import com.android.systemui.kairos.FrpNetwork +import com.android.systemui.kairos.FrpProducerScope +import com.android.systemui.kairos.FrpSpec +import com.android.systemui.kairos.FrpStateScope +import com.android.systemui.kairos.FrpTransactionScope +import com.android.systemui.kairos.GroupedTFlow +import com.android.systemui.kairos.LocalFrpNetwork +import com.android.systemui.kairos.MutableTFlow +import com.android.systemui.kairos.TFlow +import com.android.systemui.kairos.TFlowInit +import com.android.systemui.kairos.groupByKey +import com.android.systemui.kairos.init +import com.android.systemui.kairos.internal.util.childScope +import com.android.systemui.kairos.internal.util.launchOnCancel +import com.android.systemui.kairos.internal.util.mapValuesParallel +import com.android.systemui.kairos.launchEffect +import com.android.systemui.kairos.util.Just +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.None +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.map import java.util.concurrent.atomic.AtomicReference import kotlin.coroutines.Continuation import kotlin.coroutines.CoroutineContext diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/DeferScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/DeferScope.kt index f72ba5fdfc6f..f65307c6106f 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/DeferScope.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/DeferScope.kt @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.internal.util.asyncImmediate -import com.android.systemui.experimental.frp.internal.util.launchImmediate +import com.android.systemui.kairos.internal.util.asyncImmediate +import com.android.systemui.kairos.internal.util.launchImmediate import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Demux.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Demux.kt index 418220f2da4d..e7b99528fdfc 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Demux.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Demux.kt @@ -16,13 +16,13 @@ @file:Suppress("NOTHING_TO_INLINE") -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.internal.util.hashString -import com.android.systemui.experimental.frp.util.Just -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.flatMap -import com.android.systemui.experimental.frp.util.getMaybe +import com.android.systemui.kairos.internal.util.hashString +import com.android.systemui.kairos.util.Just +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.flatMap +import com.android.systemui.kairos.util.getMaybe import java.util.concurrent.ConcurrentHashMap import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.async diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/EvalScopeImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/EvalScopeImpl.kt index 38bc22f1df80..815473fe900f 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/EvalScopeImpl.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/EvalScopeImpl.kt @@ -14,20 +14,20 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal - -import com.android.systemui.experimental.frp.FrpDeferredValue -import com.android.systemui.experimental.frp.FrpTransactionScope -import com.android.systemui.experimental.frp.TFlow -import com.android.systemui.experimental.frp.TFlowInit -import com.android.systemui.experimental.frp.TFlowLoop -import com.android.systemui.experimental.frp.TState -import com.android.systemui.experimental.frp.TStateInit -import com.android.systemui.experimental.frp.Transactional -import com.android.systemui.experimental.frp.emptyTFlow -import com.android.systemui.experimental.frp.init -import com.android.systemui.experimental.frp.mapCheap -import com.android.systemui.experimental.frp.switch +package com.android.systemui.kairos.internal + +import com.android.systemui.kairos.FrpDeferredValue +import com.android.systemui.kairos.FrpTransactionScope +import com.android.systemui.kairos.TFlow +import com.android.systemui.kairos.TFlowInit +import com.android.systemui.kairos.TFlowLoop +import com.android.systemui.kairos.TState +import com.android.systemui.kairos.TStateInit +import com.android.systemui.kairos.Transactional +import com.android.systemui.kairos.emptyTFlow +import com.android.systemui.kairos.init +import com.android.systemui.kairos.mapCheap +import com.android.systemui.kairos.switch import kotlin.coroutines.Continuation import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/FilterNode.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/FilterNode.kt index 4f2a76999bb6..bc06a3679d5c 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/FilterNode.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/FilterNode.kt @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.util.Just -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.just -import com.android.systemui.experimental.frp.util.none +import com.android.systemui.kairos.util.Just +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.none internal inline fun <A, B> mapMaybeNode( crossinline getPulse: suspend EvalScope.() -> TFlowImpl<A>, diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Graph.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Graph.kt index 9425870738fc..3aec319881d0 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Graph.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Graph.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.internal.util.Bag +import com.android.systemui.kairos.internal.util.Bag import java.util.TreeMap import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Init.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Init.kt index efb7a0951737..57db9a493e21 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Init.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Init.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.just -import com.android.systemui.experimental.frp.util.none +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.none import java.util.concurrent.atomic.AtomicBoolean import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.ExperimentalCoroutinesApi diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Inputs.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Inputs.kt index 85c87fea299b..8efaf79b18b2 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Inputs.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Inputs.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.internal.util.Key -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.just +import com.android.systemui.kairos.internal.util.Key +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.just import java.util.concurrent.atomic.AtomicBoolean import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.sync.Mutex diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/InternalScopes.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/InternalScopes.kt index b6cd9063622b..af864e6c3496 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/InternalScopes.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/InternalScopes.kt @@ -14,15 +14,15 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal - -import com.android.systemui.experimental.frp.FrpBuildScope -import com.android.systemui.experimental.frp.FrpStateScope -import com.android.systemui.experimental.frp.FrpTransactionScope -import com.android.systemui.experimental.frp.TFlow -import com.android.systemui.experimental.frp.internal.util.HeteroMap -import com.android.systemui.experimental.frp.internal.util.Key -import com.android.systemui.experimental.frp.util.Maybe +package com.android.systemui.kairos.internal + +import com.android.systemui.kairos.FrpBuildScope +import com.android.systemui.kairos.FrpStateScope +import com.android.systemui.kairos.FrpTransactionScope +import com.android.systemui.kairos.TFlow +import com.android.systemui.kairos.internal.util.HeteroMap +import com.android.systemui.kairos.internal.util.Key +import com.android.systemui.kairos.util.Maybe internal interface InitScope { val networkId: Any diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Mux.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Mux.kt index e616d625dd1c..f7ff15f0507b 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Mux.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Mux.kt @@ -16,11 +16,11 @@ @file:Suppress("NOTHING_TO_INLINE") -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.internal.util.ConcurrentNullableHashMap -import com.android.systemui.experimental.frp.internal.util.hashString -import com.android.systemui.experimental.frp.util.Just +import com.android.systemui.kairos.internal.util.ConcurrentNullableHashMap +import com.android.systemui.kairos.internal.util.hashString +import com.android.systemui.kairos.util.Just import java.util.concurrent.ConcurrentHashMap import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.sync.Mutex diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/MuxDeferred.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/MuxDeferred.kt index 6d43285c9ef5..08bee855831a 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/MuxDeferred.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/MuxDeferred.kt @@ -14,28 +14,28 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal - -import com.android.systemui.experimental.frp.internal.util.Key -import com.android.systemui.experimental.frp.internal.util.associateByIndexTo -import com.android.systemui.experimental.frp.internal.util.hashString -import com.android.systemui.experimental.frp.internal.util.mapParallel -import com.android.systemui.experimental.frp.internal.util.mapValuesNotNullParallelTo -import com.android.systemui.experimental.frp.util.Just -import com.android.systemui.experimental.frp.util.Left -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.None -import com.android.systemui.experimental.frp.util.Right -import com.android.systemui.experimental.frp.util.These -import com.android.systemui.experimental.frp.util.flatMap -import com.android.systemui.experimental.frp.util.getMaybe -import com.android.systemui.experimental.frp.util.just -import com.android.systemui.experimental.frp.util.maybeThat -import com.android.systemui.experimental.frp.util.maybeThis -import com.android.systemui.experimental.frp.util.merge -import com.android.systemui.experimental.frp.util.orElseGet -import com.android.systemui.experimental.frp.util.partitionEithers -import com.android.systemui.experimental.frp.util.these +package com.android.systemui.kairos.internal + +import com.android.systemui.kairos.internal.util.Key +import com.android.systemui.kairos.internal.util.associateByIndexTo +import com.android.systemui.kairos.internal.util.hashString +import com.android.systemui.kairos.internal.util.mapParallel +import com.android.systemui.kairos.internal.util.mapValuesNotNullParallelTo +import com.android.systemui.kairos.util.Just +import com.android.systemui.kairos.util.Left +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.None +import com.android.systemui.kairos.util.Right +import com.android.systemui.kairos.util.These +import com.android.systemui.kairos.util.flatMap +import com.android.systemui.kairos.util.getMaybe +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.maybeThat +import com.android.systemui.kairos.util.maybeThis +import com.android.systemui.kairos.util.merge +import com.android.systemui.kairos.util.orElseGet +import com.android.systemui.kairos.util.partitionEithers +import com.android.systemui.kairos.util.these import java.util.TreeMap import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/MuxPrompt.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/MuxPrompt.kt index ea0c1501f6a4..cdfafa943121 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/MuxPrompt.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/MuxPrompt.kt @@ -14,20 +14,20 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal - -import com.android.systemui.experimental.frp.internal.util.Key -import com.android.systemui.experimental.frp.internal.util.launchImmediate -import com.android.systemui.experimental.frp.internal.util.mapParallel -import com.android.systemui.experimental.frp.internal.util.mapValuesNotNullParallelTo -import com.android.systemui.experimental.frp.util.Just -import com.android.systemui.experimental.frp.util.Left -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.None -import com.android.systemui.experimental.frp.util.Right -import com.android.systemui.experimental.frp.util.filterJust -import com.android.systemui.experimental.frp.util.map -import com.android.systemui.experimental.frp.util.partitionEithers +package com.android.systemui.kairos.internal + +import com.android.systemui.kairos.internal.util.Key +import com.android.systemui.kairos.internal.util.launchImmediate +import com.android.systemui.kairos.internal.util.mapParallel +import com.android.systemui.kairos.internal.util.mapValuesNotNullParallelTo +import com.android.systemui.kairos.util.Just +import com.android.systemui.kairos.util.Left +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.None +import com.android.systemui.kairos.util.Right +import com.android.systemui.kairos.util.filterJust +import com.android.systemui.kairos.util.map +import com.android.systemui.kairos.util.partitionEithers import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Network.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Network.kt index b5ffe75eb9f4..f0df89d780c9 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Network.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Network.kt @@ -14,14 +14,14 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal - -import com.android.systemui.experimental.frp.TState -import com.android.systemui.experimental.frp.internal.util.HeteroMap -import com.android.systemui.experimental.frp.util.Just -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.just -import com.android.systemui.experimental.frp.util.none +package com.android.systemui.kairos.internal + +import com.android.systemui.kairos.TState +import com.android.systemui.kairos.internal.util.HeteroMap +import com.android.systemui.kairos.util.Just +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.none import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentLinkedDeque import java.util.concurrent.ConcurrentLinkedQueue diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/NoScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/NoScope.kt index 6375918f35cd..fbd9689eb1d0 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/NoScope.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/NoScope.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.FrpScope +import com.android.systemui.kairos.FrpScope import kotlin.coroutines.Continuation import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/NodeTypes.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/NodeTypes.kt index e7f76a08b638..000240796a82 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/NodeTypes.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/NodeTypes.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.util.Maybe +import com.android.systemui.kairos.util.Maybe /* Dmux diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Output.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Output.kt index e60dccaac392..a3af2d304f7f 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Output.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Output.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.util.Just +import com.android.systemui.kairos.util.Just import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/PullNodes.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/PullNodes.kt index b4656e0aee3a..dac98e0e807c 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/PullNodes.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/PullNodes.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.internal.util.Key -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.map +import com.android.systemui.kairos.internal.util.Key +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.map import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Deferred diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Scheduler.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Scheduler.kt index 4fef865e87e7..872fb7a6cb74 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/Scheduler.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Scheduler.kt @@ -16,7 +16,7 @@ @file:OptIn(ExperimentalCoroutinesApi::class) -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.PriorityBlockingQueue diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/StateScopeImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/StateScopeImpl.kt index c1d10760978a..baf4101d52ef 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/StateScopeImpl.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/StateScopeImpl.kt @@ -14,27 +14,27 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.FrpDeferredValue -import com.android.systemui.experimental.frp.FrpStateScope -import com.android.systemui.experimental.frp.FrpStateful -import com.android.systemui.experimental.frp.FrpTransactionScope -import com.android.systemui.experimental.frp.GroupedTFlow -import com.android.systemui.experimental.frp.TFlow -import com.android.systemui.experimental.frp.TFlowInit -import com.android.systemui.experimental.frp.TFlowLoop -import com.android.systemui.experimental.frp.TState -import com.android.systemui.experimental.frp.TStateInit -import com.android.systemui.experimental.frp.emptyTFlow -import com.android.systemui.experimental.frp.groupByKey -import com.android.systemui.experimental.frp.init -import com.android.systemui.experimental.frp.internal.util.mapValuesParallel -import com.android.systemui.experimental.frp.mapCheap -import com.android.systemui.experimental.frp.merge -import com.android.systemui.experimental.frp.switch -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.map +import com.android.systemui.kairos.FrpDeferredValue +import com.android.systemui.kairos.FrpStateScope +import com.android.systemui.kairos.FrpStateful +import com.android.systemui.kairos.FrpTransactionScope +import com.android.systemui.kairos.GroupedTFlow +import com.android.systemui.kairos.TFlow +import com.android.systemui.kairos.TFlowInit +import com.android.systemui.kairos.TFlowLoop +import com.android.systemui.kairos.TState +import com.android.systemui.kairos.TStateInit +import com.android.systemui.kairos.emptyTFlow +import com.android.systemui.kairos.groupByKey +import com.android.systemui.kairos.init +import com.android.systemui.kairos.internal.util.mapValuesParallel +import com.android.systemui.kairos.mapCheap +import com.android.systemui.kairos.merge +import com.android.systemui.kairos.switch +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.map import kotlin.coroutines.Continuation import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/TFlowImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TFlowImpl.kt index 79978640d5a8..b904b48f7f9c 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/TFlowImpl.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TFlowImpl.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.util.Maybe +import com.android.systemui.kairos.util.Maybe /* Initialized TFlow */ internal fun interface TFlowImpl<out A> { diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/TStateImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TStateImpl.kt index d8b6dac000bb..5cec05c8ef2d 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/TStateImpl.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TStateImpl.kt @@ -14,16 +14,16 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal - -import com.android.systemui.experimental.frp.internal.util.Key -import com.android.systemui.experimental.frp.internal.util.associateByIndex -import com.android.systemui.experimental.frp.internal.util.hashString -import com.android.systemui.experimental.frp.internal.util.mapValuesParallel -import com.android.systemui.experimental.frp.util.Just -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.just -import com.android.systemui.experimental.frp.util.none +package com.android.systemui.kairos.internal + +import com.android.systemui.kairos.internal.util.Key +import com.android.systemui.kairos.internal.util.associateByIndex +import com.android.systemui.kairos.internal.util.hashString +import com.android.systemui.kairos.internal.util.mapValuesParallel +import com.android.systemui.kairos.util.Just +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.none import java.util.concurrent.atomic.AtomicLong import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineStart diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/TransactionalImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TransactionalImpl.kt index c3f80a179684..8647bdd5b7b1 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/TransactionalImpl.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TransactionalImpl.kt @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal +package com.android.systemui.kairos.internal -import com.android.systemui.experimental.frp.internal.util.Key -import com.android.systemui.experimental.frp.internal.util.hashString +import com.android.systemui.kairos.internal.util.Key +import com.android.systemui.kairos.internal.util.hashString import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Deferred diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/util/Bag.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/Bag.kt index cc5538e5c87c..47185195a2bb 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/util/Bag.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/Bag.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal.util +package com.android.systemui.kairos.internal.util internal class Bag<T> private constructor(private val intMap: MutableMap<T, Int>) : Set<T> by intMap.keys { diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/util/ConcurrentNullableHashMap.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/ConcurrentNullableHashMap.kt index 449aa19be635..6c8ae7cf6436 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/util/ConcurrentNullableHashMap.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/ConcurrentNullableHashMap.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal.util +package com.android.systemui.kairos.internal.util import java.util.concurrent.ConcurrentHashMap diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/util/HeteroMap.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/HeteroMap.kt index 14a567ca67c8..5cee2dd5880a 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/util/HeteroMap.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/HeteroMap.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal.util +package com.android.systemui.kairos.internal.util -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.None -import com.android.systemui.experimental.frp.util.just +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.None +import com.android.systemui.kairos.util.just import java.util.concurrent.ConcurrentHashMap internal interface Key<A> diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/util/MapUtils.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/MapUtils.kt index 6f19a76f8900..ebf9a66be0ae 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/util/MapUtils.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/MapUtils.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.internal.util +package com.android.systemui.kairos.internal.util import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.async diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/util/Util.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/Util.kt index 0a47429d4113..6bb7f9f593aa 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/internal/util/Util.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/Util.kt @@ -16,7 +16,7 @@ @file:OptIn(ExperimentalCoroutinesApi::class) -package com.android.systemui.experimental.frp.internal.util +package com.android.systemui.kairos.internal.util import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/util/Either.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/Either.kt index dca8364ed8ef..ad9f7d715156 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/util/Either.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/Either.kt @@ -16,7 +16,7 @@ @file:Suppress("NOTHING_TO_INLINE") -package com.android.systemui.experimental.frp.util +package com.android.systemui.kairos.util /** * Contains a value of two possibilities: `Left<A>` or `Right<B>` diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/util/Maybe.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/Maybe.kt index 59c680e91a52..c3cae3885bd3 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/util/Maybe.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/Maybe.kt @@ -16,7 +16,7 @@ @file:Suppress("NOTHING_TO_INLINE", "SuspendCoroutine") -package com.android.systemui.experimental.frp.util +package com.android.systemui.kairos.util import kotlin.coroutines.Continuation import kotlin.coroutines.CoroutineContext diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/util/These.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/These.kt index 5404c0795af8..aa95e0d2dc1b 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/util/These.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/These.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.util +package com.android.systemui.kairos.util /** Contains at least one of two potential values. */ sealed class These<A, B> { diff --git a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/util/WithPrev.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/WithPrev.kt index e52a6e166ec5..5cfaa3ea2801 100644 --- a/packages/SystemUI/frp/src/com/android/systemui/experimental/frp/util/WithPrev.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/WithPrev.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.experimental.frp.util +package com.android.systemui.kairos.util /** Holds a [newValue] emitted from a `TFlow`, along with the [previousValue] emitted value. */ data class WithPrev<out S, out T : S>(val previousValue: S, val newValue: T) diff --git a/packages/SystemUI/frp/test/com/android/systemui/experimental/frp/FrpTests.kt b/packages/SystemUI/utils/kairos/test/com/android/systemui/kairos/KairosTests.kt index a58f4995138a..165230b2aeaf 100644 --- a/packages/SystemUI/frp/test/com/android/systemui/experimental/frp/FrpTests.kt +++ b/packages/SystemUI/utils/kairos/test/com/android/systemui/kairos/KairosTests.kt @@ -16,17 +16,17 @@ @file:OptIn(ExperimentalCoroutinesApi::class, ExperimentalFrpApi::class) -package com.android.systemui.experimental.frp - -import com.android.systemui.experimental.frp.util.Either -import com.android.systemui.experimental.frp.util.Left -import com.android.systemui.experimental.frp.util.Maybe -import com.android.systemui.experimental.frp.util.None -import com.android.systemui.experimental.frp.util.Right -import com.android.systemui.experimental.frp.util.just -import com.android.systemui.experimental.frp.util.map -import com.android.systemui.experimental.frp.util.maybe -import com.android.systemui.experimental.frp.util.none +package com.android.systemui.kairos + +import com.android.systemui.kairos.util.Either +import com.android.systemui.kairos.util.Left +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.None +import com.android.systemui.kairos.util.Right +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.map +import com.android.systemui.kairos.util.maybe +import com.android.systemui.kairos.util.none import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds import kotlin.time.DurationUnit @@ -55,7 +55,7 @@ import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Test -class FrpTests { +class KairosTests { @Test fun basic() = runFrpTest { network -> diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto index 994bdb58f543..648990588d29 100644 --- a/proto/src/system_messages.proto +++ b/proto/src/system_messages.proto @@ -206,7 +206,7 @@ message SystemMessage { // Inform that DND settings have changed on OS upgrade // Package: android - NOTE_ZEN_UPGRADE = 48; + NOTE_ZEN_UPGRADE = 48 [deprecated = true]; // Notification to suggest automatic battery saver. // Package: android diff --git a/ravenwood/TEST_MAPPING b/ravenwood/TEST_MAPPING index 86246e2dcc2a..72f62c5c29ee 100644 --- a/ravenwood/TEST_MAPPING +++ b/ravenwood/TEST_MAPPING @@ -5,7 +5,8 @@ { "name": "hoststubgen-test-tiny-test" }, { "name": "hoststubgen-invoke-test" }, { "name": "RavenwoodMockitoTest_device" }, - { "name": "RavenwoodBivalentTest_device" }, + // TODO(b/371215487): Re-enable when the test is fixed. + // { "name": "RavenwoodBivalentTest_device" }, { "name": "RavenwoodBivalentInstTest_nonself_inst" }, { "name": "RavenwoodBivalentInstTest_self_inst_device" }, diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java index 6e73b2cc5486..644babb8984d 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java @@ -21,6 +21,8 @@ import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_RESOUR import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERSION_JAVA_SYSPROP; +import static org.junit.Assert.assertThrows; + import android.app.ActivityManager; import android.app.Instrumentation; import android.app.ResourcesManager; @@ -167,6 +169,8 @@ public class RavenwoodRuntimeEnvironmentController { // This will let AndroidJUnit4 use the original runner. System.setProperty("android.junit.runner", "androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner"); + + assertMockitoVersion(); } /** @@ -377,6 +381,28 @@ public class RavenwoodRuntimeEnvironmentController { } } + private static final String MOCKITO_ERROR = "FATAL: Unsupported Mockito detected!" + + " Your test or its dependencies use one of the \"mockito-target-*\"" + + " modules as static library, which is unusable on host side." + + " Please switch over to use \"mockito-ravenwood-prebuilt\" as shared library, or" + + " as a last resort, set `ravenizer: { strip_mockito: true }` in your test module."; + + /** + * Assert the Mockito version at runtime to ensure no incorrect Mockito classes are loaded. + */ + private static void assertMockitoVersion() { + // DexMaker should not exist + assertThrows( + MOCKITO_ERROR, + ClassNotFoundException.class, + () -> Class.forName("com.android.dx.DexMaker")); + // Mockito 2 should not exist + assertThrows( + MOCKITO_ERROR, + ClassNotFoundException.class, + () -> Class.forName("org.mockito.Matchers")); + } + @SuppressWarnings("unused") // Called from native code (ravenwood_sysprop.cpp) private static void checkSystemPropertyAccess(String key, boolean write) { boolean result = write ? sProps.isKeyWritable(key) : sProps.isKeyReadable(key); diff --git a/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java b/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java index ef795c63880e..520f050f0655 100644 --- a/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java +++ b/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java @@ -37,8 +37,6 @@ public class RavenwoodCommonUtils { private RavenwoodCommonUtils() { } - private static final Object sLock = new Object(); - /** * If set to "1", we enable the verbose logging. * @@ -68,9 +66,6 @@ public class RavenwoodCommonUtils { public static final String RAVENWOOD_VERSION_JAVA_SYSPROP = "android.ravenwood.version"; - // @GuardedBy("sLock") - private static boolean sIntegrityChecked = false; - /** * @return if we're running on Ravenwood. */ diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java index 4e7dc5d6264f..ad86135de32e 100644 --- a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java +++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java @@ -32,25 +32,20 @@ public class NativeAllocationRegistry { public static NativeAllocationRegistry createNonmalloced( ClassLoader classLoader, long freeFunction, long size) { - return new NativeAllocationRegistry(classLoader, freeFunction, size, false); + return new NativeAllocationRegistry(classLoader, freeFunction, size); } public static NativeAllocationRegistry createMalloced( ClassLoader classLoader, long freeFunction, long size) { - return new NativeAllocationRegistry(classLoader, freeFunction, size, true); + return new NativeAllocationRegistry(classLoader, freeFunction, size); } public static NativeAllocationRegistry createMalloced( ClassLoader classLoader, long freeFunction) { - return new NativeAllocationRegistry(classLoader, freeFunction, 0, true); + return new NativeAllocationRegistry(classLoader, freeFunction, 0); } public NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size) { - this(classLoader, freeFunction, size, size == 0); - } - - private NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size, - boolean mallocAllocation) { if (size < 0) { throw new IllegalArgumentException("Invalid native allocation size: " + size); } diff --git a/ravenwood/bivalenttest/Android.bp b/ravenwood/tests/bivalenttest/Android.bp index e897735493a3..ac499b966afe 100644 --- a/ravenwood/bivalenttest/Android.bp +++ b/ravenwood/tests/bivalenttest/Android.bp @@ -54,32 +54,34 @@ android_ravenwood_test { auto_gen_config: true, } -android_test { - name: "RavenwoodBivalentTest_device", +// TODO(b/371215487): migrate bivalenttest.ravenizer tests to another architecture - srcs: [ - "test/**/*.java", - ], - static_libs: [ - "junit", - "truth", - - "androidx.annotation_annotation", - "androidx.test.ext.junit", - "androidx.test.rules", - - "junit-params", - "platform-parametric-runner-lib", - - "ravenwood-junit", - ], - jni_libs: [ - "libravenwoodbivalenttest_jni", - ], - test_suites: [ - "device-tests", - ], - optimize: { - enabled: false, - }, -} +// android_test { +// name: "RavenwoodBivalentTest_device", +// +// srcs: [ +// "test/**/*.java", +// ], +// static_libs: [ +// "junit", +// "truth", +// +// "androidx.annotation_annotation", +// "androidx.test.ext.junit", +// "androidx.test.rules", +// +// "junit-params", +// "platform-parametric-runner-lib", +// +// "ravenwood-junit", +// ], +// jni_libs: [ +// "libravenwoodbivalenttest_jni", +// ], +// test_suites: [ +// "device-tests", +// ], +// optimize: { +// enabled: false, +// }, +// } diff --git a/ravenwood/bivalenttest/AndroidManifest.xml b/ravenwood/tests/bivalenttest/AndroidManifest.xml index 474c03f4f3c9..474c03f4f3c9 100644 --- a/ravenwood/bivalenttest/AndroidManifest.xml +++ b/ravenwood/tests/bivalenttest/AndroidManifest.xml diff --git a/ravenwood/bivalenttest/AndroidTest.xml b/ravenwood/tests/bivalenttest/AndroidTest.xml index 9e5dd11b60cb..9e5dd11b60cb 100644 --- a/ravenwood/bivalenttest/AndroidTest.xml +++ b/ravenwood/tests/bivalenttest/AndroidTest.xml diff --git a/ravenwood/bivalenttest/README.md b/ravenwood/tests/bivalenttest/README.md index 71535556ec75..71535556ec75 100644 --- a/ravenwood/bivalenttest/README.md +++ b/ravenwood/tests/bivalenttest/README.md diff --git a/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp b/ravenwood/tests/bivalenttest/jni/ravenwood_core_test_jni.cpp index 956d79c0d25f..956d79c0d25f 100644 --- a/ravenwood/bivalenttest/jni/ravenwood_core_test_jni.cpp +++ b/ravenwood/tests/bivalenttest/jni/ravenwood_core_test_jni.cpp diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodAndroidApiTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodAndroidApiTest.java index d91e73438fa3..d91e73438fa3 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodAndroidApiTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodAndroidApiTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodClassRuleDeviceOnlyTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodClassRuleDeviceOnlyTest.java index e8f59db86901..e8f59db86901 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodClassRuleDeviceOnlyTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodClassRuleDeviceOnlyTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodConfigTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodConfigTest.java index a5a16c14600b..a5a16c14600b 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodConfigTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodConfigTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java index 0cc2adc6b26b..0cc2adc6b26b 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodJniTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodMultipleRuleTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodMultipleRuleTest.java index c25d2b4cbc4d..c25d2b4cbc4d 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodMultipleRuleTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodMultipleRuleTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNativeAllocationRegistryTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNativeAllocationRegistryTest.java index 415b4676f46b..415b4676f46b 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNativeAllocationRegistryTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNativeAllocationRegistryTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNoConfigNoRuleTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNoConfigNoRuleTest.java index d47330568828..d47330568828 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNoConfigNoRuleTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNoConfigNoRuleTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodRuleTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodRuleTest.java index 3de372e48e3a..3de372e48e3a 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodRuleTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodRuleTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/CallTracker.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/CallTracker.java index 09a0aa8dbaa2..09a0aa8dbaa2 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/CallTracker.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/CallTracker.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodAwareTestRunnerTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodAwareTestRunnerTest.java index d7c2c6cd73a8..d7c2c6cd73a8 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodAwareTestRunnerTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodAwareTestRunnerTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitClassRuleDeviceOnlyTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitClassRuleDeviceOnlyTest.java index 7ef672e80bee..7ef672e80bee 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitClassRuleDeviceOnlyTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitClassRuleDeviceOnlyTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitRuleOrderRewriteTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitRuleOrderRewriteTest.java index 7ef40dc49e1a..7ef40dc49e1a 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitRuleOrderRewriteTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitRuleOrderRewriteTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitRuleShadowingTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitRuleShadowingTest.java index ae596b10848b..ae596b10848b 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitRuleShadowingTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitRuleShadowingTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitRuleShadowingTestBase.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitRuleShadowingTestBase.java index 1ca97af632dd..1ca97af632dd 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitRuleShadowingTestBase.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodImplicitRuleShadowingTestBase.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodNoRavenizerTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodNoRavenizerTest.java index 9d878f444e5e..9d878f444e5e 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodNoRavenizerTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodNoRavenizerTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunDisabledTestsReallyDisabledTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunDisabledTestsReallyDisabledTest.java index c77841b1b55a..c77841b1b55a 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunDisabledTestsReallyDisabledTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunDisabledTestsReallyDisabledTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunDisabledTestsTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunDisabledTestsTest.java index ea1a29d57482..ea1a29d57482 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunDisabledTestsTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunDisabledTestsTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunnerWithAndroidXRunnerTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunnerWithAndroidXRunnerTest.java index c042eb010558..c042eb010558 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunnerWithAndroidXRunnerTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunnerWithAndroidXRunnerTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunnerWithJUnitParamsRunnerTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunnerWithJUnitParamsRunnerTest.java index 2feb5ba9aa01..2feb5ba9aa01 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunnerWithJUnitParamsRunnerTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunnerWithJUnitParamsRunnerTest.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunnerWithParameterizedAndroidJunit4Test.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunnerWithParameterizedAndroidJunit4Test.java index 7e3bc0fccd7f..7e3bc0fccd7f 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunnerWithParameterizedAndroidJunit4Test.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodRunnerWithParameterizedAndroidJunit4Test.java diff --git a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodSuiteTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodSuiteTest.java index 7e396c2080eb..7e396c2080eb 100644 --- a/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodSuiteTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/ravenizer/RavenwoodSuiteTest.java diff --git a/ravenwood/tests/coretest/Android.bp b/ravenwood/tests/coretest/Android.bp index d94475c00240..85f1baf1cab9 100644 --- a/ravenwood/tests/coretest/Android.bp +++ b/ravenwood/tests/coretest/Android.bp @@ -17,9 +17,15 @@ android_ravenwood_test { "junit-params", "platform-parametric-runner-lib", "truth", + + // This library should be removed by Ravenizer + "mockito-target-minus-junit4", ], srcs: [ "test/**/*.java", ], + ravenizer: { + strip_mockito: true, + }, auto_gen_config: true, } diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java new file mode 100644 index 000000000000..31884b6bfc57 --- /dev/null +++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java @@ -0,0 +1,50 @@ +/* + * 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.ravenwoodtest.coretest; + +import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; + +import org.junit.Test; + +public class RavenwoodMockitoTest { + + private static class MockClass { + void foo() { + throw new RuntimeException("Unsupported!!"); + } + } + + @Test + public void checkMockitoClasses() { + // DexMaker should not exist + assertThrows( + ClassNotFoundException.class, + () -> Class.forName("com.android.dx.DexMaker")); + // Mockito 2 should not exist + assertThrows( + ClassNotFoundException.class, + () -> Class.forName("org.mockito.Matchers")); + } + + @Test + public void checkMockitoActuallyWorks() { + var mock = mock(MockClass.class); + doNothing().when(mock).foo(); + mock.foo(); + } +} diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt index f7f9a8563656..e67c730df069 100644 --- a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt +++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt @@ -85,18 +85,17 @@ data class RavenizerStats( /** * Main class. */ -class Ravenizer(val options: RavenizerOptions) { - fun run() { +class Ravenizer { + fun run(options: RavenizerOptions) { val stats = RavenizerStats() - val fatalValidation = options.fatalValidation.get - stats.totalTime = log.nTime { process( options.inJar.get, options.outJar.get, options.enableValidation.get, - fatalValidation, + options.fatalValidation.get, + options.stripMockito.get, stats, ) } @@ -108,6 +107,7 @@ class Ravenizer(val options: RavenizerOptions) { outJar: String, enableValidation: Boolean, fatalValidation: Boolean, + stripMockito: Boolean, stats: RavenizerStats, ) { var allClasses = ClassNodes.loadClassStructures(inJar) { @@ -126,6 +126,9 @@ class Ravenizer(val options: RavenizerOptions) { } } } + if (includeUnsupportedMockito(allClasses)) { + log.w("Unsupported Mockito detected in $inJar!") + } stats.totalProcessTime = log.vTime("$executableName processing $inJar") { ZipFile(inJar).use { inZip -> @@ -145,6 +148,11 @@ class Ravenizer(val options: RavenizerOptions) { ) } + if (stripMockito && entry.name.isMockitoFile()) { + // Skip this entry + continue + } + val className = zipEntryNameToClassName(entry.name) if (className != null) { diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt index ff41818cd370..aee453020fb4 100644 --- a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt +++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt @@ -36,6 +36,6 @@ fun main(args: Array<String>) { log.v("Options: $options") // Run. - Ravenizer(options).run() + Ravenizer().run(options) } } diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt index 10fe0a3b5a93..32dcbe546f3c 100644 --- a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt +++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt @@ -47,6 +47,9 @@ class RavenizerOptions( /** Whether the validation failure is fatal or not. */ var fatalValidation: SetOnce<Boolean> = SetOnce(false), + + /** Whether to remove mockito and dexmaker classes. */ + var stripMockito: SetOnce<Boolean> = SetOnce(false), ) { companion object { @@ -85,6 +88,9 @@ class RavenizerOptions( "--fatal-validation" -> ret.fatalValidation.set(true) "--no-fatal-validation" -> ret.fatalValidation.set(false) + "--strip-mockito" -> ret.stripMockito.set(true) + "--no-strip-mockito" -> ret.stripMockito.set(false) + else -> throw ArgumentsException("Unknown option: $arg") } } catch (e: SetOnce.SetMoreThanOnceException) { diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt index 1aa70c08c254..37a797528e13 100644 --- a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt +++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt @@ -100,3 +100,19 @@ fun String.shouldByBypassed(): Boolean { // TODO -- anything else? ) } + +/** + * Files that should be removed when "--strip-mockito" is set. + */ +fun String.isMockitoFile(): Boolean { + return this.startsWithAny( + "org/mockito/", // Mockito + "com/android/dx/", // DexMaker + "mockito-extensions/", // DexMaker overrides + ) +} + +fun includeUnsupportedMockito(classes: ClassNodes): Boolean { + return classes.findClass("com/android/dx/DexMaker") != null + || classes.findClass("org/mockito/Matchers") != null +} diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig index ee3bbcaf711d..034127c0420e 100644 --- a/services/accessibility/accessibility.aconfig +++ b/services/accessibility/accessibility.aconfig @@ -162,6 +162,13 @@ flag { } flag { + name: "magnification_enlarge_pointer" + namespace: "accessibility" + description: "When fullscreen magnification is enabled, pointer icon is enlarged" + bug: "355734856" +} + +flag { name: "manager_avoid_receiver_timeout" namespace: "accessibility" description: "Register receivers on background handler so they have more time to complete" diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java index 6b6b39df24d7..a77ba624a68f 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java @@ -47,7 +47,6 @@ import android.util.MathUtils; import android.util.Slog; import android.util.SparseArray; import android.util.TypedValue; -import android.view.Display; import android.view.DisplayInfo; import android.view.MagnificationSpec; import android.view.View; @@ -1637,9 +1636,10 @@ public class FullScreenMagnificationController implements * <strong>if scale is >= {@link MagnificationConstants.PERSISTED_SCALE_MIN_VALUE}</strong>. * We assume if the scale is < {@link MagnificationConstants.PERSISTED_SCALE_MIN_VALUE}, there * will be no obvious magnification effect. + * Only the value of the default display is persisted in user's settings. */ public void persistScale(int displayId) { - final float scale = getScale(Display.DEFAULT_DISPLAY); + final float scale = getScale(displayId); if (scale < MagnificationConstants.PERSISTED_SCALE_MIN_VALUE) { return; } diff --git a/services/appfunctions/TEST_MAPPING b/services/appfunctions/TEST_MAPPING index 91cfa064d9fc..851d754af943 100644 --- a/services/appfunctions/TEST_MAPPING +++ b/services/appfunctions/TEST_MAPPING @@ -2,11 +2,6 @@ "presubmit": [ { "name": "FrameworksAppFunctionsTests" - } - ], - "postsubmit": [ - { - "name": "FrameworksAppFunctionsTests" }, { "name": "CtsAppFunctionTestCases" diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java index ab9cc20763a8..d31ced3f2ce3 100644 --- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java +++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java @@ -16,8 +16,6 @@ package com.android.server.appfunctions; -import static android.app.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_DISABLED; -import static android.app.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_ENABLED; import static android.app.appfunctions.AppFunctionRuntimeMetadata.APP_FUNCTION_RUNTIME_METADATA_DB; import static android.app.appfunctions.AppFunctionRuntimeMetadata.APP_FUNCTION_RUNTIME_NAMESPACE; @@ -363,26 +361,14 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { callingPackage, functionIdentifier, runtimeMetadataSearchSession)); - AppFunctionRuntimeMetadata.Builder newMetadata = - new AppFunctionRuntimeMetadata.Builder(existingMetadata); - switch (enabledState) { - case AppFunctionManager.APP_FUNCTION_STATE_DEFAULT -> { - newMetadata.setEnabled(null); - } - case APP_FUNCTION_STATE_ENABLED -> { - newMetadata.setEnabled(true); - } - case APP_FUNCTION_STATE_DISABLED -> { - newMetadata.setEnabled(false); - } - default -> - throw new IllegalArgumentException("Value of EnabledState is unsupported."); - } + AppFunctionRuntimeMetadata newMetadata = + new AppFunctionRuntimeMetadata.Builder(existingMetadata) + .setEnabled(enabledState).build(); AppSearchBatchResult<String, Void> putDocumentBatchResult = runtimeMetadataSearchSession .put( new PutDocumentsRequest.Builder() - .addGenericDocuments(newMetadata.build()) + .addGenericDocuments(newMetadata) .build()) .get(); if (!putDocumentBatchResult.isSuccess()) { @@ -438,62 +424,17 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { targetUser, mServiceConfig.getExecuteAppFunctionCancellationTimeoutMillis(), cancellationSignal, - new RunServiceCallCallback<IAppFunctionService>() { - @Override - public void onServiceConnected( - @NonNull IAppFunctionService service, - @NonNull - ServiceUsageCompleteListener - serviceUsageCompleteListener) { - try { - service.executeAppFunction( - requestInternal.getClientRequest(), - cancellationCallback, - new IExecuteAppFunctionCallback.Stub() { - @Override - public void onResult( - ExecuteAppFunctionResponse response) { - safeExecuteAppFunctionCallback.onResult( - response); - serviceUsageCompleteListener.onCompleted(); - } - }); - } catch (Exception e) { - safeExecuteAppFunctionCallback.onResult( - ExecuteAppFunctionResponse.newFailure( - ExecuteAppFunctionResponse - .RESULT_APP_UNKNOWN_ERROR, - e.getMessage(), - /* extras= */ null)); - serviceUsageCompleteListener.onCompleted(); - } - } - - @Override - public void onFailedToConnect() { - Slog.e(TAG, "Failed to connect to service"); - safeExecuteAppFunctionCallback.onResult( - ExecuteAppFunctionResponse.newFailure( - ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR, - "Failed to connect to AppFunctionService", - /* extras= */ null)); - } - - @Override - public void onCancelled() { - // Do not forward the result back to the caller once it has been - // canceled. The caller does not need a notification and should - // proceed after initiating a cancellation. - safeExecuteAppFunctionCallback.disable(); - } - }, + RunAppFunctionServiceCallback.create( + requestInternal, + cancellationCallback, + safeExecuteAppFunctionCallback), callerBinder); if (!bindServiceResult) { Slog.e(TAG, "Failed to bind to the AppFunctionService"); safeExecuteAppFunctionCallback.onResult( ExecuteAppFunctionResponse.newFailure( - ExecuteAppFunctionResponse.RESULT_TIMED_OUT, + ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR, "Failed to bind the AppFunctionService.", /* extras= */ null)); } diff --git a/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java b/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java new file mode 100644 index 000000000000..7820390dd544 --- /dev/null +++ b/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java @@ -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.server.appfunctions; + +import android.annotation.NonNull; +import android.app.appfunctions.ExecuteAppFunctionAidlRequest; +import android.app.appfunctions.ExecuteAppFunctionResponse; +import android.app.appfunctions.IAppFunctionService; +import android.app.appfunctions.ICancellationCallback; +import android.app.appfunctions.IExecuteAppFunctionCallback; +import android.app.appfunctions.SafeOneTimeExecuteAppFunctionCallback; +import android.util.Slog; + +import com.android.server.appfunctions.RemoteServiceCaller.RunServiceCallCallback; +import com.android.server.appfunctions.RemoteServiceCaller.ServiceUsageCompleteListener; + + +/** + * A callback to forward a request to the {@link IAppFunctionService} and report back the result. + */ +public class RunAppFunctionServiceCallback implements RunServiceCallCallback<IAppFunctionService> { + + private final ExecuteAppFunctionAidlRequest mRequestInternal; + private final SafeOneTimeExecuteAppFunctionCallback mSafeExecuteAppFunctionCallback; + private final ICancellationCallback mCancellationCallback; + + private RunAppFunctionServiceCallback( + ExecuteAppFunctionAidlRequest requestInternal, + ICancellationCallback cancellationCallback, + SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback) { + this.mRequestInternal = requestInternal; + this.mSafeExecuteAppFunctionCallback = safeExecuteAppFunctionCallback; + this.mCancellationCallback = cancellationCallback; + } + + /** + * Creates a new instance of {@link RunAppFunctionServiceCallback}. + * + * @param requestInternal a request to send to the service. + * @param cancellationCallback a callback to forward cancellation signal to the service. + * @param safeExecuteAppFunctionCallback a callback to report back the result of the operation. + */ + public static RunAppFunctionServiceCallback create( + ExecuteAppFunctionAidlRequest requestInternal, + ICancellationCallback cancellationCallback, + SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback) { + return new RunAppFunctionServiceCallback( + requestInternal, cancellationCallback, safeExecuteAppFunctionCallback); + } + + @Override + public void onServiceConnected( + @NonNull IAppFunctionService service, + @NonNull ServiceUsageCompleteListener serviceUsageCompleteListener) { + try { + service.executeAppFunction( + mRequestInternal.getClientRequest(), + mCancellationCallback, + new IExecuteAppFunctionCallback.Stub() { + @Override + public void onResult(ExecuteAppFunctionResponse response) { + mSafeExecuteAppFunctionCallback.onResult(response); + serviceUsageCompleteListener.onCompleted(); + } + }); + } catch (Exception e) { + mSafeExecuteAppFunctionCallback.onResult( + ExecuteAppFunctionResponse.newFailure( + ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR, + e.getMessage(), + /* extras= */ null)); + serviceUsageCompleteListener.onCompleted(); + } + } + + @Override + public void onFailedToConnect() { + Slog.e("AppFunctionManagerServiceImpl", "Failed to connect to service"); + mSafeExecuteAppFunctionCallback.onResult( + ExecuteAppFunctionResponse.newFailure( + ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR, + "Failed to connect to AppFunctionService", + /* extras= */ null)); + } + + @Override + public void onCancelled() { + mSafeExecuteAppFunctionCallback.disable(); + } +} diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java index cd2dd3a27c9a..3bcca1c22c89 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java @@ -42,6 +42,7 @@ import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; import android.app.compat.CompatChanges; import android.companion.AssociationInfo; +import android.companion.AssociationRequest; import android.companion.virtual.ActivityPolicyExemption; import android.companion.virtual.IVirtualDevice; import android.companion.virtual.IVirtualDeviceActivityListener; @@ -98,6 +99,7 @@ import android.os.PermissionEnforcer; import android.os.PowerManager; import android.os.RemoteException; import android.os.ResultReceiver; +import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.util.ArrayMap; @@ -153,6 +155,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub private static final String PERSISTENT_ID_PREFIX_CDM_ASSOCIATION = "companion:"; + private static final List<String> DEVICE_PROFILES_ALLOWING_MIRROR_DISPLAYS = List.of( + AssociationRequest.DEVICE_PROFILE_APP_STREAMING); + /** * Timeout until {@link #launchPendingIntent} stops waiting for an activity to be launched. */ @@ -199,6 +204,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub private IVirtualDeviceSoundEffectListener mSoundEffectListener; private final DisplayManagerGlobal mDisplayManager; private final DisplayManagerInternal mDisplayManagerInternal; + private final PowerManager mPowerManager; @GuardedBy("mVirtualDeviceLock") private final Map<IBinder, IntentFilter> mIntentInterceptors = new ArrayMap<>(); @NonNull @@ -209,6 +215,10 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub @GuardedBy("mVirtualDeviceLock") @Nullable private LocaleList mLocaleList = null; + @GuardedBy("mVirtualDeviceLock") + private boolean mLockdownActive = false; + @GuardedBy("mVirtualDeviceLock") + private boolean mRequestedToBeAwake = true; @NonNull private final VirtualDevice mPublicVirtualDeviceObject; @@ -414,6 +424,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mDevicePolicies = params.getDevicePolicies(); mDisplayManager = displayManager; mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); + mPowerManager = context.getSystemService(PowerManager.class); if (inputController == null) { mInputController = new InputController( context.getMainThreadHandler(), @@ -471,6 +482,20 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub } } + void onLockdownChanged(boolean lockdownActive) { + synchronized (mVirtualDeviceLock) { + if (lockdownActive != mLockdownActive) { + mLockdownActive = lockdownActive; + if (mLockdownActive) { + goToSleepInternal(PowerManager.GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF); + } else if (mRequestedToBeAwake) { + wakeUpInternal(PowerManager.WAKE_REASON_DISPLAY_GROUP_TURNED_ON, + "android.server.companion.virtual:LOCKDOWN_ENDED"); + } + } + } + } + @VisibleForTesting SensorController getSensorControllerForTest() { return mSensorController; @@ -498,6 +523,10 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return mAssociationInfo == null ? mParams.getName() : mAssociationInfo.getDisplayName(); } + String getDeviceProfile() { + return mAssociationInfo == null ? null : mAssociationInfo.getDeviceProfile(); + } + /** Returns the public representation of the device. */ VirtualDevice getPublicVirtualDeviceObject() { return mPublicVirtualDeviceObject; @@ -568,8 +597,45 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub } @Override // Binder call + @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) + public void goToSleep() { + super.goToSleep_enforcePermission(); + synchronized (mVirtualDeviceLock) { + mRequestedToBeAwake = false; + } + final long ident = Binder.clearCallingIdentity(); + try { + goToSleepInternal(PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) + public void wakeUp() { + super.wakeUp_enforcePermission(); + synchronized (mVirtualDeviceLock) { + mRequestedToBeAwake = true; + if (mLockdownActive) { + Slog.w(TAG, "Cannot wake up device during lockdown."); + return; + } + } + final long ident = Binder.clearCallingIdentity(); + try { + wakeUpInternal(PowerManager.WAKE_REASON_POWER_BUTTON, + "android.server.companion.virtual:DEVICE_ON"); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void launchPendingIntent(int displayId, PendingIntent pendingIntent, ResultReceiver resultReceiver) { + super.launchPendingIntent_enforcePermission(); Objects.requireNonNull(pendingIntent); synchronized (mVirtualDeviceLock) { if (!mVirtualDisplays.contains(displayId)) { @@ -1034,7 +1100,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub } @Override // Binder call + @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public int getInputDeviceId(IBinder token) { + super.getInputDeviceId_enforcePermission(); final long ident = Binder.clearCallingIdentity(); try { return mInputController.getInputDeviceId(token); @@ -1117,7 +1185,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub } @Override // Binder call + @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public PointF getCursorPosition(IBinder token) { + super.getCursorPosition_enforcePermission(); final long ident = Binder.clearCallingIdentity(); try { return mInputController.getCursorPosition(token); @@ -1294,6 +1364,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return hasCustomAudioInputSupportInternal(); } + @Override + public boolean canCreateMirrorDisplays() { + return DEVICE_PROFILES_ALLOWING_MIRROR_DISPLAYS.contains(getDeviceProfile()); + } + private boolean hasCustomAudioInputSupportInternal() { if (!Flags.vdmPublicApis()) { return false; @@ -1398,18 +1473,24 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return gwpc; } - int createVirtualDisplay(@NonNull VirtualDisplayConfig virtualDisplayConfig, - @NonNull IVirtualDisplayCallback callback, String packageName) { + @Override // Binder call + @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) + public int createVirtualDisplay(@NonNull VirtualDisplayConfig virtualDisplayConfig, + @NonNull IVirtualDisplayCallback callback) { + super.createVirtualDisplay_enforcePermission(); GenericWindowPolicyController gwpc; synchronized (mVirtualDeviceLock) { gwpc = createWindowPolicyControllerLocked(virtualDisplayConfig.getDisplayCategories()); } int displayId; displayId = mDisplayManagerInternal.createVirtualDisplay(virtualDisplayConfig, callback, - this, gwpc, packageName); + this, gwpc, mOwnerPackageName); boolean isMirrorDisplay = mDisplayManagerInternal.getDisplayIdToMirror(displayId) != Display.INVALID_DISPLAY; gwpc.setDisplayId(displayId, isMirrorDisplay); + boolean isTrustedDisplay = + (mDisplayManagerInternal.getDisplayInfo(displayId).flags & Display.FLAG_TRUSTED) + == Display.FLAG_TRUSTED; boolean showPointer; synchronized (mVirtualDeviceLock) { @@ -1420,7 +1501,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub } PowerManager.WakeLock wakeLock = createAndAcquireWakeLockForDisplay(displayId); - mVirtualDisplays.put(displayId, new VirtualDisplayWrapper(callback, gwpc, wakeLock)); + mVirtualDisplays.put(displayId, new VirtualDisplayWrapper(callback, gwpc, wakeLock, + isTrustedDisplay, isMirrorDisplay)); showPointer = mDefaultShowPointerIcon; } @@ -1431,8 +1513,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false, displayId); // WM throws a SecurityException if the display is untrusted. - if ((mDisplayManagerInternal.getDisplayInfo(displayId).flags & Display.FLAG_TRUSTED) - == Display.FLAG_TRUSTED) { + if (isTrustedDisplay) { mInputController.setDisplayImePolicy(displayId, WindowManager.DISPLAY_IME_POLICY_LOCAL); } @@ -1498,7 +1579,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return result; } - void onVirtualDisplayRemoved(int displayId) { /* This is callback invoked by VirtualDeviceManagerService when VirtualDisplay was released * by DisplayManager (most probably caused by someone calling VirtualDisplay.close()). @@ -1549,6 +1629,34 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub } } + void goToSleepInternal(@PowerManager.GoToSleepReason int reason) { + final long now = SystemClock.uptimeMillis(); + synchronized (mVirtualDeviceLock) { + for (int i = 0; i < mVirtualDisplays.size(); i++) { + VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i); + if (!wrapper.isTrusted() || wrapper.isMirror()) { + continue; + } + int displayId = mVirtualDisplays.keyAt(i); + mPowerManager.goToSleep(displayId, now, reason, /* flags= */ 0); + } + } + } + + void wakeUpInternal(@PowerManager.WakeReason int reason, String details) { + final long now = SystemClock.uptimeMillis(); + synchronized (mVirtualDeviceLock) { + for (int i = 0; i < mVirtualDisplays.size(); i++) { + VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i); + if (!wrapper.isTrusted() || wrapper.isMirror()) { + continue; + } + int displayId = mVirtualDisplays.keyAt(i); + mPowerManager.wakeUp(now, reason, details, displayId); + } + } + } + /** * Release resources tied to virtual display owned by this VirtualDevice instance. * @@ -1652,6 +1760,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return mInputController.getInputDeviceDescriptors().values().stream().anyMatch( inputDeviceDescriptor -> inputDeviceDescriptor.getInputDeviceId() == inputDeviceId); } + void playSoundEffect(int effectType) { try { mSoundEffectListener.onPlaySoundEffect(effectType); @@ -1719,13 +1828,17 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub private final IVirtualDisplayCallback mToken; private final GenericWindowPolicyController mWindowPolicyController; private final PowerManager.WakeLock mWakeLock; + private final boolean mIsTrusted; + private final boolean mIsMirror; VirtualDisplayWrapper(@NonNull IVirtualDisplayCallback token, @NonNull GenericWindowPolicyController windowPolicyController, - @NonNull PowerManager.WakeLock wakeLock) { + @NonNull PowerManager.WakeLock wakeLock, boolean isTrusted, boolean isMirror) { mToken = Objects.requireNonNull(token); mWindowPolicyController = Objects.requireNonNull(windowPolicyController); mWakeLock = Objects.requireNonNull(wakeLock); + mIsTrusted = isTrusted; + mIsMirror = isMirror; } GenericWindowPolicyController getWindowPolicyController() { @@ -1736,6 +1849,14 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return mWakeLock; } + boolean isTrusted() { + return mIsTrusted; + } + + boolean isMirror() { + return mIsMirror; + } + IVirtualDisplayCallback getToken() { return mToken; } diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java index 3cd1ca4c6486..41b6a8533880 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java @@ -44,8 +44,6 @@ import android.content.AttributionSource; import android.content.Context; import android.content.Intent; import android.hardware.display.DisplayManagerInternal; -import android.hardware.display.IVirtualDisplayCallback; -import android.hardware.display.VirtualDisplayConfig; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -68,6 +66,7 @@ import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.DumpUtils; +import com.android.internal.widget.LockPatternUtils; import com.android.modules.expresslog.Counter; import com.android.server.LocalServices; import com.android.server.SystemService; @@ -129,6 +128,26 @@ public class VirtualDeviceManagerService extends SystemService { } }; + private class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker { + final Set<Integer> mUsersInLockdown = new ArraySet<>(); + + StrongAuthTracker(Context context) { + super(context); + } + + @Override + public synchronized void onStrongAuthRequiredChanged(int userId) { + if ((getStrongAuthForUser(userId) & STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN) > 0) { + if (mUsersInLockdown.add(userId) && mUsersInLockdown.size() == 1) { + onLockdownChanged(true); + } + } else if (mUsersInLockdown.remove(userId) && mUsersInLockdown.isEmpty()) { + onLockdownChanged(false); + } + } + } + private StrongAuthTracker mStrongAuthTracker; + private final RemoteCallbackList<IVirtualDeviceListener> mVirtualDeviceListeners = new RemoteCallbackList<>(); @@ -201,6 +220,20 @@ public class VirtualDeviceManagerService extends SystemService { + " will be available."); } } + if (android.companion.virtualdevice.flags.Flags.deviceAwareDisplayPower()) { + mStrongAuthTracker = new StrongAuthTracker(getContext()); + new LockPatternUtils(getContext()).registerStrongAuthTracker(mStrongAuthTracker); + } + } + + // Called when the global lockdown state changes, i.e. lockdown is considered active if any user + // is in lockdown mode, and inactive if no users are in lockdown mode. + void onLockdownChanged(boolean lockdownActive) { + synchronized (mVirtualDeviceManagerLock) { + for (int i = 0; i < mVirtualDevices.size(); i++) { + mVirtualDevices.valueAt(i).onLockdownChanged(lockdownActive); + } + } } void onCameraAccessBlocked(int appUid) { @@ -505,37 +538,6 @@ public class VirtualDeviceManagerService extends SystemService { } @Override // Binder call - public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig, - IVirtualDisplayCallback callback, IVirtualDevice virtualDevice, String packageName) - throws RemoteException { - Objects.requireNonNull(virtualDisplayConfig); - final int callingUid = getCallingUid(); - if (!PermissionUtils.validateCallingPackageName(getContext(), packageName)) { - throw new SecurityException( - "Package name " + packageName + " does not belong to calling uid " - + callingUid); - } - VirtualDeviceImpl virtualDeviceImpl; - synchronized (mVirtualDeviceManagerLock) { - virtualDeviceImpl = mVirtualDevices.get(virtualDevice.getDeviceId()); - if (virtualDeviceImpl == null) { - throw new SecurityException( - "Invalid VirtualDevice (deviceId = " + virtualDevice.getDeviceId() - + ")"); - } - } - if (virtualDeviceImpl.getOwnerUid() != callingUid) { - throw new SecurityException( - "uid " + callingUid - + " is not the owner of the supplied VirtualDevice (deviceId = " - + virtualDevice.getDeviceId() + ")"); - } - - return virtualDeviceImpl.createVirtualDisplay( - virtualDisplayConfig, callback, packageName); - } - - @Override // Binder call public List<VirtualDevice> getVirtualDevices() { List<VirtualDevice> virtualDevices = new ArrayList<>(); synchronized (mVirtualDeviceManagerLock) { diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java index 9060250d9869..2acedd56e505 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/services/core/java/com/android/server/PackageWatchdog.java @@ -47,6 +47,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; +import android.util.EventLog; import android.util.IndentingPrintWriter; import android.util.LongArrayQueue; import android.util.Slog; @@ -200,6 +201,13 @@ public class PackageWatchdog { // aborted. private static final String METADATA_FILE = "/metadata/watchdog/mitigation_count.txt"; + /** + * EventLog tags used when logging into the event log. Note the values must be sync with + * frameworks/base/services/core/java/com/android/server/EventLogTags.logtags to get correct + * name translation. + */ + private static final int LOG_TAG_RESCUE_NOTE = 2900; + private static final Object sPackageWatchdogLock = new Object(); @GuardedBy("sPackageWatchdogLock") private static PackageWatchdog sPackageWatchdog; @@ -2024,7 +2032,7 @@ public class PackageWatchdog { } else { int count = getCount() + 1; setCount(count); - EventLogTags.writeRescueNote(Process.ROOT_UID, count, window); + EventLog.writeEvent(LOG_TAG_RESCUE_NOTE, Process.ROOT_UID, count, window); if (Flags.recoverabilityDetection()) { // After a reboot (e.g. by WARM_REBOOT or mainline rollback) we apply // mitigations without waiting for DEFAULT_BOOT_LOOP_TRIGGER_COUNT. diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java index ada19530abfb..feb5775e5aac 100644 --- a/services/core/java/com/android/server/RescueParty.java +++ b/services/core/java/com/android/server/RescueParty.java @@ -42,6 +42,7 @@ import android.provider.Settings; import android.sysprop.CrashRecoveryProperties; import android.text.TextUtils; import android.util.ArraySet; +import android.util.EventLog; import android.util.Log; import android.util.Slog; @@ -154,6 +155,14 @@ public class RescueParty { private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_PERSISTENT | ApplicationInfo.FLAG_SYSTEM; + /** + * EventLog tags used when logging into the event log. Note the values must be sync with + * frameworks/base/services/core/java/com/android/server/EventLogTags.logtags to get correct + * name translation. + */ + private static final int LOG_TAG_RESCUE_SUCCESS = 2902; + private static final int LOG_TAG_RESCUE_FAILURE = 2903; + /** Register the Rescue Party observer as a Package Watchdog health observer */ public static void registerHealthObserver(Context context) { PackageWatchdog.getInstance(context).registerHealthObserver( @@ -523,7 +532,7 @@ public class RescueParty { Slog.w(TAG, "Attempting rescue level " + levelToString(level)); try { executeRescueLevelInternal(context, level, failedPackage); - EventLogTags.writeRescueSuccess(level); + EventLog.writeEvent(LOG_TAG_RESCUE_SUCCESS, level); String successMsg = "Finished rescue level " + levelToString(level); if (!TextUtils.isEmpty(failedPackage)) { successMsg += " for package " + failedPackage; @@ -704,7 +713,7 @@ public class RescueParty { private static void logRescueException(int level, @Nullable String failedPackageName, Throwable t) { final String msg = getCompleteMessage(t); - EventLogTags.writeRescueFailure(level, msg); + EventLog.writeEvent(LOG_TAG_RESCUE_FAILURE, level, msg); String failureMsg = "Failed rescue level " + levelToString(level); if (!TextUtils.isEmpty(failedPackageName)) { failureMsg += " for package " + failedPackageName; diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING index a459ea944008..ce66dc3c76cb 100644 --- a/services/core/java/com/android/server/TEST_MAPPING +++ b/services/core/java/com/android/server/TEST_MAPPING @@ -114,6 +114,9 @@ "options": [ { "include-filter": "android.os.storage.cts.StorageManagerTest" + }, + { + "include-filter": "android.os.storage.cts.StorageStatsManagerTest" } ] } @@ -173,15 +176,6 @@ "include-filter": "com.android.server.wm.BackgroundActivityStart*" } ] - }, - { - "name": "CtsOsTestCases", - "file_patterns": ["StorageManagerService\\.java"], - "options": [ - { - "include-filter": "android.os.storage.cts.StorageStatsManagerTest" - } - ] } ] } diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index f32031dec43c..f8857d3e152a 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -17,6 +17,7 @@ package com.android.server; import static android.app.Flags.modesApi; +import static android.app.Flags.enableCurrentModeTypeBinderCache; import static android.app.Flags.enableNightModeBinderCache; import static android.app.UiModeManager.ContrastUtils.CONTRAST_DEFAULT_VALUE; import static android.app.UiModeManager.DEFAULT_PRIORITY; @@ -138,7 +139,7 @@ final class UiModeManagerService extends SystemService { private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED; - private final NightMode mNightMode = new NightMode(){ + private final IntProperty mNightMode = new IntProperty(){ private int mNightModeValue = UiModeManager.MODE_NIGHT_NO; @Override @@ -192,7 +193,22 @@ final class UiModeManagerService extends SystemService { // flag set by resource, whether to night mode change for normal all or not. private boolean mNightModeLocked = false; - int mCurUiMode = 0; + private final IntProperty mCurUiMode = new IntProperty(){ + private int mCurrentModeTypeValue = 0; + + @Override + public int get() { + return mCurrentModeTypeValue; + } + + @Override + public void set(int mode) { + mCurrentModeTypeValue = mode; + if (enableCurrentModeTypeBinderCache()) { + UiModeManager.invalidateCurrentModeTypeCache(); + } + } + }; private int mSetUiMode = 0; private boolean mHoldingConfiguration = false; private int mCurrentUser; @@ -810,7 +826,7 @@ final class UiModeManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { synchronized (mLock) { - return mCurUiMode & Configuration.UI_MODE_TYPE_MASK; + return mCurUiMode.get() & Configuration.UI_MODE_TYPE_MASK; } } finally { Binder.restoreCallingIdentity(ident); @@ -1492,7 +1508,7 @@ final class UiModeManagerService extends SystemService { pw.print(" mCarModeEnableFlags="); pw.print(mCarModeEnableFlags); pw.print(" mEnableCarDockLaunch="); pw.println(mEnableCarDockLaunch); - pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode)); + pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode.get())); pw.print(" mUiModeLocked="); pw.print(mUiModeLocked); pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode)); @@ -1745,7 +1761,7 @@ final class UiModeManagerService extends SystemService { + "; uiMode=" + uiMode); } - mCurUiMode = uiMode; + mCurUiMode.set(uiMode); if (!mHoldingConfiguration && (!mWaitForDeviceInactive || mPowerSave)) { mConfiguration.uiMode = uiMode; } @@ -1892,7 +1908,7 @@ final class UiModeManagerService extends SystemService { boolean keepScreenOn = mCharging && ((mCarModeEnabled && mCarModeKeepsScreenOn && (mCarModeEnableFlags & UiModeManager.ENABLE_CAR_MODE_ALLOW_SLEEP) == 0) || - (mCurUiMode == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn)); + (mCurUiMode.get() == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn)); if (keepScreenOn != mWakeLock.isHeld()) { if (keepScreenOn) { mWakeLock.acquire(); @@ -2048,12 +2064,14 @@ final class UiModeManagerService extends SystemService { private void updateComputedNightModeLocked(boolean activate) { boolean newComputedValue = activate; + boolean appliedOverrides = false; if (mNightMode.get() != MODE_NIGHT_YES && mNightMode.get() != UiModeManager.MODE_NIGHT_NO) { if (mOverrideNightModeOn && !newComputedValue) { newComputedValue = true; } else if (mOverrideNightModeOff && newComputedValue) { newComputedValue = false; } + appliedOverrides = true; } if (modesApi()) { @@ -2063,8 +2081,10 @@ final class UiModeManagerService extends SystemService { case (UiModeManager.MODE_ATTENTION_THEME_OVERLAY_DAY) -> false; default -> newComputedValue; // case OFF }; - } else { - mComputedNightMode = newComputedValue; + } + + if (appliedOverrides) { + return; } if (mNightMode.get() != MODE_NIGHT_AUTO || (mTwilightManager != null @@ -2319,11 +2339,12 @@ final class UiModeManagerService extends SystemService { } /** - * Interface to contain the value for system night mode. We make the night mode accessible - * through this class to ensure that the reassignment of this value invalidates the cache. + * Interface to contain the value for an integral property. We make the property + * accessible through this class to ensure that the reassignment of this value invalidates the + * cache. */ - private interface NightMode { + private interface IntProperty { int get(); - void set(int mode); + void set(int value); } } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 36665240c16b..f9197e3c5c42 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -5077,7 +5077,10 @@ public final class ActiveServices { + " requires " + r.permission); return new ServiceLookupResult(r.permission); } else if ((Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE.equals(r.permission) - || Manifest.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE.equals(r.permission)) + || Manifest.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE.equals(r.permission) + || Manifest.permission.BIND_WEARABLE_SENSING_SERVICE.equals(r.permission) + || Manifest.permission.BIND_ON_DEVICE_SANDBOXED_INFERENCE_SERVICE.equals( + r.permission)) && callingUid != Process.SYSTEM_UID) { // Hotword detection and visual query detection must run in its own sandbox, and we // don't even trust its enclosing application to bind to it - only the system. diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 6fd281e7003e..f5a297bfd4f5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -685,11 +685,6 @@ final class ActivityManagerConstants extends ContentObserver { // default. Controlled by Settings.Global.FORCE_ENABLE_PSS_PROFILING volatile boolean mForceEnablePssProfiling = false; - // Indicates whether to use ApplicationInfo to determine launched state instead of PM user state - // This is a temporary workaround until the trunk-stable flag is pushed to nextfood. - // TODO: b/365979852 - remove this workaround when redundant - volatile boolean mFlagUseAppInfoNotLaunched = false; - /** * Indicates whether the foreground service background start restriction is enabled for * caller app that is targeting S+. @@ -1022,9 +1017,6 @@ final class ActivityManagerConstants extends ContentObserver { private static final Uri FORCE_ENABLE_PSS_PROFILING_URI = Settings.Global.getUriFor(Settings.Global.FORCE_ENABLE_PSS_PROFILING); - private static final Uri ENABLE_USE_APP_INFO_NOT_LAUNCHED_URI = - Settings.Global.getUriFor(Settings.Global.ENABLE_USE_APP_INFO_NOT_LAUNCHED); - /** * The threshold to decide if a given association should be dumped into metrics. */ @@ -1487,7 +1479,6 @@ final class ActivityManagerConstants extends ContentObserver { false, this); } mResolver.registerContentObserver(FORCE_ENABLE_PSS_PROFILING_URI, false, this); - mResolver.registerContentObserver(ENABLE_USE_APP_INFO_NOT_LAUNCHED_URI, false, this); updateConstants(); if (mSystemServerAutomaticHeapDumpEnabled) { updateEnableAutomaticSystemServerHeapDumps(); @@ -1504,7 +1495,6 @@ final class ActivityManagerConstants extends ContentObserver { updateActivityStartsLoggingEnabled(); updateForegroundServiceStartsLoggingEnabled(); updateForceEnablePssProfiling(); - updateEnableUseAppInfoNotLaunched(); // Read DropboxRateLimiter params from flags. mService.initDropboxRateLimiter(); } @@ -1550,8 +1540,6 @@ final class ActivityManagerConstants extends ContentObserver { updateEnableAutomaticSystemServerHeapDumps(); } else if (FORCE_ENABLE_PSS_PROFILING_URI.equals(uri)) { updateForceEnablePssProfiling(); - } else if (ENABLE_USE_APP_INFO_NOT_LAUNCHED_URI.equals(uri)) { - updateEnableUseAppInfoNotLaunched(); } } @@ -1671,11 +1659,6 @@ final class ActivityManagerConstants extends ContentObserver { Settings.Global.FORCE_ENABLE_PSS_PROFILING, 0) == 1; } - private void updateEnableUseAppInfoNotLaunched() { - mFlagUseAppInfoNotLaunched = Settings.Global.getInt(mResolver, - Settings.Global.ENABLE_USE_APP_INFO_NOT_LAUNCHED, 0) == 1; - } - private void updateBackgroundActivityStarts() { mFlagBackgroundActivityStartsEnabled = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, @@ -2555,8 +2538,6 @@ final class ActivityManagerConstants extends ContentObserver { pw.print(" OOMADJ_UPDATE_QUICK="); pw.println(OOMADJ_UPDATE_QUICK); pw.print(" ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION="); pw.println(mEnableWaitForFinishAttachApplication); - pw.print(" FLAG_USE_APP_INFO_NOT_LAUNCHED="); - pw.println(mFlagUseAppInfoNotLaunched); pw.print(" "); pw.print(KEY_FOLLOW_UP_OOMADJ_UPDATE_WAIT_DURATION); pw.print("="); pw.println(FOLLOW_UP_OOMADJ_UPDATE_WAIT_DURATION); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 83bc75e9f66f..74437cd3c2ef 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -130,6 +130,7 @@ import static android.os.Process.setThreadScheduler; import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES; import static android.provider.Settings.Global.DEBUG_APP; import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER; +import static android.security.Flags.preventIntentRedirect; import static android.util.FeatureFlagUtils.SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS; import static android.view.Display.INVALID_DISPLAY; @@ -420,6 +421,7 @@ import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.MemInfoReader; import com.android.internal.util.Preconditions; +import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.AlarmManagerInternal; import com.android.server.BootReceiver; import com.android.server.DeviceIdleInternal; @@ -2420,6 +2422,7 @@ public class ActivityManagerService extends IActivityManager.Stub mBroadcastController = new BroadcastController(mContext, this, mBroadcastQueue); mComponentAliasResolver = new ComponentAliasResolver(this); mApplicationSharedMemoryReadOnlyFd = null; + sCreatorTokenCacheCleaner = new Handler(mHandlerThread.getLooper()); } // Note: This method is invoked on the main thread but may need to attach various @@ -2526,6 +2529,7 @@ public class ActivityManagerService extends IActivityManager.Stub mPendingStartActivityUids = new PendingStartActivityUids(); mTraceErrorLogger = new TraceErrorLogger(); mComponentAliasResolver = new ComponentAliasResolver(this); + sCreatorTokenCacheCleaner = new Handler(mHandlerThread.getLooper()); try { mApplicationSharedMemoryReadOnlyFd = ApplicationSharedMemory.getInstance().getReadOnlyFileDescriptor(); @@ -5532,6 +5536,7 @@ public class ActivityManagerService extends IActivityManager.Stub public int sendIntentSender(IApplicationThread caller, IIntentSender target, IBinder allowlistToken, int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) { + addCreatorToken(intent); if (target instanceof PendingIntentRecord) { final PendingIntentRecord originalRecord = (PendingIntentRecord) target; @@ -8269,7 +8274,16 @@ public class ActivityManagerService extends IActivityManager.Stub setThreadScheduler(proc.getRenderThreadTid(), SCHED_FIFO | SCHED_RESET_ON_FORK, 1); } else { - setThreadPriority(proc.getRenderThreadTid(), THREAD_PRIORITY_TOP_APP_BOOST); + if (Flags.resetOnForkEnabled()) { + if (Process.getThreadScheduler(proc.getRenderThreadTid()) + == Process.SCHED_OTHER) { + Process.setThreadScheduler(proc.getRenderThreadTid(), + Process.SCHED_OTHER | Process.SCHED_RESET_ON_FORK, + 0); + } + } + setThreadPriority(proc.getRenderThreadTid(), + THREAD_PRIORITY_TOP_APP_BOOST); } } } else { @@ -13610,6 +13624,7 @@ public class ActivityManagerService extends IActivityManager.Stub throws TransactionTooLargeException { enforceNotIsolatedCaller("startService"); enforceAllowedToStartOrBindServiceIfSdkSandbox(service); + addCreatorToken(service); if (service != null) { // Refuse possible leaked file descriptors if (service.hasFileDescriptors()) { @@ -13871,6 +13886,7 @@ public class ActivityManagerService extends IActivityManager.Stub validateServiceInstanceName(instanceName); + addCreatorToken(service); try { if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { final ComponentName cn = service.getComponent(); @@ -17148,6 +17164,7 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.v(TAG_SERVICE, "startServiceInPackage: " + service + " type=" + resolvedType); } + addCreatorToken(service); final long origId = Binder.clearCallingIdentity(); ComponentName res; try { @@ -17973,6 +17990,11 @@ public class ActivityManagerService extends IActivityManager.Stub userId, reason, exitInfoReason); } } + + @Override + public void addCreatorToken(Intent intent) { + ActivityManagerService.this.addCreatorToken(intent); + } } long inputDispatchingTimedOut(int pid, final boolean aboveSystem, TimeoutRecord timeoutRecord) { @@ -18398,25 +18420,34 @@ public class ActivityManagerService extends IActivityManager.Stub "Cannot kill the dependents of a package without its name."); } + userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), + userId, true, ALLOW_FULL_ONLY, "killPackageDependents", null); + final int[] userIds = mUserController.expandUserId(userId); + final long callingId = Binder.clearCallingIdentity(); IPackageManager pm = AppGlobals.getPackageManager(); - int pkgUid = -1; try { - pkgUid = pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId); - } catch (RemoteException e) { - } - if (userId != UserHandle.USER_ALL && pkgUid == -1) { - throw new IllegalArgumentException( - "Cannot kill dependents of non-existing package " + packageName); - } - try { - synchronized(this) { - synchronized (mProcLock) { - mProcessList.killPackageProcessesLSP(packageName, UserHandle.getAppId(pkgUid), - userId, ProcessList.FOREGROUND_APP_ADJ, - ApplicationExitInfo.REASON_DEPENDENCY_DIED, - ApplicationExitInfo.SUBREASON_UNKNOWN, - "dep: " + packageName); + for (int targetUserId : userIds) { + int pkgUid = -1; + try { + pkgUid = pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, + targetUserId); + } catch (RemoteException e) { + } + if (userId != UserHandle.USER_ALL && pkgUid == -1) { + throw new IllegalArgumentException( + "Cannot kill dependents of non-existing package " + packageName); + } + synchronized (this) { + synchronized (mProcLock) { + mProcessList.killPackageProcessesLSP(packageName, + UserHandle.getAppId(pkgUid), + targetUserId, + ProcessList.FOREGROUND_APP_ADJ, + ApplicationExitInfo.REASON_DEPENDENCY_DIED, + ApplicationExitInfo.SUBREASON_UNKNOWN, + "dep: " + packageName); + } } } } finally { @@ -19105,6 +19136,7 @@ public class ActivityManagerService extends IActivityManager.Stub private static final Map<IntentCreatorToken.Key, WeakReference<IntentCreatorToken>> sIntentCreatorTokenCache = new ConcurrentHashMap<>(); + private static Handler sCreatorTokenCacheCleaner; /** * A binder token used to keep track of which app created the intent. This token can be used to * defend against intent redirect attacks. It stores uid of the intent creator and key fields of @@ -19112,13 +19144,16 @@ public class ActivityManagerService extends IActivityManager.Stub * * @hide */ + @VisibleForTesting public static final class IntentCreatorToken extends Binder { @NonNull private final Key mKeyFields; + private final WeakReference<IntentCreatorToken> mRef; public IntentCreatorToken(int creatorUid, Intent intent) { super(); this.mKeyFields = new Key(creatorUid, intent); + mRef = new WeakReference<>(this); } public int getCreatorUid() { @@ -19136,6 +19171,26 @@ public class ActivityManagerService extends IActivityManager.Stub new Key(token.mKeyFields.mCreatorUid, intent)); } + @Override + protected void finalize() throws Throwable { + try { + sCreatorTokenCacheCleaner.sendMessage(PooledLambda.obtainMessage( + IntentCreatorToken::completeFinalize, this)); + } finally { + super.finalize(); + } + } + + private void completeFinalize() { + synchronized (sIntentCreatorTokenCache) { + WeakReference<IntentCreatorToken> current = sIntentCreatorTokenCache.get( + mKeyFields); + if (current == mRef) { + sIntentCreatorTokenCache.remove(mKeyFields); + } + } + } + private static class Key { private Key(int creatorUid, Intent intent) { this.mCreatorUid = creatorUid; @@ -19178,9 +19233,57 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public int hashCode() { return Objects.hash(mCreatorUid, mAction, mData, mType, mPackage, mComponent, - mFlags, - mClipDataUris); + mFlags, mClipDataUris); + } + } + } + + /** + * Add a creator token for all embedded intents (stored as extra) of the given intent. + * + * @param intent The given intent + * @hide + */ + public void addCreatorToken(@Nullable Intent intent) { + if (!preventIntentRedirect()) return; + + if (intent == null || intent.getExtraIntentKeys() == null) return; + for (String key : intent.getExtraIntentKeys()) { + try { + Intent extraIntent = intent.getParcelableExtra(key, Intent.class); + if (extraIntent == null) { + Slog.w(TAG, "The key {" + key + + "} does not correspond to an intent in the extra bundle."); + continue; + } + Slog.wtf(TAG, "A creator token is added to an intent."); + IBinder creatorToken = createIntentCreatorToken(extraIntent); + if (creatorToken != null) { + extraIntent.setCreatorToken(creatorToken); + } + } catch (Exception e) { + Slog.wtf(TAG, + "Something went wrong when trying to add creator token for embedded " + + "intents of intent: ." + + intent, e); + } + } + } + + private IBinder createIntentCreatorToken(Intent intent) { + if (IntentCreatorToken.isValid(intent)) return null; + int creatorUid = getCallingUid(); + IntentCreatorToken.Key key = new IntentCreatorToken.Key(creatorUid, intent); + IntentCreatorToken token; + synchronized (sIntentCreatorTokenCache) { + WeakReference<IntentCreatorToken> ref = sIntentCreatorTokenCache.get(key); + if (ref == null || ref.get() == null) { + token = new IntentCreatorToken(creatorUid, intent); + sIntentCreatorTokenCache.put(key, token.mRef); + } else { + token = ref.get(); } } + return token; } } diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java index 71b64567d062..aca6d0b0b967 100644 --- a/services/core/java/com/android/server/am/AppStartInfoTracker.java +++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java @@ -1005,7 +1005,8 @@ public final class AppStartInfoTracker { case (int) AppsStartInfoProto.Package.USERS: AppStartInfoContainer container = new AppStartInfoContainer(mAppStartInfoHistoryListSize); - int uid = container.readFromProto(proto, AppsStartInfoProto.Package.USERS); + int uid = container.readFromProto(proto, AppsStartInfoProto.Package.USERS, + pkgName); synchronized (mLock) { mData.put(pkgName, uid, container); } @@ -1403,7 +1404,7 @@ public final class AppStartInfoTracker { proto.end(token); } - int readFromProto(ProtoInputStream proto, long fieldId) + int readFromProto(ProtoInputStream proto, long fieldId, String packageName) throws IOException, WireTypeMismatchException, ClassNotFoundException { long token = proto.start(fieldId); for (int next = proto.nextField(); @@ -1418,6 +1419,7 @@ public final class AppStartInfoTracker { // have a create time. ApplicationStartInfo info = new ApplicationStartInfo(0); info.readFromProto(proto, AppsStartInfoProto.Package.User.APP_START_INFO); + info.setPackageName(packageName); mInfos.add(info); break; case (int) AppsStartInfoProto.Package.User.MONITORING_ENABLED: diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 78a0a117fe6f..4073ab848f81 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -458,6 +458,13 @@ public class OomAdjuster { } void setThreadPriority(int tid, int priority) { + if (Flags.resetOnForkEnabled()) { + if (Process.getThreadScheduler(tid) == Process.SCHED_OTHER) { + Process.setThreadScheduler(tid, + Process.SCHED_OTHER | Process.SCHED_RESET_ON_FORK, + 0); + } + } Process.setThreadPriority(tid, priority); } diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index a93ae72fcfea..57922d5eb05e 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -3401,8 +3401,7 @@ public final class ProcessList { // Check if we should mark the processrecord for first launch after force-stopping if (wasStopped) { boolean wasEverLaunched = false; - if (android.app.Flags.useAppInfoNotLaunched() - || mService.mConstants.mFlagUseAppInfoNotLaunched) { + if (android.app.Flags.useAppInfoNotLaunched()) { wasEverLaunched = !info.isNotLaunched(); } else { try { @@ -3423,8 +3422,7 @@ public final class ProcessList { : STOPPED_STATE_FIRST_LAUNCH; r.getWindowProcessController().setStoppedState(stoppedState); } else { - if (android.app.Flags.useAppInfoNotLaunched() - || mService.mConstants.mFlagUseAppInfoNotLaunched) { + if (android.app.Flags.useAppInfoNotLaunched()) { // If it was launched before, then it must be a force-stop r.setWasForceStopped(wasEverLaunched); } else { diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java index bae9a670c438..a815f72ca09e 100644 --- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java @@ -138,6 +138,7 @@ public class SettingsToPropertiesMapper { // The list is sorted. @VisibleForTesting static final String[] sDeviceConfigAconfigScopes = new String[] { + "aaos_sdv", "accessibility", "android_core_networking", "android_health_services", @@ -150,6 +151,7 @@ public class SettingsToPropertiesMapper { "art_performance", "attack_tools", "avic", + "desktop_firmware", "biometrics", "biometrics_framework", "biometrics_integration", @@ -211,6 +213,7 @@ public class SettingsToPropertiesMapper { "preload_safety", "printing", "privacy_infra_policy", + "ravenwood", "resource_manager", "responsible_apis", "rust", @@ -243,8 +246,10 @@ public class SettingsToPropertiesMapper { "wear_system_health", "wear_systems", "wear_sysui", + "wear_system_managed_surfaces", "window_surfaces", "windowing_frontend", + "xr", }; public static final String NAMESPACE_REBOOT_STAGING = "staged"; diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig index 4f6da3baca12..7873d34e9047 100644 --- a/services/core/java/com/android/server/am/flags.aconfig +++ b/services/core/java/com/android/server/am/flags.aconfig @@ -198,13 +198,10 @@ flag { flag { name: "logcat_longer_timeout" - namespace: "backstage_power" + namespace: "stability" description: "Wait longer during the logcat gathering operation" bug: "292533246" is_fixed_read_only: true - metadata { - purpose: PURPOSE_BUGFIX - } } flag { @@ -214,3 +211,10 @@ flag { description: "Defer submitting display events to frozen processes." bug: "326315985" } + +flag { + name: "reset_on_fork_enabled" + namespace: "system_performance" + description: "Set reset_on_fork flag." + bug: "370988407" +} diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index e0cf96fbccd0..596e375b439d 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -72,6 +72,9 @@ import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP; import static android.permission.flags.Flags.deviceAwareAppOpNewSchemaEnabled; +import static com.android.internal.util.FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__CHECK_OPERATION; +import static com.android.internal.util.FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__NOTE_OPERATION; +import static com.android.internal.util.FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__NOTE_PROXY_OPERATION; import static com.android.server.appop.AppOpsService.ModeCallback.ALL_OPS; import android.Manifest; @@ -160,6 +163,7 @@ import com.android.internal.os.Clock; import com.android.internal.pm.pkg.component.ParsedAttribution; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; +import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.internal.util.function.pooled.PooledLambda; @@ -2829,12 +2833,26 @@ public class AppOpsService extends IAppOpsService.Stub { @Override public int checkOperation(int code, int uid, String packageName) { + if (Flags.appopAccessTrackingLoggingEnabled()) { + FrameworkStatsLog.write( + FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED, + uid, code, + APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__CHECK_OPERATION, + false); + } return mCheckOpsDelegateDispatcher.checkOperation(code, uid, packageName, null, Context.DEVICE_ID_DEFAULT, false /*raw*/); } @Override public int checkOperationForDevice(int code, int uid, String packageName, int virtualDeviceId) { + if (Flags.appopAccessTrackingLoggingEnabled()) { + FrameworkStatsLog.write( + FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED, + uid, code, + APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__CHECK_OPERATION, + false); + } return mCheckOpsDelegateDispatcher.checkOperation(code, uid, packageName, null, virtualDeviceId, false /*raw*/); } @@ -3015,6 +3033,14 @@ public class AppOpsService extends IAppOpsService.Stub { public SyncNotedAppOp noteProxyOperationWithState(int code, AttributionSourceState attributionSourceState, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation) { + if (Flags.appopAccessTrackingLoggingEnabled()) { + FrameworkStatsLog.write( + FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED, + attributionSourceState.uid, code, + APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__NOTE_PROXY_OPERATION, + attributionSourceState.attributionTag != null); + } + AttributionSource attributionSource = new AttributionSource(attributionSourceState); return mCheckOpsDelegateDispatcher.noteProxyOperation(code, attributionSource, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation); @@ -3096,6 +3122,14 @@ public class AppOpsService extends IAppOpsService.Stub { public SyncNotedAppOp noteOperation(int code, int uid, String packageName, String attributionTag, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage) { + if (Flags.appopAccessTrackingLoggingEnabled()) { + FrameworkStatsLog.write( + FrameworkStatsLog.APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED, + uid, code, + APP_OP_NOTE_OP_OR_CHECK_OP_BINDER_API_CALLED__BINDER_API__NOTE_OPERATION, + attributionTag != null); + } + return mCheckOpsDelegateDispatcher.noteOperation(code, uid, packageName, attributionTag, Context.DEVICE_ID_DEFAULT, shouldCollectAsyncNotedOp, message, shouldCollectMessage); diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 875041540f40..60dbf3f21587 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -384,11 +384,13 @@ public class AudioDeviceBroker { /** * Indicates if a Bluetooth SCO activation request owner is controlling * the SCO audio state itself or not. - * @param uid the UI of the SOC request owner app + * @param uid the UID of the SOC request owner app * @return true if we should control SCO audio state, false otherwise */ private boolean shouldStartScoForUid(int uid) { - return !(uid == Process.BLUETOOTH_UID || uid == Process.PHONE_UID); + return !(UserHandle.isSameApp(uid, Process.BLUETOOTH_UID) + || UserHandle.isSameApp(uid, Process.PHONE_UID) + || UserHandle.isSameApp(uid, Process.SYSTEM_UID)); } @GuardedBy("mDeviceStateLock") diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index 5fd12c29d2f8..09de89445122 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -385,11 +385,6 @@ public class AudioDeviceInventory { || !updatedDevice.getDeviceAddress().equals(ads.getDeviceAddress())) { continue; } - if (mDeviceBroker.isSADevice(updatedDevice) == mDeviceBroker.isSADevice(ads)) { - ads.setHasHeadTracker(updatedDevice.hasHeadTracker()); - ads.setHeadTrackerEnabled(updatedDevice.isHeadTrackerEnabled()); - ads.setSAEnabled(updatedDevice.isSAEnabled()); - } ads.setAudioDeviceCategory(updatedDevice.getAudioDeviceCategory()); mDeviceBroker.postUpdatedAdiDeviceState(ads, false /*initSA*/); diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index f9e839273784..1563a6257552 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -286,6 +286,7 @@ import java.util.Objects; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.CancellationException; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -4030,7 +4031,6 @@ public class AudioService extends IAudioService.Stub && isFullVolumeDevice(device); boolean tvConditions = mHdmiTvClient != null && mHdmiSystemAudioSupported - && isFullVolumeDevice(device) && !isAbsoluteVolumeDevice(device) && !isA2dpAbsoluteVolumeDevice(device); @@ -10100,9 +10100,6 @@ public class AudioService extends IAudioService.Stub case MSG_INIT_SPATIALIZER: onInitSpatializer(); - // the device inventory can only be synchronized after the - // spatializer has been initialized - mDeviceBroker.postSynchronizeAdiDevicesInInventory(null); mAudioEventWakeLock.release(); break; diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java index 88268cd19a38..a734e73d213b 100644 --- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java @@ -253,7 +253,11 @@ public final class PlaybackActivityMonitor updateAllowedCapturePolicy(apc, mAllowedCapturePolicies.get(uid)); } } - sEventLogger.enqueue(new NewPlayerEvent(apc)); + var packages = mContext.getPackageManager().getPackagesForUid(apc.getClientUid()); + sEventLogger.enqueue(new NewPlayerEvent( + apc, + packages != null && packages.length > 0 ? packages[0] : null + )); synchronized(mPlayerLock) { mPlayers.put(newPiid, apc); maybeMutePlayerAwaitingConnection(apc); @@ -1402,14 +1406,16 @@ public final class PlaybackActivityMonitor private final int mPlayerIId; private final int mPlayerType; private final int mClientUid; + private final String mClientPackageName; private final int mClientPid; private final AudioAttributes mPlayerAttr; private final int mSessionId; - NewPlayerEvent(AudioPlaybackConfiguration apc) { + NewPlayerEvent(AudioPlaybackConfiguration apc, String packageName) { mPlayerIId = apc.getPlayerInterfaceId(); mPlayerType = apc.getPlayerType(); mClientUid = apc.getClientUid(); + mClientPackageName = packageName; mClientPid = apc.getClientPid(); mPlayerAttr = apc.getAudioAttributes(); mSessionId = apc.getSessionId(); @@ -1418,7 +1424,7 @@ public final class PlaybackActivityMonitor @Override public String eventToString() { return new String("new player piid:" + mPlayerIId + " uid/pid:" + mClientUid + "/" - + mClientPid + " type:" + + mClientPid + " package:" + mClientPackageName + " type:" + AudioPlaybackConfiguration.toLogFriendlyPlayerType(mPlayerType) + " attr:" + mPlayerAttr + " session:" + mSessionId); diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java index abfbddc18e24..3afecf1d8bbf 100644 --- a/services/core/java/com/android/server/biometrics/AuthSession.java +++ b/services/core/java/com/android/server/biometrics/AuthSession.java @@ -879,6 +879,14 @@ public final class AuthSession implements IBinder.DeathRecipient { ); break; + case BiometricPrompt.DISMISSED_REASON_ERROR_NO_WM: + mClientReceiver.onError( + getEligibleModalities(), + BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, + 0 /* vendorCode */ + ); + break; + default: Slog.w(TAG, "Unhandled reason: " + reason); break; diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java index de7bce78587b..87341365355b 100644 --- a/services/core/java/com/android/server/biometrics/Utils.java +++ b/services/core/java/com/android/server/biometrics/Utils.java @@ -253,9 +253,15 @@ public class Utils { // Check if any of the non-biometric and non-credential bits are set. If so, this is // invalid. - final int testBits = ~(Authenticators.DEVICE_CREDENTIAL - | Authenticators.BIOMETRIC_MIN_STRENGTH - | Authenticators.MANDATORY_BIOMETRICS); + final int testBits; + if (Flags.mandatoryBiometrics()) { + testBits = ~(Authenticators.DEVICE_CREDENTIAL + | Authenticators.BIOMETRIC_MIN_STRENGTH + | Authenticators.MANDATORY_BIOMETRICS); + } else { + testBits = ~(Authenticators.DEVICE_CREDENTIAL + | Authenticators.BIOMETRIC_MIN_STRENGTH); + } if ((authenticators & testBits) != 0) { Slog.e(BiometricService.TAG, "Non-biometric, non-credential bits found." + " Authenticators: " + authenticators); diff --git a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java index bc58501f5b59..93b0e66d1ae5 100644 --- a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java +++ b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java @@ -123,7 +123,8 @@ public class BiometricFrameworkStatsLogger { enrollSuccessful, -1, /* sensorId */ ambientLightLux, - source); + source, + -1 /* templateId*/); } /** {@see FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED}. */ diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index af9c9accb635..8d96ba93530b 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -377,6 +377,7 @@ import javax.xml.datatype.DatatypeConfigurationException; * </point> * </map> * </luxToBrightnessMapping> + * <idleStylusTimeoutMillis>10000</idleStylusTimeoutMillis> * </autoBrightness> * * <screenBrightnessRampFastDecrease>0.01</screenBrightnessRampFastDecrease> @@ -708,6 +709,10 @@ public class DisplayDeviceConfig { private static final int KEEP_CURRENT_BRIGHTNESS = -1; + // The default value to 0 which will signify that the stylus usage immediately stopped + // after it was started. This will make the system behave as if the stylus was never used + private static final int DEFAULT_IDLE_STYLUS_TIMEOUT_MILLIS = 0; + private final Context mContext; // The details of the ambient light sensor associated with this display. @@ -754,6 +759,9 @@ public class DisplayDeviceConfig { @Nullable private DisplayBrightnessMappingConfig mDisplayBrightnessMapping; + private int mIdleStylusTimeoutMillis = + DEFAULT_IDLE_STYLUS_TIMEOUT_MILLIS; + private float mBacklightMinimum = Float.NaN; private float mBacklightMaximum = Float.NaN; private float mBrightnessDefault = Float.NaN; @@ -1730,6 +1738,7 @@ public class DisplayDeviceConfig { + ", mDisplayBrightnessMapping= " + mDisplayBrightnessMapping + ", mDdcAutoBrightnessAvailable= " + mDdcAutoBrightnessAvailable + ", mAutoBrightnessAvailable= " + mAutoBrightnessAvailable + + ", mIdleStylusTimeoutMillis= " + mIdleStylusTimeoutMillis + "\n" + "mDefaultLowBlockingZoneRefreshRate= " + mDefaultLowBlockingZoneRefreshRate + ", mDefaultHighBlockingZoneRefreshRate= " + mDefaultHighBlockingZoneRefreshRate @@ -2389,10 +2398,19 @@ public class DisplayDeviceConfig { loadAutoBrightnessDarkeningLightDebounceIdle(autoBrightness); mDisplayBrightnessMapping = new DisplayBrightnessMappingConfig(mContext, mFlags, autoBrightness, getBacklightToBrightnessSpline()); + loadIdleStylusTimeoutMillis(autoBrightness); loadEnableAutoBrightness(autoBrightness); } /** + * Gets the timeout post the stylus usage after which the automatic brightness will be enabled + * again + */ + public int getIdleStylusTimeoutMillis() { + return mIdleStylusTimeoutMillis; + } + + /** * Loads the auto-brightness brightening light debounce. Internally, this takes care of loading * the value from the display config, and if not present, falls back to config.xml. */ @@ -2923,6 +2941,16 @@ public class DisplayDeviceConfig { return levels; } + private void loadIdleStylusTimeoutMillis(AutoBrightness autoBrightness) { + if (autoBrightness == null) { + return; + } + BigInteger idleStylusTimeoutMillis = autoBrightness.getIdleStylusTimeoutMillis(); + if (idleStylusTimeoutMillis != null) { + mIdleStylusTimeoutMillis = idleStylusTimeoutMillis.intValue(); + } + } + private void loadEnableAutoBrightness(AutoBrightness autobrightness) { // mDdcAutoBrightnessAvailable is initialised to true, so that we fallback to using the // config.xml values if the autobrightness tag is not defined in the ddc file. diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 4152ec9e26e3..179ec63458dd 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -1661,33 +1661,49 @@ public final class DisplayManagerService extends SystemService { return false; } + private boolean hasVideoOutputPermission(String func) { + return checkCallingPermission(CAPTURE_VIDEO_OUTPUT, func) + || hasSecureVideoOutputPermission(func); + } + + private boolean hasSecureVideoOutputPermission(String func) { + return checkCallingPermission(CAPTURE_SECURE_VIDEO_OUTPUT, func); + } + + private boolean canCreateMirrorDisplays(IVirtualDevice virtualDevice) { + if (virtualDevice == null) { + return false; + } + try { + return virtualDevice.canCreateMirrorDisplays(); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to query virtual device for permissions", e); + return false; + } + } + private boolean canProjectVideo(IMediaProjection projection) { - if (projection != null) { - try { - if (projection.canProjectVideo()) { - return true; - } - } catch (RemoteException e) { - Slog.e(TAG, "Unable to query projection service for permissions", e); - } + if (projection == null) { + return false; } - if (checkCallingPermission(CAPTURE_VIDEO_OUTPUT, "canProjectVideo()")) { - return true; + try { + return projection.canProjectVideo(); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to query projection service for permissions", e); + return false; } - return canProjectSecureVideo(projection); } private boolean canProjectSecureVideo(IMediaProjection projection) { - if (projection != null) { - try { - if (projection.canProjectSecureVideo()) { - return true; - } - } catch (RemoteException e) { - Slog.e(TAG, "Unable to query projection service for permissions", e); - } + if (projection == null) { + return false; + } + try { + return projection.canProjectSecureVideo(); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to query projection service for permissions", e); + return false; } - return checkCallingPermission(CAPTURE_SECURE_VIDEO_OUTPUT, "canProjectSecureVideo()"); } private boolean checkCallingPermission(String permission, String func) { @@ -1793,7 +1809,8 @@ public final class DisplayManagerService extends SystemService { && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { // Only a valid media projection or a virtual device can create a mirror virtual // display. - if (!canProjectVideo(projection) && virtualDevice == null) { + if (!canProjectVideo(projection) && !canCreateMirrorDisplays(virtualDevice) + && !hasVideoOutputPermission("createVirtualDisplayInternal")) { throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate " + "MediaProjection token in order to create a screen sharing virtual " @@ -1803,7 +1820,8 @@ public final class DisplayManagerService extends SystemService { } } if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { - if (!canProjectSecureVideo(projection)) { + if (!canProjectSecureVideo(projection) + && !hasSecureVideoOutputPermission("createVirtualDisplayInternal")) { throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT " + "or an appropriate MediaProjection token to create a " + "secure virtual display."); @@ -1960,7 +1978,7 @@ public final class DisplayManagerService extends SystemService { // handles stopping the projection. Slog.w(TAG, "Content Recording: failed to start mirroring - " + "releasing virtual display " + displayId); - releaseVirtualDisplayInternal(callback.asBinder()); + releaseVirtualDisplayInternal(callback.asBinder(), callingUid); return Display.INVALID_DISPLAY; } else if (projection != null) { // Indicate that this projection has been used to record, and can't be used @@ -2049,7 +2067,7 @@ public final class DisplayManagerService extends SystemService { // Something weird happened and the logical display was not created. Slog.w(TAG, "Rejecting request to create virtual display " + "because the logical display was not created."); - mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder()); + mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder(), callingUid); mDisplayDeviceRepo.onDisplayDeviceEvent(device, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED); return -1; @@ -2076,14 +2094,14 @@ public final class DisplayManagerService extends SystemService { } } - private void releaseVirtualDisplayInternal(IBinder appToken) { + private void releaseVirtualDisplayInternal(IBinder appToken, int callingUid) { synchronized (mSyncRoot) { if (mVirtualDisplayAdapter == null) { return; } DisplayDevice device = - mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); + mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken, callingUid); Slog.d(TAG, "Virtual Display: Display Device released"); if (device != null) { // TODO: multi-display - handle virtual displays the same as other display adapters. @@ -2093,16 +2111,6 @@ public final class DisplayManagerService extends SystemService { } } - private void setVirtualDisplayStateInternal(IBinder appToken, boolean isOn) { - synchronized (mSyncRoot) { - if (mVirtualDisplayAdapter == null) { - return; - } - - mVirtualDisplayAdapter.setVirtualDisplayStateLocked(appToken, isOn); - } - } - private void setVirtualDisplayRotationInternal(IBinder appToken, @Surface.Rotation int rotation) { int displayId; @@ -2294,6 +2302,9 @@ public final class DisplayManagerService extends SystemService { updateLogicalDisplayState(display); mExternalDisplayPolicy.handleLogicalDisplayAddedLocked(display); + if (mDisplayTopologyCoordinator != null) { + mDisplayTopologyCoordinator.onDisplayAdded(display.getDisplayInfoLocked()); + } } private void handleLogicalDisplayChangedLocked(@NonNull LogicalDisplay display) { @@ -2381,6 +2392,9 @@ public final class DisplayManagerService extends SystemService { } else { releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED); } + if (mDisplayTopologyCoordinator != null) { + mDisplayTopologyCoordinator.onDisplayRemoved(display.getDisplayIdLocked()); + } Slog.i(TAG, "Logical display removed: " + display.getDisplayIdLocked()); } @@ -4606,19 +4620,10 @@ public final class DisplayManagerService extends SystemService { @Override // Binder call public void releaseVirtualDisplay(IVirtualDisplayCallback callback) { + final int callingUid = Binder.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { - releaseVirtualDisplayInternal(callback.asBinder()); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override // Binder call - public void setVirtualDisplayState(IVirtualDisplayCallback callback, boolean isOn) { - final long token = Binder.clearCallingIdentity(); - try { - setVirtualDisplayStateInternal(callback.asBinder(), isOn); + releaseVirtualDisplayInternal(callback.asBinder(), callingUid); } finally { Binder.restoreCallingIdentity(token); } @@ -5235,10 +5240,9 @@ public final class DisplayManagerService extends SystemService { } @Override - public boolean isProximitySensorAvailable() { + public boolean isProximitySensorAvailable(int displayId) { synchronized (mSyncRoot) { - return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) - .isProximitySensorAvailable(); + return mDisplayPowerControllers.get(displayId).isProximitySensorAvailable(); } } @@ -5648,6 +5652,21 @@ public final class DisplayManagerService extends SystemService { public void onPresentation(int displayId, boolean isShown) { mExternalDisplayPolicy.onPresentation(displayId, isShown); } + + @Override + public void stylusGestureStarted(long eventTime) { + if (mFlags.isBlockAutobrightnessChangesOnStylusUsage()) { + DisplayPowerController displayPowerController; + synchronized (mSyncRoot) { + displayPowerController = mDisplayPowerControllers.get( + Display.DEFAULT_DISPLAY); + } + // We assume that the stylus is being used on the default display. This should + // be changed to the displayId on which it is being used once we start getting this + // information from the input manager service + displayPowerController.stylusGestureStarted(eventTime); + } + } } class DesiredDisplayModeSpecsObserver diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 03fec0115613..42a62f098b6a 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -167,12 +167,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private static final int MSG_SET_DWBC_LOGGING_ENABLED = 16; private static final int MSG_SET_BRIGHTNESS_FROM_OFFLOAD = 17; private static final int MSG_OFFLOADING_SCREEN_ON_UNBLOCKED = 18; - - + private static final int MSG_SET_STYLUS_BEING_USED = 19; + private static final int MSG_SET_STYLUS_USE_ENDED = 20; private static final int BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS = 500; - // State machine constants for tracking initial brightness ramp skipping when enabled. private static final int RAMP_STATE_SKIP_NONE = 0; private static final int RAMP_STATE_SKIP_INITIAL = 1; @@ -191,6 +190,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200, 1400, 1600, 1800, 2000, 2250, 2500, 2750, 3000}; + + private static final int STYLUS_USAGE_DEBOUNCE_TIME = 1000; + private static final int NANO_SECONDS_TO_MILLI_SECONDS_RATIO = 1_000_000; + private static final int[] BRIGHTNESS_RANGE_INDEX = { FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_UNKNOWN, FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_0_1, @@ -498,6 +501,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call @GuardedBy("mLock") private int mPendingOverrideDozeScreenStateLocked; + private long mLastStylusUsageEventTime = -1; + + // The time of inactivity after which the stylus can be assumed to be no longer in use. + private long mIdleStylusTimeoutMillisConfig = 0; + /** * Creates the display power controller. */ @@ -518,6 +526,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mSensorManager = sensorManager; mHandler = new DisplayControllerHandler(handler.getLooper()); mDisplayDeviceConfig = mDisplayDevice.getDisplayDeviceConfig(); + mIdleStylusTimeoutMillisConfig = mDisplayDeviceConfig.getIdleStylusTimeoutMillis(); mIsEnabled = logicalDisplay.isEnabledLocked(); mIsInTransition = logicalDisplay.isInTransitionLocked(); mIsDisplayInternal = displayDeviceInfo.type == Display.TYPE_INTERNAL; @@ -537,7 +546,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mLastBrightnessEvent = new BrightnessEvent(mDisplayId); mTempBrightnessEvent = new BrightnessEvent(mDisplayId); - if (flags.isBatteryStatsEnabledForAllDisplays()) { + if (flags.isBatteryStatsEnabledForAllDisplays() + && isDisplaySupportedForBatteryStats(displayDeviceInfo)) { mBatteryStats = BatteryStatsService.getService(); } else if (mDisplayId == Display.DEFAULT_DISPLAY) { mBatteryStats = BatteryStatsService.getService(); @@ -893,6 +903,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mPhysicalDisplayName = displayName; mDisplayStatsId = mUniqueDisplayId.hashCode(); mDisplayDeviceConfig = config; + mIdleStylusTimeoutMillisConfig = mDisplayDeviceConfig.getIdleStylusTimeoutMillis(); mThermalBrightnessThrottlingDataId = thermalBrightnessThrottlingDataId; loadFromDisplayDeviceConfig(token, info, hbmMetadata); mDisplayPowerProximityStateController.notifyDisplayDeviceChanged(config); @@ -2762,6 +2773,16 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } + private static boolean isDisplaySupportedForBatteryStats(DisplayDeviceInfo displayDeviceInfo) { + switch (displayDeviceInfo.type) { + case Display.TYPE_INTERNAL: + case Display.TYPE_EXTERNAL: + return true; + default: + return false; + } + } + private void dumpBrightnessEvents(PrintWriter pw) { int size = mBrightnessEventRingBuffer.size(); if (size < 1) { @@ -2971,6 +2992,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call return mDisplayId == Display.DEFAULT_DISPLAY || mBootCompleted; } + public void stylusGestureStarted(long eventTimeNanoSeconds) { + long eventTimeMs = eventTimeNanoSeconds / NANO_SECONDS_TO_MILLI_SECONDS_RATIO; + if (mLastStylusUsageEventTime == -1 + || eventTimeMs > mLastStylusUsageEventTime + STYLUS_USAGE_DEBOUNCE_TIME) { + synchronized (mLock) { + // Add a message to notify the stylus usage has started + mHandler.sendEmptyMessageAtTime(MSG_SET_STYLUS_BEING_USED, mClock.uptimeMillis()); + } + mLastStylusUsageEventTime = eventTimeMs; + } + } + private final class DisplayControllerHandler extends Handler { DisplayControllerHandler(Looper looper) { super(looper, null, true /*async*/); @@ -3087,6 +3120,20 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call updatePowerState(); } break; + case MSG_SET_STYLUS_BEING_USED: + // Remove any MSG_SET_STYLUS_USE_ENDED message from the handler queue and + // post a delayed MSG_SET_STYLUS_USE_ENDED message to delay the stylus + // usage ended event processing + mHandler.removeMessages(MSG_SET_STYLUS_USE_ENDED); + Message message = mHandler.obtainMessage(MSG_SET_STYLUS_USE_ENDED); + mHandler.sendMessageAtTime(message, + mClock.uptimeMillis() + mIdleStylusTimeoutMillisConfig); + mDisplayBrightnessController.setStylusBeingUsed(true); + break; + case MSG_SET_STYLUS_USE_ENDED: + mDisplayBrightnessController.setStylusBeingUsed(false); + updatePowerState(); + break; } } } diff --git a/services/core/java/com/android/server/display/DisplayTopology.java b/services/core/java/com/android/server/display/DisplayTopology.java index 90038a09850f..b01d61721c9c 100644 --- a/services/core/java/com/android/server/display/DisplayTopology.java +++ b/services/core/java/com/android/server/display/DisplayTopology.java @@ -20,12 +20,15 @@ import android.annotation.Nullable; import android.util.IndentingPrintWriter; import android.util.Pair; import android.util.Slog; +import android.view.Display; import com.android.internal.annotations.VisibleForTesting; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; +import java.util.Queue; /** * Represents the relative placement of extended displays. @@ -45,35 +48,50 @@ class DisplayTopology { * This is not necessarily the same as the default display. */ @VisibleForTesting - int mPrimaryDisplayId; + int mPrimaryDisplayId = Display.INVALID_DISPLAY; /** * Add a display to the topology. * If this is the second display in the topology, it will be placed above the first display. * Subsequent displays will be places to the left or right of the second display. - * @param displayId The ID of the display + * @param displayId The logical display ID * @param width The width of the display * @param height The height of the display */ void addDisplay(int displayId, double width, double height) { - if (mRoot == null) { - mRoot = new TreeNode(displayId, width, height, /* position= */ null, /* offset= */ 0); - mPrimaryDisplayId = displayId; - Slog.i(TAG, "First display added: " + mRoot); - } else if (mRoot.mChildren.isEmpty()) { - // This is the 2nd display. Align the middles of the top and bottom edges. - double offset = mRoot.mWidth / 2 - width / 2; - TreeNode display = new TreeNode(displayId, width, height, - TreeNode.Position.POSITION_TOP, offset); - mRoot.mChildren.add(display); - Slog.i(TAG, "Second display added: " + display + ", parent ID: " + mRoot.mDisplayId); + addDisplay(displayId, width, height, /* shouldLog= */ true); + } + + /** + * Remove a display from the topology. + * The default topology is created from the remaining displays, as if they were reconnected + * one by one. + * @param displayId The logical display ID + */ + void removeDisplay(int displayId) { + if (!isDisplayPresent(displayId, mRoot)) { + return; + } + Queue<TreeNode> queue = new LinkedList<>(); + queue.add(mRoot); + mRoot = null; + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + if (node.mDisplayId != displayId) { + addDisplay(node.mDisplayId, node.mWidth, node.mHeight, /* shouldLog= */ false); + } + queue.addAll(node.mChildren); + } + if (mPrimaryDisplayId == displayId) { + if (mRoot != null) { + mPrimaryDisplayId = mRoot.mDisplayId; + } else { + mPrimaryDisplayId = Display.INVALID_DISPLAY; + } + Slog.i(TAG, "Primary display with ID " + displayId + + " removed, new primary display: " + mPrimaryDisplayId); } else { - TreeNode rightMostDisplay = findRightMostDisplay(mRoot, mRoot.mWidth).first; - TreeNode newDisplay = new TreeNode(displayId, width, height, - TreeNode.Position.POSITION_RIGHT, /* offset= */ 0); - rightMostDisplay.mChildren.add(newDisplay); - Slog.i(TAG, "Display added: " + newDisplay + ", parent ID: " - + rightMostDisplay.mDisplayId); + Slog.i(TAG, "Display with ID " + displayId + " removed"); } } @@ -97,6 +115,35 @@ class DisplayTopology { } } + private void addDisplay(int displayId, double width, double height, boolean shouldLog) { + if (mRoot == null) { + mRoot = new TreeNode(displayId, width, height, /* position= */ null, /* offset= */ 0); + mPrimaryDisplayId = displayId; + if (shouldLog) { + Slog.i(TAG, "First display added: " + mRoot); + } + } else if (mRoot.mChildren.isEmpty()) { + // This is the 2nd display. Align the middles of the top and bottom edges. + double offset = mRoot.mWidth / 2 - width / 2; + TreeNode display = new TreeNode(displayId, width, height, + TreeNode.Position.POSITION_TOP, offset); + mRoot.mChildren.add(display); + if (shouldLog) { + Slog.i(TAG, "Second display added: " + display + ", parent ID: " + + mRoot.mDisplayId); + } + } else { + TreeNode rightMostDisplay = findRightMostDisplay(mRoot, mRoot.mWidth).first; + TreeNode newDisplay = new TreeNode(displayId, width, height, + TreeNode.Position.POSITION_RIGHT, /* offset= */ 0); + rightMostDisplay.mChildren.add(newDisplay); + if (shouldLog) { + Slog.i(TAG, "Display added: " + newDisplay + ", parent ID: " + + rightMostDisplay.mDisplayId); + } + } + } + /** * @param display The display from which the search should start. * @param xPos The x position of the right edge of that display. @@ -126,6 +173,21 @@ class DisplayTopology { return result; } + private boolean isDisplayPresent(int displayId, TreeNode node) { + if (node == null) { + return false; + } + if (node.mDisplayId == displayId) { + return true; + } + for (TreeNode child : node.mChildren) { + if (isDisplayPresent(displayId, child)) { + return true; + } + } + return false; + } + @VisibleForTesting static class TreeNode { diff --git a/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java b/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java index cbd224c3d842..46358dfd90ec 100644 --- a/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java +++ b/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java @@ -66,6 +66,16 @@ class DisplayTopologyCoordinator { } /** + * Remove a display from the topology. + * @param displayId The logical display ID + */ + void onDisplayRemoved(int displayId) { + synchronized (mLock) { + mTopology.removeDisplay(displayId); + } + } + + /** * Print the object's state and debug information into the given stream. * @param pw The stream to dump information to. */ diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java index bcb600d0f91c..06a910396d6c 100644 --- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java +++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java @@ -355,8 +355,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { public SparseArray<int[]> getDisplayIdsByGroupIdLocked() { SparseArray<int[]> displayIdsByGroupIds = new SparseArray<>(); for (int i = 0; i < mDisplayGroups.size(); i++) { - int groupId = mDisplayGroups.get(i).getGroupId(); - displayIdsByGroupIds.put(groupId, getDisplayIdsForGroupLocked(groupId)); + final int displayGroupId = mDisplayGroups.keyAt(i); + displayIdsByGroupIds.put(displayGroupId, getDisplayIdsForGroupLocked(displayGroupId)); } return displayIdsByGroupIds; } diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index 9b02f4b71ebe..421145390190 100644 --- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -55,12 +55,14 @@ import android.os.RemoteException; import android.os.SystemProperties; import android.util.ArrayMap; import android.util.Slog; +import android.util.SparseIntArray; import android.view.Display; import android.view.DisplayCutout; import android.view.DisplayShape; import android.view.Surface; import android.view.SurfaceControl; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.feature.DisplayManagerFlags; @@ -85,6 +87,11 @@ public class VirtualDisplayAdapter extends DisplayAdapter { private static final AtomicInteger sNextUniqueIndex = new AtomicInteger(0); private final ArrayMap<IBinder, VirtualDisplayDevice> mVirtualDisplayDevices = new ArrayMap<>(); + + private final int mMaxDevices; + private final int mMaxDevicesPerPackage; + private final SparseIntArray mNoOfDevicesPerPackage = new SparseIntArray(); + private final Handler mHandler; private final SurfaceControlDisplayFactory mSurfaceControlDisplayFactory; @@ -114,8 +121,31 @@ public class VirtualDisplayAdapter extends DisplayAdapter { super(syncRoot, context, handler, listener, TAG, featureFlags); mHandler = handler; mSurfaceControlDisplayFactory = surfaceControlDisplayFactory; + + mMaxDevices = context.getResources().getInteger(R.integer.config_virtualDisplayLimit); + if (mMaxDevices < 1) { + throw new IllegalArgumentException("The limit of virtual displays must be >= 1"); + } + mMaxDevicesPerPackage = + context.getResources().getInteger(R.integer.config_virtualDisplayLimitPerPackage); + if (mMaxDevicesPerPackage < 1) { + throw new IllegalArgumentException( + "The limit of virtual displays per package must be >= 1"); + } } + /** + * Create a virtual display + * @param callback The callback + * @param projection The media projection + * @param ownerUid The UID of the package creating a display + * @param ownerPackageName The name of the package creating a display + * @param uniqueId The unique ID of the display device + * @param surface The surface + * @param flags The flags + * @param virtualDisplayConfig The config + * @return The display device created + */ public DisplayDevice createVirtualDisplayLocked(IVirtualDisplayCallback callback, IMediaProjection projection, int ownerUid, String ownerPackageName, String uniqueId, Surface surface, int flags, VirtualDisplayConfig virtualDisplayConfig) { @@ -126,6 +156,22 @@ public class VirtualDisplayAdapter extends DisplayAdapter { return null; } + if (getFeatureFlags().isVirtualDisplayLimitEnabled() + && mVirtualDisplayDevices.size() >= mMaxDevices) { + Slog.w(TAG, "Rejecting request to create private virtual display because " + + mMaxDevices + " devices already exist."); + return null; + } + + int noOfDevices = mNoOfDevicesPerPackage.get(ownerUid, /* valueIfKeyNotFound= */ 0); + if (getFeatureFlags().isVirtualDisplayLimitEnabled() + && noOfDevices >= mMaxDevicesPerPackage) { + Slog.w(TAG, "Rejecting request to create private virtual display because " + + mMaxDevicesPerPackage + " devices already exist for package " + + ownerPackageName + "."); + return null; + } + String name = virtualDisplayConfig.getName(); boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0; @@ -140,6 +186,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter { projection, mediaProjectionCallback, uniqueId, virtualDisplayConfig); mVirtualDisplayDevices.put(appToken, device); + if (getFeatureFlags().isVirtualDisplayLimitEnabled()) { + mNoOfDevicesPerPackage.put(ownerUid, noOfDevices + 1); + } try { if (projection != null) { @@ -150,7 +199,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { appToken.linkToDeath(device, 0); } catch (RemoteException ex) { Slog.e(TAG, "Virtual Display: error while setting up VirtualDisplayDevice", ex); - mVirtualDisplayDevices.remove(appToken); + removeVirtualDisplayDeviceLocked(appToken, ownerUid); device.destroyLocked(false); return null; } @@ -194,8 +243,15 @@ public class VirtualDisplayAdapter extends DisplayAdapter { } } - public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) { - VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken); + /** + * Release a virtual display that was previously created + * @param appToken The token to identify the display + * @param ownerUid The UID of the package, used to keep track of and limit the number of + * displays created per package + * @return The display device that has been removed + */ + public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken, int ownerUid) { + VirtualDisplayDevice device = removeVirtualDisplayDeviceLocked(appToken, ownerUid); if (device != null) { Slog.v(TAG, "Release VirtualDisplay " + device.mName); device.destroyLocked(true); @@ -207,13 +263,6 @@ public class VirtualDisplayAdapter extends DisplayAdapter { return device; } - void setVirtualDisplayStateLocked(IBinder appToken, boolean isOn) { - VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken); - if (device != null) { - device.setDisplayState(isOn); - } - } - DisplayDevice getDisplayDevice(IBinder appToken) { return mVirtualDisplayDevices.get(appToken); } @@ -235,10 +284,6 @@ public class VirtualDisplayAdapter extends DisplayAdapter { : ("," + uid + "," + config.getName() + "," + sNextUniqueIndex.getAndIncrement())); } - private void handleBinderDiedLocked(IBinder appToken) { - mVirtualDisplayDevices.remove(appToken); - } - private void handleMediaProjectionStoppedLocked(IBinder appToken) { VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken); if (device != null) { @@ -248,6 +293,18 @@ public class VirtualDisplayAdapter extends DisplayAdapter { } } + private VirtualDisplayDevice removeVirtualDisplayDeviceLocked(IBinder appToken, int ownerUid) { + int noOfDevices = mNoOfDevicesPerPackage.get(ownerUid, /* valueIfKeyNotFound= */ 0); + if (getFeatureFlags().isVirtualDisplayLimitEnabled()) { + if (noOfDevices <= 1) { + mNoOfDevicesPerPackage.delete(ownerUid); + } else { + mNoOfDevicesPerPackage.put(ownerUid, noOfDevices - 1); + } + } + return mVirtualDisplayDevices.remove(appToken); + } + private final class VirtualDisplayDevice extends DisplayDevice implements DeathRecipient { private static final int PENDING_SURFACE_CHANGE = 0x01; private static final int PENDING_RESIZE = 0x02; @@ -273,7 +330,6 @@ public class VirtualDisplayAdapter extends DisplayAdapter { private boolean mStopped; private int mPendingChanges; private Display.Mode mMode; - private boolean mIsDisplayOn; private int mDisplayIdToMirror; private boolean mIsWindowManagerMirroring; private DisplayCutout mDisplayCutout; @@ -299,9 +355,8 @@ public class VirtualDisplayAdapter extends DisplayAdapter { mCallback = callback; mProjection = projection; mMediaProjectionCallback = mediaProjectionCallback; - mDisplayState = Display.STATE_UNKNOWN; + mDisplayState = Display.STATE_ON; mPendingChanges |= PENDING_SURFACE_CHANGE; - mIsDisplayOn = surface != null; mDisplayIdToMirror = virtualDisplayConfig.getDisplayIdToMirror(); mIsWindowManagerMirroring = virtualDisplayConfig.isWindowManagerMirroringEnabled(); } @@ -309,7 +364,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { @Override public void binderDied() { synchronized (getSyncRoot()) { - handleBinderDiedLocked(mAppToken); + removeVirtualDisplayDeviceLocked(mAppToken, mOwnerUid); Slog.i(TAG, "Virtual display device released because application token died: " + mOwnerPackageName); destroyLocked(false); @@ -394,6 +449,8 @@ public class VirtualDisplayAdapter extends DisplayAdapter { float sdrBrightnessState, DisplayOffloadSessionImpl displayOffloadSession) { if (state != mDisplayState) { mDisplayState = state; + mInfo = null; + sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED); if (state == Display.STATE_OFF) { mCallback.dispatchDisplayPaused(); } else { @@ -416,12 +473,13 @@ public class VirtualDisplayAdapter extends DisplayAdapter { public void setSurfaceLocked(Surface surface) { if (!mStopped && mSurface != surface) { - if ((mSurface != null) != (surface != null)) { + if (mDisplayState == Display.STATE_ON + && ((mSurface == null) != (surface == null))) { + mInfo = null; sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED); } sendTraversalRequestLocked(); mSurface = surface; - mInfo = null; mPendingChanges |= PENDING_SURFACE_CHANGE; } } @@ -439,14 +497,6 @@ public class VirtualDisplayAdapter extends DisplayAdapter { } } - void setDisplayState(boolean isOn) { - if (mIsDisplayOn != isOn) { - mIsDisplayOn = isOn; - mInfo = null; - sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED); - } - } - public void stopLocked() { Slog.d(TAG, "Virtual Display: stopping device " + mName); setSurfaceLocked(null); @@ -567,7 +617,11 @@ public class VirtualDisplayAdapter extends DisplayAdapter { mInfo.touch = ((mFlags & VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH) == 0) ? DisplayDeviceInfo.TOUCH_NONE : DisplayDeviceInfo.TOUCH_VIRTUAL; - mInfo.state = mIsDisplayOn ? Display.STATE_ON : Display.STATE_OFF; + if (mSurface == null) { + mInfo.state = Display.STATE_OFF; + } else { + mInfo.state = mDisplayState; + } mInfo.ownerUid = mOwnerUid; mInfo.ownerPackageName = mOwnerPackageName; diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java index 72a91d59c911..71fdaf3f85b6 100644 --- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java +++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java @@ -501,6 +501,13 @@ public final class DisplayBrightnessController { return true; } + /** + * Notifies if the stylus is currently being used or not. + */ + public void setStylusBeingUsed(boolean isEnabled) { + // Todo(b/369977976) - Disable the auto-brightness strategy + } + @VisibleForTesting static class Injector { DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(Context context, diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java index df66893a2f35..eeec36919480 100644 --- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java @@ -199,10 +199,19 @@ public class DisplayManagerFlags { Flags.FLAG_IDLE_SCREEN_CONFIG_IN_SUBSCRIBING_LIGHT_SENSOR, Flags::idleScreenConfigInSubscribingLightSensor); + private final FlagState mVirtualDisplayLimit = + new FlagState( + Flags.FLAG_VIRTUAL_DISPLAY_LIMIT, + Flags::virtualDisplayLimit); + private final FlagState mNormalBrightnessForDozeParameter = new FlagState( Flags.FLAG_NORMAL_BRIGHTNESS_FOR_DOZE_PARAMETER, Flags::normalBrightnessForDozeParameter ); + private final FlagState mBlockAutobrightnessChangesOnStylusUsage = new FlagState( + Flags.FLAG_BLOCK_AUTOBRIGHTNESS_CHANGES_ON_STYLUS_USAGE, + Flags::blockAutobrightnessChangesOnStylusUsage + ); private final FlagState mEnableBatteryStatsForAllDisplays = new FlagState( Flags.FLAG_ENABLE_BATTERY_STATS_FOR_ALL_DISPLAYS, @@ -412,6 +421,10 @@ public class DisplayManagerFlags { return mNewHdrBrightnessModifier.isEnabled(); } + public boolean isVirtualDisplayLimitEnabled() { + return mVirtualDisplayLimit.isEnabled(); + } + /** * @return Whether the useDozeBrightness parameter should be used */ @@ -436,6 +449,13 @@ public class DisplayManagerFlags { } /** + * @return {@code true} if autobrightness is to be blocked when stylus is being used + */ + public boolean isBlockAutobrightnessChangesOnStylusUsage() { + return mBlockAutobrightnessChangesOnStylusUsage.isEnabled(); + } + + /** * dumps all flagstates * @param pw printWriter */ @@ -476,9 +496,11 @@ public class DisplayManagerFlags { pw.println(" " + mOffloadDozeOverrideHoldsWakelock); pw.println(" " + mOffloadSessionCancelBlockScreenOn); pw.println(" " + mNewHdrBrightnessModifier); + pw.println(" " + mVirtualDisplayLimit); pw.println(" " + mNormalBrightnessForDozeParameter); pw.println(" " + mIdleScreenConfigInSubscribingLightSensor); pw.println(" " + mEnableBatteryStatsForAllDisplays); + pw.println(" " + mBlockAutobrightnessChangesOnStylusUsage); } private static class FlagState { diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig index e3ebe5bcd9ed..20ecd2d8303e 100644 --- a/services/core/java/com/android/server/display/feature/display_flags.aconfig +++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig @@ -348,6 +348,14 @@ flag { } flag { + name: "virtual_display_limit" + namespace: "display_manager" + description: "Limit the number of virtual displays that can be created." + bug: "261791612" + is_fixed_read_only: true +} + +flag { name: "idle_screen_config_in_subscribing_light_sensor" namespace: "display_manager" description: "Account for Idle screen refresh rate configs while subscribing to light sensor" @@ -364,4 +372,12 @@ flag { description: "Flag to enable battery stats for all displays." bug: "366112793" is_fixed_read_only: true -}
\ No newline at end of file +} + +flag { + name: "block_autobrightness_changes_on_stylus_usage" + namespace: "display_manager" + description: "Block the usage of ALS to control the display brightness when stylus is being used" + bug: "352411468" + is_fixed_read_only: true +} diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index b78f8a7d8ee7..0e7d2b631833 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -509,6 +509,21 @@ final class Constants { static final String PROPERTY_STRIP_AUDIO_TV_NO_SYSTEM_AUDIO = "persist.sys.hdmi.property_strip_audio_tv_no_system_audio"; + /** + * Property that decides whether CEC should be disabled on standby when the low energy mode + * option is used. + */ + static final String PROPERTY_WAS_CEC_DISABLED_ON_STANDBY_BY_LOW_ENERGY_MODE = + "persist.sys.hdmi.property_was_cec_disabled_on_standby_by_low_energy_mode"; + + /** + * Property that checks if CEC was disabled on standby by low energy mode. With the help of this + * property we avoid re-enabling CEC if the user explicitly disabled it, unrelated to the + * selected energy mode. + */ + static final String PROPERTY_DISABLE_CEC_ON_STANDBY_IN_LOW_ENERGY_MODE = + "persist.sys.hdmi.property_disable_cec_on_standby_in_low_energy_mode"; + static final int RECORDING_TYPE_DIGITAL_RF = 1; static final int RECORDING_TYPE_ANALOGUE_RF = 2; static final int RECORDING_TYPE_EXTERNAL_PHYSICAL_ADDRESS = 3; @@ -644,6 +659,11 @@ final class Constants { }) @interface FeatureFlag {} + /** + * Identifier key for Low energy mode. + */ + static final String KEY_LOW_ENERGY_USE = "low_energy_use"; + private Constants() { /* cannot be instantiated */ } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 8e41d18f0953..81be0baefd7a 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -22,6 +22,7 @@ import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_ADD_DEVICE; import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE; import static android.hardware.hdmi.HdmiControlManager.EARC_FEATURE_DISABLED; import static android.hardware.hdmi.HdmiControlManager.EARC_FEATURE_ENABLED; +import static android.hardware.hdmi.HdmiControlManager.HDMI_CEC_CONTROL_DISABLED; import static android.hardware.hdmi.HdmiControlManager.HDMI_CEC_CONTROL_ENABLED; import static android.hardware.hdmi.HdmiControlManager.POWER_CONTROL_MODE_NONE; import static android.hardware.hdmi.HdmiControlManager.SOUNDBAR_MODE_DISABLED; @@ -478,7 +479,8 @@ public class HdmiControlService extends SystemService { @Nullable private HdmiCecController mCecController; - private HdmiCecPowerStatusController mPowerStatusController; + @VisibleForTesting + protected HdmiCecPowerStatusController mPowerStatusController; @Nullable private HdmiEarcController mEarcController; @@ -3814,7 +3816,32 @@ public class HdmiControlService extends SystemService { mPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON, false); if (mCecController != null) { - if (isCecControlEnabled()) { + if (isTvDevice() && getWasCecDisabledOnStandbyByLowEnergyMode()) { + Slog.w(TAG, "Re-enable CEC on wake-up since it was disabled due to low energy " + + " mode."); + getHdmiCecConfig().setIntValue(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, + HDMI_CEC_CONTROL_ENABLED); + setWasCecDisabledOnStandbyByLowEnergyMode(false); + int controlStateChangedReason = -1; + switch (wakeUpAction) { + case WAKE_UP_SCREEN_ON: + controlStateChangedReason = + HdmiControlManager.CONTROL_STATE_CHANGED_REASON_WAKEUP; + break; + case WAKE_UP_BOOT_UP: + controlStateChangedReason = + HdmiControlManager.CONTROL_STATE_CHANGED_REASON_START; + break; + default: + Slog.e(TAG, "wakeUpAction " + wakeUpAction + " not defined."); + return; + + } + // Since CEC is going to be initialized by the setting value update, we must invoke + // the vendor command listeners here with the reason TV woke up. + invokeVendorCommandListenersOnControlStateChanged(true, + controlStateChangedReason); + } else if (isCecControlEnabled()) { int startReason = -1; switch (wakeUpAction) { case WAKE_UP_SCREEN_ON: @@ -3988,6 +4015,14 @@ public class HdmiControlService extends SystemService { if (isAudioSystemDevice() || !isPowerStandby()) { return; } + if (isTvDevice() && getDisableCecOnStandbyByLowEnergyMode() + && mPowerManager.isLowPowerStandbyEnabled()) { + Slog.w(TAG, "Disable CEC on standby due to low power energy mode."); + setWasCecDisabledOnStandbyByLowEnergyMode(true); + getHdmiCecConfig().setIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, + HDMI_CEC_CONTROL_DISABLED); + } mCecController.enableSystemCecControl(false); mMhlController.setOption(OPTION_MHL_SERVICE_CONTROL, DISABLED); } @@ -5148,4 +5183,34 @@ public class HdmiControlService extends SystemService { protected boolean isHdmiControlEnhancedBehaviorFlagEnabled() { return hdmiControlEnhancedBehavior(); } + + /** + * Reads the property value that decides whether CEC should be disabled on standby when the low + * energy mode option is used. + */ + @VisibleForTesting + protected boolean getDisableCecOnStandbyByLowEnergyMode() { + return SystemProperties.getBoolean( + Constants.PROPERTY_DISABLE_CEC_ON_STANDBY_IN_LOW_ENERGY_MODE, false); + } + + /** + * Reads the property that checks if CEC was disabled on standby by low energy mode. + */ + @VisibleForTesting + protected boolean getWasCecDisabledOnStandbyByLowEnergyMode() { + return SystemProperties.getBoolean( + Constants.PROPERTY_WAS_CEC_DISABLED_ON_STANDBY_BY_LOW_ENERGY_MODE, false); + } + + /** + * Sets the truth value of the property that checks if CEC was disabled on standby by low energy + * mode. + */ + @VisibleForTesting + protected void setWasCecDisabledOnStandbyByLowEnergyMode(boolean value) { + writeStringSystemProperty( + Constants.PROPERTY_WAS_CEC_DISABLED_ON_STANDBY_BY_LOW_ENERGY_MODE, + String.valueOf(value)); + } } diff --git a/services/core/java/com/android/server/hdmi/HdmiEarcController.java b/services/core/java/com/android/server/hdmi/HdmiEarcController.java index 46a8f039584b..1c947e9d626d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiEarcController.java +++ b/services/core/java/com/android/server/hdmi/HdmiEarcController.java @@ -87,8 +87,8 @@ final class HdmiEarcController { } catch (ServiceSpecificException sse) { HdmiLogger.error( "Could not set eARC enabled to " + enabled + ". Error: ", sse.errorCode); - } catch (RemoteException re) { - HdmiLogger.error("Could not set eARC enabled to " + enabled + ":. Exception: ", re); + } catch (RemoteException | NullPointerException e) { + HdmiLogger.error("Could not set eARC enabled to " + enabled + ":. Exception: ", e); } } @@ -96,8 +96,8 @@ final class HdmiEarcController { public boolean nativeIsEarcEnabled() { try { return mEarc.isEArcEnabled(); - } catch (RemoteException re) { - HdmiLogger.error("Could not read if eARC is enabled. Exception: ", re); + } catch (RemoteException | NullPointerException e) { + HdmiLogger.error("Could not read if eARC is enabled. Exception: ", e); return false; } } @@ -107,8 +107,8 @@ final class HdmiEarcController { mEarcCallback = callback; try { mEarc.setCallback(callback); - } catch (RemoteException re) { - HdmiLogger.error("Could not set callback. Exception: ", re); + } catch (RemoteException | NullPointerException e) { + HdmiLogger.error("Could not set callback. Exception: ", e); } } @@ -116,8 +116,8 @@ final class HdmiEarcController { public byte nativeGetState(int portId) { try { return mEarc.getState(portId); - } catch (RemoteException re) { - HdmiLogger.error("Could not get eARC state. Exception: ", re); + } catch (RemoteException | NullPointerException e) { + HdmiLogger.error("Could not get eARC state. Exception: ", e); return -1; } } @@ -126,9 +126,9 @@ final class HdmiEarcController { public byte[] nativeGetLastReportedAudioCapabilities(int portId) { try { return mEarc.getLastReportedAudioCapabilities(portId); - } catch (RemoteException re) { + } catch (RemoteException | NullPointerException e) { HdmiLogger.error( - "Could not read last reported audio capabilities. Exception: ", re); + "Could not read last reported audio capabilities. Exception: ", e); return null; } } diff --git a/services/core/java/com/android/server/hdmi/PowerManagerWrapper.java b/services/core/java/com/android/server/hdmi/PowerManagerWrapper.java index 7530b3b239b4..5292cbbb9336 100644 --- a/services/core/java/com/android/server/hdmi/PowerManagerWrapper.java +++ b/services/core/java/com/android/server/hdmi/PowerManagerWrapper.java @@ -16,6 +16,8 @@ package com.android.server.hdmi; +import static com.android.server.hdmi.Constants.KEY_LOW_ENERGY_USE; + import android.content.Context; import android.os.PowerManager; @@ -47,6 +49,12 @@ public class PowerManagerWrapper { return new DefaultWakeLockWrapper(mPowerManager.newWakeLock(levelAndFlags, tag)); } + boolean isLowPowerStandbyEnabled() { + PowerManager.LowPowerStandbyPolicy lowPowerStandbyPolicy + = mPowerManager.getLowPowerStandbyPolicy(); + return lowPowerStandbyPolicy.getIdentifier().equals(KEY_LOW_ENERGY_USE); + } + /** * "Default" wrapper for {@link PowerManager.WakeLock}, as opposed to a "Fake" wrapper for * testing - see {@link FakePowerManagerWrapper.FakeWakeLockWrapper}. diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index f04557665477..8acf583e0765 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -2694,6 +2694,9 @@ public class InputManagerService extends IInputManager.Stub @SuppressWarnings("unused") private void notifyStylusGestureStarted(int deviceId, long eventTime) { mBatteryController.notifyStylusGestureStarted(deviceId, eventTime); + if (mDisplayManagerInternal != null) { + mDisplayManagerInternal.stylusGestureStarted(eventTime); + } } /** diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 3780fbd61e79..bbdac5636fa4 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -99,6 +99,7 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.ShellCallback; +import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; @@ -126,6 +127,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.LongSparseArray; +import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; @@ -253,6 +255,8 @@ public class LockSettingsService extends ILockSettings.Stub { private static final String MIGRATED_KEYSTORE_NS = "migrated_keystore_namespace"; private static final String MIGRATED_SP_CE_ONLY = "migrated_all_users_to_sp_and_bound_ce"; private static final String MIGRATED_SP_FULL = "migrated_all_users_to_sp_and_bound_keys"; + private static final String MIGRATED_WEAVER_DISABLED_ON_UNSECURED_USERS = + "migrated_weaver_disabled_on_unsecured_users"; // Duration that LockSettingsService will store the gatekeeper password for. This allows // multiple biometric enrollments without prompting the user to enter their password via @@ -309,6 +313,10 @@ public class LockSettingsService extends ILockSettings.Stub { @GuardedBy("mUserCreationAndRemovalLock") private boolean mThirdPartyAppsStarted; + // This list contains the (protectorId, userId) of any protectors that were by replaced by a + // migration and should be destroyed once rollback to the old build is no longer possible. + private ArrayList<Pair<Long, Integer>> mProtectorsToDestroyOnBootCompleted = new ArrayList<>(); + // Current password metrics for all secured users on the device. Updated when user unlocks the // device or changes password. Removed if user is stopped with its CE key evicted. @GuardedBy("this") @@ -363,6 +371,10 @@ public class LockSettingsService extends ILockSettings.Stub { mLockSettingsService.migrateOldDataAfterSystemReady(); mLockSettingsService.deleteRepairModePersistentDataIfNeeded(); } else if (phase == PHASE_BOOT_COMPLETED) { + // In the case of an upgrade, PHASE_BOOT_COMPLETED means that a rollback to the old + // build can no longer occur. This is the time to destroy any migrated protectors. + mLockSettingsService.destroyMigratedProtectors(); + mLockSettingsService.loadEscrowData(); } } @@ -1076,6 +1088,11 @@ public class LockSettingsService extends ILockSettings.Stub { mStorage.deleteRepairModePersistentData(); } + private boolean isWeaverDisabledOnUnsecuredUsers() { + return mContext.getResources().getBoolean( + com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers); + } + // This is called when Weaver is guaranteed to be available (if the device supports Weaver). // It does any synthetic password related work that was delayed from earlier in the boot. private void onThirdPartyAppsStarted() { @@ -1114,13 +1131,20 @@ public class LockSettingsService extends ILockSettings.Stub { // // - Upgrading from Android 14, where unsecured users didn't have Keystore super keys. // + // - Upgrading from a build with config_disableWeaverOnUnsecuredUsers=false to one with + // config_disableWeaverOnUnsecuredUsers=true. (We don't bother to proactively add + // Weaver for the reverse update to false, as it's too late to help in that case.) + // // The end result is that all users, regardless of whether they are secured or not, have - // a synthetic password with all keys initialized and protected by it. + // a synthetic password with all keys initialized and protected by it, and honoring + // config_disableWeaverOnUnsecuredUsers=true when applicable. // // Note: if this migration gets interrupted (e.g. by the device powering off), there // shouldn't be a problem since this will run again on the next boot, and // setCeStorageProtection() and initKeystoreSuperKeys(..., true) are idempotent. - if (!getBoolean(MIGRATED_SP_FULL, false, 0)) { + if (!getBoolean(MIGRATED_SP_FULL, false, 0) + || (isWeaverDisabledOnUnsecuredUsers() + && !getBoolean(MIGRATED_WEAVER_DISABLED_ON_UNSECURED_USERS, false, 0))) { for (UserInfo user : mUserManager.getAliveUsers()) { removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber); synchronized (mSpManager) { @@ -1128,6 +1152,9 @@ public class LockSettingsService extends ILockSettings.Stub { } } setBoolean(MIGRATED_SP_FULL, true, 0); + if (isWeaverDisabledOnUnsecuredUsers()) { + setBoolean(MIGRATED_WEAVER_DISABLED_ON_UNSECURED_USERS, true, 0); + } } mThirdPartyAppsStarted = true; @@ -1151,13 +1178,61 @@ public class LockSettingsService extends ILockSettings.Stub { getGateKeeperService(), protectorId, LockscreenCredential.createNone(), userId, null); SyntheticPassword sp = result.syntheticPassword; - if (sp == null) { + if (isWeaverDisabledOnUnsecuredUsers()) { + Slog.i(TAG, "config_disableWeaverOnUnsecuredUsers=true"); + + // If config_disableWeaverOnUnsecuredUsers=true, then the Weaver HAL may be buggy and + // need multiple retries before it works here to unwrap the SP, if the SP was already + // protected by Weaver. Note that the problematic HAL can also deadlock if called with + // the ActivityManagerService lock held, but that should not be a problem here since + // that lock isn't held here, unlike unlockUserKeyIfUnsecured() where it is. + for (int i = 0; i < 12 && sp == null; i++) { + Slog.e(TAG, "Failed to unwrap synthetic password. Waiting 5 seconds to retry."); + SystemClock.sleep(5000); + result = mSpManager.unlockLskfBasedProtector(getGateKeeperService(), protectorId, + LockscreenCredential.createNone(), userId, null); + sp = result.syntheticPassword; + } + if (sp == null) { + throw new IllegalStateException( + "Failed to unwrap synthetic password for unsecured user"); + } + // If the SP is protected by Weaver, then remove the Weaver protection in order to make + // config_disableWeaverOnUnsecuredUsers=true take effect. + if (result.usedWeaver) { + Slog.i(TAG, "Removing Weaver protection from the synthetic password"); + // Create a new protector, which will not use Weaver. + long newProtectorId = mSpManager.createLskfBasedProtector( + getGateKeeperService(), LockscreenCredential.createNone(), sp, userId); + + // Out of paranoia, make sure the new protector really works. + result = mSpManager.unlockLskfBasedProtector(getGateKeeperService(), + newProtectorId, LockscreenCredential.createNone(), userId, null); + sp = result.syntheticPassword; + if (sp == null) { + throw new IllegalStateException("New SP protector does not work"); + } + + // Replace the protector. Wait until PHASE_BOOT_COMPLETED to destroy the old + // protector, since the Weaver slot erasure and freeing cannot be rolled back. + setCurrentLskfBasedProtectorId(newProtectorId, userId); + mProtectorsToDestroyOnBootCompleted.add(new Pair(protectorId, userId)); + } else { + Slog.i(TAG, "Synthetic password is already not protected by Weaver"); + } + } else if (sp == null) { Slogf.wtf(TAG, "Failed to unwrap synthetic password for unsecured user %d", userId); return; } - // While setCeStorageProtection() is idempotent, it does log some error messages when called - // again. Skip it if we know it was already handled by an earlier upgrade to Android 14. - if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null) { + + // Call setCeStorageProtection(), to re-encrypt the CE key with the SP if it's currently + // encrypted by an empty secret. Skip this if it was definitely already done as part of the + // upgrade to Android 14, since while setCeStorageProtection() is idempotent it does log + // some error messages when called again. Do not skip this if + // config_disableWeaverOnUnsecuredUsers=true, since in that case we'd like to recover from + // the case where an earlier upgrade to Android 14 incorrectly skipped this step. + if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null + || isWeaverDisabledOnUnsecuredUsers()) { Slogf.i(TAG, "Encrypting CE key of user %d with synthetic password", userId); setCeStorageProtection(userId, sp); } @@ -1165,6 +1240,17 @@ public class LockSettingsService extends ILockSettings.Stub { initKeystoreSuperKeys(userId, sp, /* allowExisting= */ true); } + private void destroyMigratedProtectors() { + if (!mProtectorsToDestroyOnBootCompleted.isEmpty()) { + synchronized (mSpManager) { + for (Pair<Long, Integer> pair : mProtectorsToDestroyOnBootCompleted) { + mSpManager.destroyLskfBasedProtector(pair.first, pair.second); + } + } + } + mProtectorsToDestroyOnBootCompleted = null; // The list is no longer needed. + } + /** * Returns the lowest password quality that still presents the same UI for entering it. * diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java index 3a429b041b3c..47788f2e7d2f 100644 --- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java @@ -195,6 +195,8 @@ class SyntheticPasswordManager { // ERROR: password / token fails verification // RETRY: password / token verification is throttled at the moment. @Nullable public VerifyCredentialResponse gkResponse; + // For unlockLskfBasedProtector() this is set to true if the protector uses Weaver. + public boolean usedWeaver; } /** @@ -532,6 +534,11 @@ class SyntheticPasswordManager { Settings.Global.DEVICE_PROVISIONED, 0) != 0; } + private boolean isWeaverDisabledOnUnsecuredUsers() { + return mContext.getResources().getBoolean( + com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers); + } + @VisibleForTesting protected android.hardware.weaver.V1_0.IWeaver getWeaverHidlService() throws RemoteException { try { @@ -1011,7 +1018,13 @@ class SyntheticPasswordManager { Slogf.i(TAG, "Creating LSKF-based protector %016x for user %d", protectorId, userId); - final IWeaver weaver = getWeaverService(); + final IWeaver weaver; + if (credential.isNone() && isWeaverDisabledOnUnsecuredUsers()) { + weaver = null; + Slog.w(TAG, "Not using Weaver for unsecured user (disabled by config)"); + } else { + weaver = getWeaverService(); + } if (weaver != null) { // Weaver is available, so make the protector use it to verify the LSKF. Do this even // if the LSKF is empty, as that gives us support for securely deleting the protector. @@ -1404,6 +1417,7 @@ class SyntheticPasswordManager { int weaverSlot = loadWeaverSlot(protectorId, userId); if (weaverSlot != INVALID_WEAVER_SLOT) { // Protector uses Weaver to verify the LSKF + result.usedWeaver = true; final IWeaver weaver = getWeaverService(); if (weaver == null) { Slog.e(TAG, "Protector uses Weaver, but Weaver is unavailable"); diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 8b06dadbaeeb..d1d5d4868c6f 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -1112,19 +1112,12 @@ class MediaRouter2ServiceImpl { continue; } - Log.w( - TAG, - TextUtils.formatSimple( - "Revoking access to manager record id: %d, package: %s, userId:" - + " %d", - manager.mManagerId, manager.mOwnerPackageName, userRecord.mUserId)); - + Slog.w(TAG, "Revoking access for " + manager.getDebugString()); unregisterManagerLocked(manager.mManager, /* died */ false); - try { manager.mManager.invalidateInstance(); } catch (RemoteException ex) { - Slog.w(TAG, "Failed to notify manager= " + manager + " of permission revocation."); + manager.logRemoteException("invalidateInstance", ex); } } } @@ -2428,10 +2421,7 @@ class MediaRouter2ServiceImpl { try { mManager.notifyRequestFailed(requestId, reason); } catch (RemoteException ex) { - Slog.w( - TAG, - "Failed to notify manager of the request failure. Manager probably died.", - ex); + logRemoteException("notifyRequestFailed", ex); } } @@ -2444,7 +2434,7 @@ class MediaRouter2ServiceImpl { try { mManager.notifyRoutesUpdated(routes); } catch (RemoteException ex) { - Slog.w(TAG, "Failed to notify routes. Manager probably died.", ex); + logRemoteException("notifyRoutesUpdated", ex); } } @@ -2457,10 +2447,7 @@ class MediaRouter2ServiceImpl { try { mManager.notifySessionUpdated(sessionInfo); } catch (RemoteException ex) { - Slog.w( - TAG, - "notifySessionUpdatedToManagers: Failed to notify. Manager probably died.", - ex); + logRemoteException("notifySessionUpdated", ex); } } @@ -2473,13 +2460,18 @@ class MediaRouter2ServiceImpl { try { mManager.notifySessionReleased(sessionInfo); } catch (RemoteException ex) { - Slog.w( - TAG, - "notifySessionReleasedToManagers: Failed to notify. Manager probably died.", - ex); + logRemoteException("notifySessionReleased", ex); } } + private void logRemoteException(String operation, RemoteException exception) { + String message = + TextUtils.formatSimple( + "%s failed for %s due to %s", + operation, getDebugString(), exception.toString()); + Slog.w(TAG, message); + } + private void updateScanningState(@ScanningState int scanningState) { if (mScanningState == scanningState) { return; @@ -2492,9 +2484,16 @@ class MediaRouter2ServiceImpl { UserHandler::updateDiscoveryPreferenceOnHandler, mUserRecord.mHandler)); } - @Override - public String toString() { - return "Manager " + mOwnerPackageName + " (pid " + mOwnerPid + ")"; + /** Returns a human readable representation of this manager record for logging purposes. */ + public String getDebugString() { + return TextUtils.formatSimple( + "Manager %s (id=%d,pid=%d,userId=%d,uid=%d,targetPkg=%s)", + mOwnerPackageName, + mManagerId, + mOwnerPid, + mUserRecord.mUserId, + mOwnerUid, + mTargetPackageName); } } diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java index 47f579db604f..e7e519ede768 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java @@ -42,6 +42,8 @@ import android.app.AppOpsManager; import android.app.IProcessObserver; import android.app.KeyguardManager; import android.app.compat.CompatChanges; +import android.app.role.RoleManager; +import android.companion.AssociationRequest; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.content.ComponentName; @@ -94,7 +96,7 @@ import java.util.Objects; /** * Manages MediaProjection sessions. - * + * <p> * The {@link MediaProjectionManagerService} manages the creation and lifetime of MediaProjections, * as well as the capabilities they grant. Any service using MediaProjection tokens as permission * grants <b>must</b> validate the token before use by calling {@link @@ -137,6 +139,7 @@ public final class MediaProjectionManagerService extends SystemService private final PackageManager mPackageManager; private final WindowManagerInternal mWmInternal; private final KeyguardManager mKeyguardManager; + private final RoleManager mRoleManager; private final MediaRouter mMediaRouter; private final MediaRouterCallback mMediaRouterCallback; @@ -173,6 +176,7 @@ public final class MediaProjectionManagerService extends SystemService mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); mKeyguardManager.addKeyguardLockedStateListener( mContext.getMainExecutor(), this::onKeyguardLockedStateChanged); + mRoleManager = mContext.getSystemService(RoleManager.class); Watchdog.getInstance().addMonitor(this); } @@ -182,6 +186,7 @@ public final class MediaProjectionManagerService extends SystemService * - be one of the bugreport allowlisted packages, or * - hold the OP_PROJECT_MEDIA AppOp. */ + @SuppressWarnings("BooleanMethodIsAlwaysInverted") private boolean canCaptureKeyguard() { if (!android.companion.virtualdevice.flags.Flags.mediaProjectionKeyguardRestrictions()) { return true; @@ -193,6 +198,9 @@ public final class MediaProjectionManagerService extends SystemService if (mPackageManager.checkPermission(RECORD_SENSITIVE_CONTENT, mProjectionGrant.packageName) == PackageManager.PERMISSION_GRANTED) { + Slog.v(TAG, + "Allowing keyguard capture for package with RECORD_SENSITIVE_CONTENT " + + "permission"); return true; } if (AppOpsManager.MODE_ALLOWED == mAppOps.noteOpNoThrow(AppOpsManager.OP_PROJECT_MEDIA, @@ -200,6 +208,13 @@ public final class MediaProjectionManagerService extends SystemService "recording lockscreen")) { // Some tools use media projection by granting the OP_PROJECT_MEDIA app // op via a shell command. Those tools can be granted keyguard capture + Slog.v(TAG, + "Allowing keyguard capture for package with OP_PROJECT_MEDIA AppOp "); + return true; + } + if (isProjectionAppHoldingAppStreamingRoleLocked()) { + Slog.v(TAG, + "Allowing keyguard capture for package holding app streaming role."); return true; } return SystemConfig.getInstance().getBugreportWhitelistedPackages() @@ -698,6 +713,20 @@ public final class MediaProjectionManagerService extends SystemService } } + /** + * Application holding the app streaming role + * ({@value AssociationRequest#DEVICE_PROFILE_APP_STREAMING}) are allowed to record the + * lockscreen. + * + * @return true if the is held by the recording application. + */ + @GuardedBy("mLock") + private boolean isProjectionAppHoldingAppStreamingRoleLocked() { + return mRoleManager.getRoleHoldersAsUser(AssociationRequest.DEVICE_PROFILE_APP_STREAMING, + mContext.getUser()) + .contains(mProjectionGrant.packageName); + } + private void dump(final PrintWriter pw) { pw.println("MEDIA PROJECTION MANAGER (dumpsys media_projection)"); synchronized (mLock) { diff --git a/services/core/java/com/android/server/notification/GroupHelper.java b/services/core/java/com/android/server/notification/GroupHelper.java index e8d14cbde516..9b9be4cd8f3f 100644 --- a/services/core/java/com/android/server/notification/GroupHelper.java +++ b/services/core/java/com/android/server/notification/GroupHelper.java @@ -832,8 +832,9 @@ public class GroupHelper { FullyQualifiedGroupKey newGroup) { } /** - * Called when a notification channel is updated, so that this helper can adjust - * the aggregate groups by moving children if their section has changed. + * Called when a notification channel is updated (channel attributes have changed), + * so that this helper can adjust the aggregate groups by moving children + * if their section has changed. * see {@link #onNotificationPostedWithDelay(NotificationRecord, List, Map)} * @param userId the userId of the channel * @param pkgName the channel's package @@ -853,24 +854,48 @@ public class GroupHelper { } } - // The list of notification operations required after the channel update - final ArrayList<NotificationMoveOp> notificationsToMove = new ArrayList<>(); + regroupNotifications(userId, pkgName, notificationsToCheck); + } + } - // Check any already auto-grouped notifications that may need to be re-grouped - // after the channel update - notificationsToMove.addAll( - getAutogroupedNotificationsMoveOps(userId, pkgName, - notificationsToCheck)); + /** + * Called when an individuial notification's channel is updated (moved to a new channel), + * so that this helper can adjust the aggregate groups by moving children + * if their section has changed. + * see {@link #onNotificationPostedWithDelay(NotificationRecord, List, Map)} + * + * @param record the notification which had its channel updated + */ + @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_FORCE_GROUPING) + public void onChannelUpdated(final NotificationRecord record) { + synchronized (mAggregatedNotifications) { + ArrayMap<String, NotificationRecord> notificationsToCheck = new ArrayMap<>(); + notificationsToCheck.put(record.getKey(), record); + regroupNotifications(record.getUserId(), record.getSbn().getPackageName(), + notificationsToCheck); + } + } + + @GuardedBy("mAggregatedNotifications") + private void regroupNotifications(int userId, String pkgName, + ArrayMap<String, NotificationRecord> notificationsToCheck) { + // The list of notification operations required after the channel update + final ArrayList<NotificationMoveOp> notificationsToMove = new ArrayList<>(); - // Check any ungrouped notifications that may need to be auto-grouped - // after the channel update - notificationsToMove.addAll( - getUngroupedNotificationsMoveOps(userId, pkgName, notificationsToCheck)); + // Check any already auto-grouped notifications that may need to be re-grouped + // after the channel update + notificationsToMove.addAll( + getAutogroupedNotificationsMoveOps(userId, pkgName, + notificationsToCheck)); - // Batch move to new section - if (!notificationsToMove.isEmpty()) { - moveNotificationsToNewSection(userId, pkgName, notificationsToMove); - } + // Check any ungrouped notifications that may need to be auto-grouped + // after the channel update + notificationsToMove.addAll( + getUngroupedNotificationsMoveOps(userId, pkgName, notificationsToCheck)); + + // Batch move to new section + if (!notificationsToMove.isEmpty()) { + moveNotificationsToNewSection(userId, pkgName, notificationsToMove); } } diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index 03fc60cad8d6..cd0a2a7a314a 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -106,7 +106,8 @@ abstract public class ManagedServices { protected final String TAG = getClass().getSimpleName().replace('$', '.'); protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000; + protected static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000; + protected static final int ON_BINDING_DIED_REBIND_MSG = 1234; protected static final String ENABLED_SERVICES_SEPARATOR = ":"; private static final String DB_VERSION_1 = "1"; private static final String DB_VERSION_2 = "2"; @@ -856,7 +857,13 @@ abstract public class ManagedServices { String approvedItem = getApprovedValue(pkgOrComponent); if (approvedItem != null) { + final ComponentName component = ComponentName.unflattenFromString(approvedItem); if (enabled) { + if (component != null && !isValidService(component, userId)) { + Log.e(TAG, "Skip allowing " + mConfig.caption + " " + pkgOrComponent + + " (userSet: " + userSet + ") for invalid service"); + return; + } approved.add(approvedItem); } else { approved.remove(approvedItem); @@ -954,7 +961,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) { @@ -1306,11 +1313,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); } } @@ -1329,6 +1337,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); } @@ -1486,23 +1499,25 @@ abstract public class ManagedServices { * Called when user switched to unbind all services from other users. */ @VisibleForTesting - void unbindOtherUserServices(int currentUser) { + void unbindOtherUserServices(int switchedToUser) { TimingsTraceAndSlog t = new TimingsTraceAndSlog(); - t.traceBegin("ManagedServices.unbindOtherUserServices_current" + currentUser); - unbindServicesImpl(currentUser, true /* allExceptUser */); + t.traceBegin("ManagedServices.unbindOtherUserServices_current" + switchedToUser); + unbindServicesImpl(switchedToUser, true /* allExceptUser */); t.traceEnd(); } - void unbindUserServices(int user) { + void unbindUserServices(int removedUser) { TimingsTraceAndSlog t = new TimingsTraceAndSlog(); - t.traceBegin("ManagedServices.unbindUserServices" + user); - unbindServicesImpl(user, false /* allExceptUser */); + t.traceBegin("ManagedServices.unbindUserServices" + removedUser); + unbindServicesImpl(removedUser, false /* allExceptUser */); t.traceEnd(); } void unbindServicesImpl(int user, boolean allExceptUser) { final SparseArray<Set<ComponentName>> componentsToUnbind = new SparseArray<>(); synchronized (mMutex) { + // Remove enqueued rebinds to avoid rebinding services for a switched user + mHandler.removeMessages(ON_BINDING_DIED_REBIND_MSG); final Set<ManagedServiceInfo> removableBoundServices = getRemovableConnectedServices(); for (ManagedServiceInfo info : removableBoundServices) { if ((allExceptUser && (info.userid != user)) @@ -1697,6 +1712,7 @@ abstract public class ManagedServices { mServicesRebinding.add(servicesBindingTag); mHandler.postDelayed(() -> reregisterService(name, userid), + ON_BINDING_DIED_REBIND_MSG, ON_BINDING_DIED_REBIND_DELAY_MS); } else { Slog.v(TAG, getCaption() + " not rebinding in user " + userid diff --git a/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java b/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java index 97bbc2338f47..2dd4f8392fdf 100644 --- a/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java +++ b/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java @@ -15,6 +15,9 @@ */ package com.android.server.notification; +import static android.service.notification.Adjustment.KEY_TYPE; +import static android.service.notification.Flags.notificationForceGrouping; + import android.content.Context; import android.util.Slog; @@ -24,6 +27,7 @@ import android.util.Slog; public class NotificationAdjustmentExtractor implements NotificationSignalExtractor { private static final String TAG = "AdjustmentExtractor"; private static final boolean DBG = false; + private GroupHelper mGroupHelper; public void initialize(Context ctx, NotificationUsageStats usageStats) { @@ -35,8 +39,27 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac if (DBG) Slog.d(TAG, "skipping empty notification"); return null; } + + final boolean hasAdjustedClassification = record.hasAdjustment(KEY_TYPE); record.applyAdjustments(); + if (notificationForceGrouping() + && android.service.notification.Flags.notificationClassification()) { + // Classification adjustments trigger regrouping + if (mGroupHelper != null && hasAdjustedClassification) { + return new RankingReconsideration(record.getKey(), 0) { + @Override + public void work() { + } + + @Override + public void applyChangesLocked(NotificationRecord record) { + mGroupHelper.onChannelUpdated(record); + } + }; + } + } + return null; } @@ -49,4 +72,9 @@ public class NotificationAdjustmentExtractor implements NotificationSignalExtrac public void setZenHelper(ZenModeHelper helper) { } + + @Override + public void setGroupHelper(GroupHelper groupHelper) { + mGroupHelper = groupHelper; + } } diff --git a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java index 06f419a785f9..ea4a6db7a1e8 100644 --- a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java +++ b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java @@ -17,6 +17,7 @@ package com.android.server.notification; import static android.app.Flags.sortSectionByTime; +import static android.app.Notification.CATEGORY_MESSAGE; import static android.app.Notification.FLAG_INSISTENT; import static android.app.Notification.FLAG_ONLY_ALERT_ONCE; import static android.app.NotificationManager.IMPORTANCE_MIN; @@ -42,6 +43,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.content.pm.ShortcutInfo; import android.content.pm.UserInfo; import android.content.res.Resources; import android.database.ContentObserver; @@ -1641,7 +1643,7 @@ public final class NotificationAttentionHelper { } // recent conversation - if (record.isConversation() + if ((record.isConversation() || isConversationMessage(record)) && record.getNotification().getWhen() > mLastAvalancheTriggerTimestamp) { return true; } @@ -1656,6 +1658,21 @@ public final class NotificationAttentionHelper { return false; } + + // Relaxed signals for conversations messages + private boolean isConversationMessage(final NotificationRecord record) { + if (!CATEGORY_MESSAGE.equals(record.getSbn().getNotification().category)) { + return false; + } + if (record.getChannel().isDemoted()) { + return false; + } + final ShortcutInfo shortcut = record.getShortcutInfo(); + if (shortcut == null) { + return false; + } + return true; + } } //====================== Observers ============================= diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 56e0a8929772..6c2d4f72ce57 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -519,6 +519,7 @@ public class NotificationManagerService extends SystemService { private static final long DELAY_FORCE_REGROUP_TIME = 3000; + private static final String ACTION_NOTIFICATION_TIMEOUT = NotificationManagerService.class.getSimpleName() + ".TIMEOUT"; private static final int REQUEST_CODE_TIMEOUT = 1; @@ -2583,7 +2584,7 @@ public class NotificationManagerService extends SystemService { mShowReviewPermissionsNotification, Clock.systemUTC()); mRankingHelper = new RankingHelper(getContext(), mRankingHandler, mPreferencesHelper, - mZenModeHelper, mUsageStats, extractorNames, mPlatformCompat); + mZenModeHelper, mUsageStats, extractorNames, mPlatformCompat, groupHelper); mSnoozeHelper = snoozeHelper; mGroupHelper = groupHelper; mHistoryManager = historyManager; @@ -6871,22 +6872,9 @@ public class NotificationManagerService extends SystemService { } if (android.service.notification.Flags.notificationClassification() && adjustments.containsKey(KEY_TYPE)) { - NotificationChannel newChannel = null; - int type = adjustments.getInt(KEY_TYPE); - if (TYPE_NEWS == type) { - newChannel = mPreferencesHelper.getNotificationChannel( - r.getSbn().getPackageName(), r.getUid(), NEWS_ID, false); - } else if (TYPE_PROMOTION == type) { - newChannel = mPreferencesHelper.getNotificationChannel( - r.getSbn().getPackageName(), r.getUid(), PROMOTIONS_ID, false); - } else if (TYPE_SOCIAL_MEDIA == type) { - newChannel = mPreferencesHelper.getNotificationChannel( - r.getSbn().getPackageName(), r.getUid(), SOCIAL_MEDIA_ID, false); - } else if (TYPE_CONTENT_RECOMMENDATION == type) { - newChannel = mPreferencesHelper.getNotificationChannel( - r.getSbn().getPackageName(), r.getUid(), RECS_ID, false); - } - if (newChannel == null) { + final NotificationChannel newChannel = getClassificationChannelLocked(r, + adjustments); + if (newChannel == null || newChannel.getId().equals(r.getChannel().getId())) { adjustments.remove(KEY_TYPE); } else { // swap app provided type with the real thing @@ -6902,6 +6890,27 @@ public class NotificationManagerService extends SystemService { } } + @GuardedBy("mNotificationLock") + @Nullable + private NotificationChannel getClassificationChannelLocked(NotificationRecord r, + Bundle adjustments) { + int type = adjustments.getInt(KEY_TYPE); + if (TYPE_NEWS == type) { + return mPreferencesHelper.getNotificationChannel( + r.getSbn().getPackageName(), r.getUid(), NEWS_ID, false); + } else if (TYPE_PROMOTION == type) { + return mPreferencesHelper.getNotificationChannel( + r.getSbn().getPackageName(), r.getUid(), PROMOTIONS_ID, false); + } else if (TYPE_SOCIAL_MEDIA == type) { + return mPreferencesHelper.getNotificationChannel( + r.getSbn().getPackageName(), r.getUid(), SOCIAL_MEDIA_ID, false); + } else if (TYPE_CONTENT_RECOMMENDATION == type) { + return mPreferencesHelper.getNotificationChannel( + r.getSbn().getPackageName(), r.getUid(), RECS_ID, false); + } + return null; + } + @SuppressWarnings("GuardedBy") @GuardedBy("mNotificationLock") void addAutogroupKeyLocked(String key, String groupName, boolean requestSort) { @@ -12009,6 +12018,10 @@ public class NotificationManagerService extends SystemService { if (record != null && (record.getSbn().getNotification().flags & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY) > 0 && !record.isCanceledAfterLifetimeExtension()) { + // Mark that the notification is being updated due to cancelation, so it won't + // be updated again if the app cancels multiple times. + record.setCanceledAfterLifetimeExtension(true); + boolean isAppForeground = pkg != null && packageImportance == IMPORTANCE_FOREGROUND; // Save the original Record's post silently value, so we can restore it after we send @@ -12024,9 +12037,6 @@ public class NotificationManagerService extends SystemService { PostNotificationTracker tracker = mPostNotificationTrackerFactory.newTracker(null); tracker.addCleanupRunnable(() -> { synchronized (mNotificationLock) { - // Mark that the notification has been updated due to cancelation, so it won't - // be updated again if the app cancels multiple times. - record.setCanceledAfterLifetimeExtension(true); // Set the post silently status to the record's previous value. record.setPostSilently(savedPostSilentlyState); // Remove FLAG_ONLY_ALERT_ONCE if the notification did not previously have it. diff --git a/services/core/java/com/android/server/notification/NotificationSignalExtractor.java b/services/core/java/com/android/server/notification/NotificationSignalExtractor.java index f0358d1e1d8c..be34beeb1236 100644 --- a/services/core/java/com/android/server/notification/NotificationSignalExtractor.java +++ b/services/core/java/com/android/server/notification/NotificationSignalExtractor.java @@ -55,4 +55,9 @@ public interface NotificationSignalExtractor { void setZenHelper(ZenModeHelper helper); default void setCompatChangeLogger(IPlatformCompat platformCompat){}; + + /** + * @param groupHelper Helper for auto-grouping notifications + */ + default void setGroupHelper(GroupHelper groupHelper){}; } diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 03dd9351efc7..f06d6405b3c2 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -23,7 +23,6 @@ import static android.app.NotificationManager.IMPORTANCE_MIN; import static android.text.TextUtils.formatSimple; import android.annotation.NonNull; -import android.app.NotificationManager; import android.content.Context; import android.service.notification.RankingHelperProto; import android.util.ArrayMap; @@ -61,7 +60,7 @@ public class RankingHelper { }) public RankingHelper(Context context, RankingHandler rankingHandler, RankingConfig config, ZenModeHelper zenHelper, NotificationUsageStats usageStats, String[] extractorNames, - IPlatformCompat platformCompat) { + IPlatformCompat platformCompat, GroupHelper groupHelper) { mContext = context; mRankingHandler = rankingHandler; if (sortSectionByTime()) { @@ -80,6 +79,7 @@ public class RankingHelper { extractor.initialize(mContext, usageStats); extractor.setConfig(config); extractor.setZenHelper(zenHelper); + extractor.setGroupHelper(groupHelper); if (restrictAudioAttributesAlarm() || restrictAudioAttributesMedia() || restrictAudioAttributesCall()) { extractor.setCompatChangeLogger(platformCompat); diff --git a/services/core/java/com/android/server/notification/ZenModeFiltering.java b/services/core/java/com/android/server/notification/ZenModeFiltering.java index ff263d1467c3..bdca555707e3 100644 --- a/services/core/java/com/android/server/notification/ZenModeFiltering.java +++ b/services/core/java/com/android/server/notification/ZenModeFiltering.java @@ -37,7 +37,6 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; -import com.android.internal.messages.nano.SystemMessageProto; import com.android.internal.util.NotificationMessagingUtil; import java.io.PrintWriter; @@ -173,13 +172,6 @@ public class ZenModeFiltering { maybeLogInterceptDecision(record, false, "criticalNotification"); return false; } - // Make an exception to policy for the notification saying that policy has changed - if (NotificationManager.Policy.areAllVisualEffectsSuppressed(policy.suppressedVisualEffects) - && "android".equals(record.getSbn().getPackageName()) - && SystemMessageProto.SystemMessage.NOTE_ZEN_UPGRADE == record.getSbn().getId()) { - maybeLogInterceptDecision(record, false, "systemDndChangedNotification"); - return false; - } switch (zen) { case Global.ZEN_MODE_NO_INTERRUPTIONS: // #notevenalarms diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 626c3ddd49d9..ea211a9ab806 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -54,10 +54,8 @@ import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.app.AutomaticZenRule; import android.app.Flags; -import android.app.Notification; import android.app.NotificationManager; import android.app.NotificationManager.Policy; -import android.app.PendingIntent; import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; @@ -74,7 +72,6 @@ import android.content.pm.ServiceInfo; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.database.ContentObserver; -import android.graphics.drawable.Icon; import android.media.AudioAttributes; import android.media.AudioManager; import android.media.AudioManagerInternal; @@ -90,7 +87,6 @@ import android.os.Message; import android.os.Process; import android.os.SystemClock; import android.os.UserHandle; -import android.provider.Settings; import android.provider.Settings.Global; import android.service.notification.Condition; import android.service.notification.ConditionProviderService; @@ -117,8 +113,6 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags; import com.android.internal.logging.MetricsLogger; -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; -import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.XmlUtils; import com.android.modules.utils.TypedXmlPullParser; @@ -309,7 +303,6 @@ public class ZenModeHelper { mHandler.postMetricsTimer(); cleanUpZenRules(); mIsSystemServicesReady = true; - showZenUpgradeNotification(mZenMode); } /** @@ -485,7 +478,7 @@ public class ZenModeHelper { populateZenRule(pkg, automaticZenRule, rule, origin, /* isNew= */ true); rule = maybeRestoreRemovedRule(newConfig, pkg, rule, automaticZenRule, origin); newConfig.automaticRules.put(rule.id, rule); - maybeReplaceDefaultRule(newConfig, automaticZenRule); + maybeReplaceDefaultRule(newConfig, null, automaticZenRule); if (setConfigLocked(newConfig, origin, reason, rule.component, true, callingUid)) { return rule.id; @@ -535,13 +528,24 @@ public class ZenModeHelper { return ruleToRestore; } - private static void maybeReplaceDefaultRule(ZenModeConfig config, AutomaticZenRule addedRule) { + /** + * Possibly delete built-in rules if a more suitable rule is added or updated. + * + * <p>Today, this is done in one case: delete a disabled "Sleeping" rule if a Bedtime Mode is + * added (or an existing mode is turned into {@link AutomaticZenRule#TYPE_BEDTIME}, when + * upgrading). Because only the {@code config_systemWellbeing} package is allowed to use rules + * of this type, this will not trigger wantonly. + * + * @param oldRule If non-null, {@code rule} is updating {@code oldRule}. Otherwise, + * {@code rule} is being added. + */ + private static void maybeReplaceDefaultRule(ZenModeConfig config, @Nullable ZenRule oldRule, + AutomaticZenRule rule) { if (!Flags.modesApi()) { return; } - if (addedRule.getType() == AutomaticZenRule.TYPE_BEDTIME) { - // Delete a built-in disabled "Sleeping" rule when a BEDTIME rule is added; it may have - // smarter triggers and it will prevent confusion about which one to use. + if (rule.getType() == AutomaticZenRule.TYPE_BEDTIME + && (oldRule == null || oldRule.type != rule.getType())) { // Note: we must not verify canManageAutomaticZenRule here, since most likely they // won't have the same owner (sleeping - system; bedtime - DWB). ZenRule sleepingRule = config.automaticRules.get( @@ -589,6 +593,10 @@ public class ZenModeHelper { // condition) when no changes happen. return true; } + + if (Flags.modesUi()) { + maybeReplaceDefaultRule(newConfig, oldRule, automaticZenRule); + } return setConfigLocked(newConfig, origin, reason, newRule.component, true, callingUid); } @@ -1584,8 +1592,6 @@ public class ZenModeHelper { String reason, @Nullable String caller, int callingUid) { setManualZenMode(zenMode, conditionId, origin, reason, caller, true /*setRingerMode*/, callingUid); - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 0); } private void setManualZenMode(int zenMode, Uri conditionId, @ConfigOrigin int origin, @@ -1783,17 +1789,6 @@ public class ZenModeHelper { SystemZenRules.maybeUpgradeRules(mContext, config); } - // Resolve user id for settings. - userId = userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId; - if (config.version < ZenModeConfig.XML_VERSION_ZEN_UPGRADE) { - Settings.Secure.putIntForUser(mContext.getContentResolver(), - Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1, userId); - } else { - // devices not restoring/upgrading already have updated zen settings - Settings.Secure.putIntForUser(mContext.getContentResolver(), - Settings.Secure.ZEN_SETTINGS_UPDATED, 1, userId); - } - if (Flags.modesApi() && forRestore) { // Note: forBackup doesn't write deletedRules, but just in case. config.deletedRules.clear(); @@ -2062,7 +2057,6 @@ public class ZenModeHelper { Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen); ZenLog.traceSetZenMode(Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, -1), "updated setting"); - showZenUpgradeNotification(zen); } private int getPreviousRingerModeSetting() { @@ -2117,12 +2111,6 @@ public class ZenModeHelper { for (ZenRule automaticRule : mConfig.automaticRules.values()) { if (automaticRule.isActive()) { if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) { - // automatic rule triggered dnd and user hasn't seen update dnd dialog - if (Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) { - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 1); - } zen = automaticRule.zenMode; } } @@ -2702,62 +2690,6 @@ public class ZenModeHelper { } } - private void showZenUpgradeNotification(int zen) { - final boolean isWatch = mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WATCH); - final boolean showNotification = mIsSystemServicesReady - && zen != Global.ZEN_MODE_OFF - && !isWatch - && Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0 - && Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1; - - if (isWatch) { - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); - } - - if (showNotification) { - mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE, - createZenUpgradeNotification()); - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); - } - } - - @VisibleForTesting - protected Notification createZenUpgradeNotification() { - final Bundle extras = new Bundle(); - extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, - mContext.getResources().getString(R.string.global_action_settings)); - int title = R.string.zen_upgrade_notification_title; - int content = R.string.zen_upgrade_notification_content; - int drawable = R.drawable.ic_zen_24dp; - if (NotificationManager.Policy.areAllVisualEffectsSuppressed( - getConsolidatedNotificationPolicy().suppressedVisualEffects)) { - title = R.string.zen_upgrade_notification_visd_title; - content = R.string.zen_upgrade_notification_visd_content; - drawable = R.drawable.ic_dnd_block_notifications; - } - - Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING); - onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB) - .setAutoCancel(true) - .setSmallIcon(R.drawable.ic_settings_24dp) - .setLargeIcon(Icon.createWithResource(mContext, drawable)) - .setContentTitle(mContext.getResources().getString(title)) - .setContentText(mContext.getResources().getString(content)) - .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent, - PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)) - .setAutoCancel(true) - .setLocalOnly(true) - .addExtras(extras) - .setStyle(new Notification.BigTextStyle()) - .build(); - } - private int drawableResNameToResId(String packageName, String resourceName) { if (TextUtils.isEmpty(resourceName)) { return 0; diff --git a/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java b/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java index 03a34f20c311..b0d69e67dac5 100644 --- a/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java +++ b/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java @@ -19,6 +19,8 @@ package com.android.server.ondeviceintelligence; import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.DEVICE_CONFIG_UPDATE_BUNDLE_KEY; import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.MODEL_LOADED_BUNDLE_KEY; import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.MODEL_UNLOADED_BUNDLE_KEY; +import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.MODEL_LOADED_BROADCAST_INTENT; +import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.MODEL_UNLOADED_BROADCAST_INTENT; import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.REGISTER_MODEL_UPDATE_CALLBACK_BUNDLE_KEY; import static com.android.server.ondeviceintelligence.BundleUtil.sanitizeInferenceParams; @@ -154,7 +156,7 @@ public class OnDeviceIntelligenceManagerService extends SystemService { @GuardedBy("mLock") private String[] mTemporaryBroadcastKeys; @GuardedBy("mLock") - private String mBroadcastPackageName; + private String mBroadcastPackageName = SYSTEM_PACKAGE; @GuardedBy("mLock") private String mTemporaryConfigNamespace; @@ -921,10 +923,7 @@ public class OnDeviceIntelligenceManagerService extends SystemService { } } - return new String[]{mContext.getResources().getString( - R.string.config_onDeviceIntelligenceModelLoadedBroadcastKey), - mContext.getResources().getString( - R.string.config_onDeviceIntelligenceModelUnloadedBroadcastKey)}; + return new String[]{ MODEL_LOADED_BROADCAST_INTENT, MODEL_UNLOADED_BROADCAST_INTENT }; } @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index 5d71439e8f46..458b46dab54c 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -592,7 +592,7 @@ public abstract class ApexManager { return apexSessionInfo; } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); - throw new RuntimeException(re); + return null; } } @@ -607,7 +607,7 @@ public abstract class ApexManager { return result; } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); - throw new RuntimeException(re); + return new SparseArray<>(0); } } @@ -619,7 +619,9 @@ public abstract class ApexManager { return apexInfoList; } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); - throw new RuntimeException(re); + throw new PackageManagerException( + PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, + "apexd verification failed : " + re.getMessage()); } catch (Exception e) { throw new PackageManagerException( PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, @@ -633,7 +635,7 @@ public abstract class ApexManager { return waitForApexService().getStagedApexInfos(params); } catch (RemoteException re) { Slog.w(TAG, "Unable to contact apexservice" + re.getMessage()); - throw new RuntimeException(re); + return new ApexInfo[0]; } catch (Exception e) { Slog.w(TAG, "Failed to collect staged apex infos" + e.getMessage()); return new ApexInfo[0]; @@ -646,7 +648,9 @@ public abstract class ApexManager { waitForApexService().markStagedSessionReady(sessionId); } catch (RemoteException re) { Slog.e(TAG, "Unable to contact apexservice", re); - throw new RuntimeException(re); + throw new PackageManagerException( + PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, + "Failed to mark apexd session as ready : " + re.getMessage()); } catch (Exception e) { throw new PackageManagerException( PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index 89ced12e873d..4665a72b0b06 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -2208,10 +2208,10 @@ public class ComputerEngine implements Computer { return true; } boolean permissionGranted = requireFullPermission ? hasPermission( - Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid) + Manifest.permission.INTERACT_ACROSS_USERS_FULL) : (hasPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid) - || hasPermission(Manifest.permission.INTERACT_ACROSS_USERS, callingUid)); + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) + || hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)); if (!permissionGranted) { if (Process.isIsolatedUid(callingUid) && isKnownIsolatedComputeApp(callingUid)) { return checkIsolatedOwnerHasPermission(callingUid, requireFullPermission); diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java index 1569fa0aa8d7..02afdd662b10 100644 --- a/services/core/java/com/android/server/pm/DexOptHelper.java +++ b/services/core/java/com/android/server/pm/DexOptHelper.java @@ -80,6 +80,7 @@ import com.android.server.pinner.PinnerService; import com.android.server.pm.PackageDexOptimizer.DexOptResult; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; +import com.android.server.pm.local.PackageManagerLocalImpl; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageState; import com.android.server.pm.pkg.PackageStateInternal; @@ -819,10 +820,16 @@ public final class DexOptHelper { final PackageSetting ps = installRequest.getScannedPackageSetting(); final String packageName = ps.getPackageName(); + PackageSetting uncommittedPs = null; + if (Flags.improveInstallFreeze()) { + uncommittedPs = ps; + } + PackageManagerLocal packageManagerLocal = LocalManagerRegistry.getManager(PackageManagerLocal.class); try (PackageManagerLocal.FilteredSnapshot snapshot = - packageManagerLocal.withFilteredSnapshot()) { + PackageManagerLocalImpl.withFilteredSnapshot(packageManagerLocal, + uncommittedPs)) { boolean ignoreDexoptProfile = (installRequest.getInstallFlags() & PackageManager.INSTALL_IGNORE_DEXOPT_PROFILE) diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index aca65bfd561c..83292b775ddc 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -148,6 +148,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; import android.util.ExceptionUtils; +import android.util.IntArray; import android.util.Log; import android.util.Pair; import android.util.Slog; @@ -1014,13 +1015,17 @@ final class InstallPackageHelper { final Map<String, Settings.VersionInfo> versionInfos = new ArrayMap<>(requests.size()); try { CriticalEventLog.getInstance().logInstallPackagesStarted(); - if (prepareInstallPackages(requests) && scanInstallPackages(requests, createdAppId, versionInfos)) { List<ReconciledPackage> reconciledPackages = reconcileInstallPackages(requests, versionInfos); - if (reconciledPackages != null - && renameAndUpdatePaths(requests) + if (reconciledPackages == null) { + return; + } + if (Flags.improveInstallFreeze()) { + prepPerformDexoptIfNeeded(reconciledPackages); + } + if (renameAndUpdatePaths(requests) && commitInstallPackages(reconciledPackages)) { success = true; } @@ -1031,6 +1036,75 @@ final class InstallPackageHelper { } } + private int[] getNewUsers(InstallRequest installRequest, int[] allUsers) + throws PackageManagerException { + final int userId = installRequest.getUserId(); + if (userId != UserHandle.USER_ALL && userId != UserHandle.USER_CURRENT + && !mPm.mUserManager.exists(userId)) { + throw new PackageManagerException(PackageManagerException.INTERNAL_ERROR_MISSING_USER, + "User " + userId + " doesn't exist or has been removed"); + } + + final IntArray newUserIds = new IntArray(); + if (userId != UserHandle.USER_ALL) { + newUserIds.add(userId); + } else if (allUsers != null) { + final int[] installedForUsers = installRequest.getOriginUsers(); + for (int currentUserId : allUsers) { + final boolean installedForCurrentUser = ArrayUtils.contains( + installedForUsers, currentUserId); + final boolean restrictedByPolicy = + mPm.isUserRestricted(currentUserId, + UserManager.DISALLOW_INSTALL_APPS) + || mPm.isUserRestricted(currentUserId, + UserManager.DISALLOW_DEBUGGING_FEATURES); + if (installedForCurrentUser || !restrictedByPolicy) { + newUserIds.add(currentUserId); + } + } + } + + if (newUserIds.size() == 0) { + throw new PackageManagerException(PackageManagerException.INTERNAL_ERROR_MISSING_USER, + "User " + userId + " doesn't exist or has been removed"); + } else { + return newUserIds.toArray(); + } + } + + private void prepPerformDexoptIfNeeded(List<ReconciledPackage> reconciledPackages) { + for (ReconciledPackage reconciledPkg : reconciledPackages) { + final InstallRequest request = reconciledPkg.mInstallRequest; + // prepare profiles + final PackageSetting ps = request.getScannedPackageSetting(); + final PackageSetting oldPkgSetting = request.getScanRequestOldPackageSetting(); + final int[] allUsers = mPm.mUserManager.getUserIds(); + if (reconciledPkg.mCollectedSharedLibraryInfos != null + || (oldPkgSetting != null + && !oldPkgSetting.getSharedLibraryDependencies().isEmpty())) { + // Reconcile if the new package or the old package uses shared libraries. + // It is possible that the old package uses shared libraries but the new + // one doesn't. + mSharedLibraries.executeSharedLibrariesUpdate(request.getParsedPackage(), ps, + null, null, reconciledPkg.mCollectedSharedLibraryInfos, allUsers); + } + try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { + final int[] newUsers = getNewUsers(request, allUsers); + // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088) + mAppDataHelper.prepareAppDataPostCommitLIF(ps, 0, newUsers); + if (request.isClearCodeCache()) { + mAppDataHelper.clearAppDataLIF(ps.getPkg(), UserHandle.USER_ALL, + FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL + | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); + } + } catch (PackageManagerException e) { + request.setError(e.error, e.getMessage()); + return; + } + DexOptHelper.performDexoptIfNeeded(request, mDexManager, mContext, null); + } + } + private boolean renameAndUpdatePaths(List<InstallRequest> requests) { try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { for (InstallRequest request : requests) { @@ -2655,20 +2729,22 @@ final class InstallPackageHelper { incrementalStorages.add(storage); } - // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088) - mAppDataHelper.prepareAppDataPostCommitLIF(ps, 0, installRequest.getNewUsers()); - if (installRequest.isClearCodeCache()) { - mAppDataHelper.clearAppDataLIF(ps.getPkg(), UserHandle.USER_ALL, - FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL - | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); - } if (installRequest.isInstallReplace() && pkg != null) { mDexManager.notifyPackageUpdated(packageName, pkg.getBaseApkPath(), pkg.getSplitCodePaths()); } + if (!Flags.improveInstallFreeze()) { + // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088) + mAppDataHelper.prepareAppDataPostCommitLIF(ps, 0, installRequest.getNewUsers()); + if (installRequest.isClearCodeCache()) { + mAppDataHelper.clearAppDataLIF(ps.getPkg(), UserHandle.USER_ALL, + FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL + | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); + } - DexOptHelper.performDexoptIfNeeded(installRequest, mDexManager, mContext, - mPm.mInstallLock.getRawLock()); + DexOptHelper.performDexoptIfNeeded(installRequest, mDexManager, mContext, + mPm.mInstallLock.getRawLock()); + } } PackageManagerServiceUtils.waitForNativeBinariesExtractionForIncremental( incrementalStorages); diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 8657de24d725..5653da07779b 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -716,7 +716,7 @@ public class LauncherAppsService extends SystemService { visiblePackages.add(info.getActivityInfo().packageName); } final List<ApplicationInfo> installedPackages = - mPackageManagerInternal.getInstalledApplicationsCrossUser( + mPackageManagerInternal.getInstalledApplications( /* flags= */ 0, user.getIdentifier(), callingUid); for (ApplicationInfo applicationInfo : installedPackages) { if (!visiblePackages.contains(applicationInfo.packageName)) { diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index b1b1637c890b..34d939b07187 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -126,6 +126,7 @@ import com.android.server.SystemService; import com.android.server.SystemServiceManager; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.utils.RequestThrottle; +import com.android.server.pm.verify.pkg.VerifierController; import libcore.io.IoUtils; @@ -213,6 +214,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements private final StagingManager mStagingManager; private AppOpsManager mAppOps; + private final VerifierController mVerifierController; private final HandlerThread mInstallThread; private final Handler mInstallHandler; @@ -325,6 +327,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements mGentleUpdateHelper = new GentleUpdateHelper( context, mInstallThread.getLooper(), new AppStateHelper(context)); mPackageArchiver = new PackageArchiver(mContext, mPm); + mVerifierController = new VerifierController(mContext, mInstallHandler); LocalServices.getService(SystemServiceManager.class).startService( new Lifecycle(context, this)); @@ -521,7 +524,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements try { session = PackageInstallerSession.readFromXml(in, mInternalCallback, mContext, mPm, mInstallThread.getLooper(), mStagingManager, - mSessionsDir, this, mSilentUpdatePolicy); + mSessionsDir, this, mSilentUpdatePolicy, + mVerifierController); } catch (Exception e) { Slog.e(TAG, "Could not read session", e); continue; @@ -1037,7 +1041,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements mSilentUpdatePolicy, mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid, installSource, params, createdMillis, 0L, stageDir, stageCid, null, null, false, false, false, false, null, SessionInfo.INVALID_ID, - false, false, false, PackageManager.INSTALL_UNKNOWN, "", null); + false, false, false, PackageManager.INSTALL_UNKNOWN, "", null, + mVerifierController); synchronized (mSessions) { mSessions.put(sessionId, session); @@ -1047,6 +1052,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements mCallbacks.notifySessionCreated(session.sessionId, session.userId); mSettingsWriteRequest.schedule(); + if (LOGD) { Slog.d(TAG, "Created session id=" + sessionId + " staged=" + params.isStaged); } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index ff8a69de35bc..897ee4312d22 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -38,6 +38,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_VERIFICATION_FAIL import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; import static android.content.pm.PackageManager.INSTALL_STAGED; import static android.content.pm.PackageManager.INSTALL_SUCCEEDED; +import static android.content.pm.verify.pkg.VerificationSession.VERIFICATION_INCOMPLETE_UNKNOWN; import static android.os.Process.INVALID_UID; import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE; import static android.system.OsConstants.O_CREAT; @@ -87,6 +88,7 @@ import android.content.pm.DataLoaderManager; import android.content.pm.DataLoaderParams; import android.content.pm.DataLoaderParamsParcel; import android.content.pm.FileSystemControlParcel; +import android.content.pm.Flags; import android.content.pm.IDataLoader; import android.content.pm.IDataLoaderStatusListener; import android.content.pm.IOnChecksumsReadyListener; @@ -108,6 +110,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.PackageInfoFlags; import android.content.pm.PackageManagerInternal; import android.content.pm.SigningDetails; +import android.content.pm.SigningInfo; import android.content.pm.dex.DexMetadataHelper; import android.content.pm.parsing.ApkLite; import android.content.pm.parsing.ApkLiteParseUtils; @@ -115,6 +118,7 @@ import android.content.pm.parsing.PackageLite; import android.content.pm.parsing.result.ParseResult; import android.content.pm.parsing.result.ParseTypeImpl; import android.content.pm.verify.domain.DomainSet; +import android.content.pm.verify.pkg.VerificationStatus; import android.content.res.ApkAssets; import android.content.res.AssetManager; import android.content.res.Configuration; @@ -122,6 +126,7 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.icu.util.ULocale; +import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; @@ -133,6 +138,7 @@ import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.ParcelableException; +import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.RevocableFileDescriptor; @@ -190,6 +196,7 @@ import com.android.server.pm.Installer.InstallerException; import com.android.server.pm.dex.DexManager; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageStateInternal; +import com.android.server.pm.verify.pkg.VerifierController; import libcore.io.IoUtils; import libcore.util.EmptyArray; @@ -218,6 +225,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; +import java.util.function.Supplier; public class PackageInstallerSession extends IPackageInstallerSession.Stub { private static final String TAG = "PackageInstallerSession"; @@ -404,6 +412,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * Note all calls must be done outside {@link #mLock} to prevent lock inversion. */ private final StagingManager mStagingManager; + @NonNull private final VerifierController mVerifierController; final int sessionId; final int userId; @@ -1093,6 +1102,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { final boolean isUpdateOwnershipEnforcementEnabled = mPm.isUpdateOwnershipEnforcementAvailable() && existingUpdateOwnerPackageName != null; + + if (Build.IS_USERDEBUG) { + Log.d("updateowner", "PackageInstallerSession computeUserActionRequirement" + + " isUpdateOwnershipEnforcementEnabled= " + isUpdateOwnershipEnforcementEnabled + + ", mPm.isUpdateOwnershipEnforcementAvailable= " + + mPm.isUpdateOwnershipEnforcementAvailable() + + ", existingUpdateOwnerPackageName=" + existingUpdateOwnerPackageName + + ", isUpdateOwner= " + isUpdateOwner + ", getInstallerPackageName()= " + + getInstallerPackageName() + ", isInstallerShell= " + isInstallerShell + + ", mInstallerUid=" + mInstallerUid + ", packageName = " + packageName); + } // For an installation that un-archives an app, if the installer doesn't have the // INSTALL_PACKAGES permission, the user should have already been prompted to confirm the // un-archive request. There's no need for another confirmation during the installation. @@ -1106,6 +1126,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { || isInstallUnarchive; if (noUserActionNecessary) { + if (Build.IS_USERDEBUG) { + Log.d("updateowner", "PackageInstallerSession computeUserActionRequirement" + + " noUserActionNecessary userActionNotTypicallyNeededResponse"); + } return userActionNotTypicallyNeededResponse; } @@ -1115,15 +1139,27 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { && !isInstallerShell // We don't enforce the update ownership for the managed user and profile. && !isFromManagedUserOrProfile) { + if (Build.IS_USERDEBUG) { + Log.d("updateowner", "PackageInstallerSession computeUserActionRequirement" + + "USER_ACTION_REQUIRED_UPDATE_OWNER_REMINDER"); + } return USER_ACTION_REQUIRED_UPDATE_OWNER_REMINDER; } if (isPermissionGranted) { + if (Build.IS_USERDEBUG) { + Log.d("updateowner", "PackageInstallerSession computeUserActionRequirement" + + " permission userActionNotTypicallyNeededResponse"); + } return userActionNotTypicallyNeededResponse; } if (snapshot.isInstallDisabledForPackage(getInstallerPackageName(), mInstallerUid, userId)) { + if (Build.IS_USERDEBUG) { + Log.d("updateowner", "PackageInstallerSession computeUserActionRequirement" + + " disable USER_ACTION_REQUIRED"); + } // show the installer to account for device policy or unknown sources use cases return USER_ACTION_REQUIRED; } @@ -1132,9 +1168,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { && isUpdateWithoutUserActionPermissionGranted && ((isUpdateOwnershipEnforcementEnabled ? isUpdateOwner : isInstallerOfRecord) || isSelfUpdate)) { + if (Build.IS_USERDEBUG) { + Log.d("updateowner", "PackageInstallerSession computeUserActionRequirement" + + " USER_ACTION_PENDING_APK_PARSING"); + } return USER_ACTION_PENDING_APK_PARSING; } + if (Build.IS_USERDEBUG) { + Log.d("updateowner", "PackageInstallerSession computeUserActionRequirement" + + " USER_ACTION_REQUIRED"); + } return USER_ACTION_REQUIRED; } @@ -1156,7 +1200,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { boolean prepared, boolean committed, boolean destroyed, boolean sealed, @Nullable int[] childSessionIds, int parentSessionId, boolean isReady, boolean isFailed, boolean isApplied, int sessionErrorCode, - String sessionErrorMessage, DomainSet preVerifiedDomains) { + String sessionErrorMessage, DomainSet preVerifiedDomains, + @NonNull VerifierController verifierController) { mCallback = callback; mContext = context; mPm = pm; @@ -1165,6 +1210,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mSilentUpdatePolicy = silentUpdatePolicy; mHandler = new Handler(looper, mHandlerCallback); mStagingManager = stagingManager; + mVerifierController = verifierController; this.sessionId = sessionId; this.userId = userId; @@ -1249,6 +1295,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { "Archived installation can only use Streaming System DataLoader."); } } + + if (Flags.verificationService()) { + // Start binding to the verification service, if not bound already. + mVerifierController.bindToVerifierServiceIfNeeded(() -> pm.snapshotComputer(), userId); + if (!TextUtils.isEmpty(params.appPackageName)) { + mVerifierController.notifyPackageNameAvailable(params.appPackageName); + } + } } PackageInstallerHistoricalSession createHistoricalSession() { @@ -2695,6 +2749,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @UserActionRequirement int userActionRequirement = USER_ACTION_NOT_NEEDED; // TODO(b/159331446): Move this to makeSessionActiveForInstall and update javadoc userActionRequirement = session.computeUserActionRequirement(); + if (Build.IS_USERDEBUG) { + Log.d("updateowner", "PackageInstallerSession checkUserActionRequirement" + + " userActionRequirement= " + userActionRequirement + + ", session.packageName= " + session.getPackageName()); + } session.updateUserActionRequirement(userActionRequirement); if (userActionRequirement == USER_ACTION_REQUIRED || userActionRequirement == USER_ACTION_REQUIRED_UPDATE_OWNER_REMINDER) { @@ -2821,7 +2880,35 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // since installation is in progress. activate(); } + if (Flags.verificationService()) { + final Supplier<Computer> snapshotSupplier = mPm::snapshotComputer; + if (mVerifierController.isVerifierInstalled(snapshotSupplier, userId)) { + // TODO: extract shared library declarations + final SigningInfo signingInfo; + synchronized (mLock) { + signingInfo = new SigningInfo(mSigningDetails); + } + // Send the request to the verifier and wait for its response before the rest of + // the installation can proceed. + if (!mVerifierController.startVerificationSession(snapshotSupplier, userId, + sessionId, params.appPackageName, Uri.fromFile(stageDir), signingInfo, + /* declaredLibraries= */null, /* extensionParams= */ null, + new VerifierCallback(), /* retry= */ false)) { + // A verifier is installed but cannot be connected. Installation disallowed. + onSessionVerificationFailure(INSTALL_FAILED_INTERNAL_ERROR, + "A verifier agent is available on device but cannot be connected."); + } + } else { + // Verifier is not installed. Let the installation pass for now. + resumeVerify(); + } + } else { + // New verification feature is not enabled. Proceed to the rest of the verification. + resumeVerify(); + } + } + private void resumeVerify() { if (mVerificationInProgress) { Slog.w(TAG, "Verification is already in progress for session " + sessionId); return; @@ -2856,6 +2943,66 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + /** + * Used for the VerifierController to report status back. + */ + public class VerifierCallback { + /** + * Called by the VerifierController when the connection has failed. + */ + public void onConnectionFailed() { + mHandler.post(() -> { + onSessionVerificationFailure(INSTALL_FAILED_VERIFICATION_FAILURE, + "A verifier agent is available on device but cannot be connected."); + }); + } + /** + * Called by the VerifierController when the verification request has timed out. + */ + public void onTimeout() { + mHandler.post(() -> { + mVerifierController.notifyVerificationTimeout(sessionId); + onSessionVerificationFailure(INSTALL_FAILED_VERIFICATION_FAILURE, + "Verification timed out; missing a response from the verifier within the" + + " time limit"); + }); + } + /** + * Called by the VerifierController when the verification request has received a complete + * response. + */ + public void onVerificationCompleteReceived(@NonNull VerificationStatus statusReceived, + @Nullable PersistableBundle extensionResponse) { + // TODO: handle extension response + mHandler.post(() -> { + if (statusReceived.isVerified()) { + // Continue with the rest of the verification and installation. + resumeVerify(); + } else { + StringBuilder sb = new StringBuilder("Verifier rejected the installation"); + if (!TextUtils.isEmpty(statusReceived.getFailureMessage())) { + sb.append(" with message: ").append(statusReceived.getFailureMessage()); + } + onSessionVerificationFailure(INSTALL_FAILED_VERIFICATION_FAILURE, + sb.toString()); + } + }); + } + /** + * Called by the VerifierController when the verification request has received an incomplete + * response. + */ + public void onVerificationIncompleteReceived(int incompleteReason) { + mHandler.post(() -> { + if (incompleteReason == VERIFICATION_INCOMPLETE_UNKNOWN) { + // TODO: change this to a user confirmation and handle other incomplete reasons + onSessionVerificationFailure(INSTALL_FAILED_INTERNAL_ERROR, + "Verification cannot be completed for unknown reasons."); + } + }); + } + } + private IntentSender getRemoteStatusReceiver() { synchronized (mLock) { return mRemoteStatusReceiver; @@ -5369,6 +5516,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } catch (InstallerException ignored) { } + if (Flags.verificationService() + && !TextUtils.isEmpty(params.appPackageName) + && !isCommitted()) { + // Only notify for the cancellation if the verification request has not + // been sent out, which happens right after commit() is called. + mVerifierController.notifyVerificationCancelled( + params.appPackageName); + } } void dump(IndentingPrintWriter pw) { @@ -5768,7 +5923,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @NonNull PackageManagerService pm, Looper installerThread, @NonNull StagingManager stagingManager, @NonNull File sessionsDir, @NonNull PackageSessionProvider sessionProvider, - @NonNull SilentUpdatePolicy silentUpdatePolicy) + @NonNull SilentUpdatePolicy silentUpdatePolicy, + @NonNull VerifierController verifierController) throws IOException, XmlPullParserException { final int sessionId = in.getAttributeInt(null, ATTR_SESSION_ID); final int userId = in.getAttributeInt(null, ATTR_USER_ID); @@ -5972,6 +6128,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { installerUid, installSource, params, createdMillis, committedMillis, stageDir, stageCid, fileArray, checksumsMap, prepared, committed, destroyed, sealed, childSessionIdsArray, parentSessionId, isReady, isFailed, isApplied, - sessionErrorCode, sessionErrorMessage, preVerifiedDomains); + sessionErrorCode, sessionErrorMessage, preVerifiedDomains, verifierController); } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 611e0d86202a..c8cf938099f4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -340,7 +340,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService static final boolean DEBUG_UPGRADE = false; static final boolean DEBUG_DOMAIN_VERIFICATION = false; static final boolean DEBUG_BACKUP = false; - public static final boolean DEBUG_INSTALL = false; + public static final boolean DEBUG_INSTALL = Build.IS_USERDEBUG; public static final boolean DEBUG_REMOVE = false; static final boolean DEBUG_PACKAGE_INFO = false; static final boolean DEBUG_INTENT_MATCHING = false; diff --git a/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java b/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java index cf5de897cf5d..a28e3c142220 100644 --- a/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java +++ b/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java @@ -244,7 +244,7 @@ class PackageMonitorCallbackHelper { return; } int registerUid = registerUser.getUid(); - if (allowUids != null && registerUid != Process.SYSTEM_UID + if (allowUids != null && !UserHandle.isSameApp(registerUid, Process.SYSTEM_UID) && !ArrayUtils.contains(allowUids, registerUid)) { if (DEBUG) { Slog.w(TAG, "Skip invoke PackageMonitorCallback for " + intent.getAction() diff --git a/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java b/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java index 55afb17614af..c22e382682a7 100644 --- a/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java +++ b/services/core/java/com/android/server/pm/local/PackageManagerLocalImpl.java @@ -31,6 +31,7 @@ import com.android.server.pm.Computer; import com.android.server.pm.PackageManagerLocal; import com.android.server.pm.PackageManagerService; import com.android.server.pm.pkg.PackageState; +import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.SharedUserApi; import com.android.server.pm.snapshot.PackageDataSnapshot; @@ -71,8 +72,26 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { @NonNull @Override public FilteredSnapshotImpl withFilteredSnapshot(int callingUid, @NonNull UserHandle user) { + return withFilteredSnapshot(callingUid, user, /* uncommittedPs= */ null); + } + + /** + * Creates a {@link FilteredSnapshot} with a uncommitted {@link PackageState} that is used for + * dexopt in the art service to get the correct package state before the package is committed. + */ + @NonNull + public static FilteredSnapshotImpl withFilteredSnapshot(PackageManagerLocal pm, + @NonNull PackageState uncommittedPs) { + return ((PackageManagerLocalImpl) pm).withFilteredSnapshot(Binder.getCallingUid(), + Binder.getCallingUserHandle(), uncommittedPs); + } + + @NonNull + private FilteredSnapshotImpl withFilteredSnapshot(int callingUid, @NonNull UserHandle user, + @Nullable PackageState uncommittedPs) { return new FilteredSnapshotImpl(callingUid, user, - mService.snapshotComputer(false /*allowLiveComputer*/), null); + mService.snapshotComputer(/* allowLiveComputer= */ false), + /* parentSnapshot= */ null, uncommittedPs); } @Override @@ -145,7 +164,8 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { @Override public FilteredSnapshot filtered(int callingUid, @NonNull UserHandle user) { - return new FilteredSnapshotImpl(callingUid, user, mSnapshot, this); + return new FilteredSnapshotImpl(callingUid, user, mSnapshot, this, + /* uncommittedPs= */ null); } @SuppressWarnings("RedundantSuppression") @@ -209,13 +229,18 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { @Nullable private final UnfilteredSnapshotImpl mParentSnapshot; + @Nullable + private final PackageState mUncommitPackageState; + private FilteredSnapshotImpl(int callingUid, @NonNull UserHandle user, @NonNull PackageDataSnapshot snapshot, - @Nullable UnfilteredSnapshotImpl parentSnapshot) { + @Nullable UnfilteredSnapshotImpl parentSnapshot, + @Nullable PackageState uncommittedPs) { super(snapshot); mCallingUid = callingUid; mUserId = user.getIdentifier(); mParentSnapshot = parentSnapshot; + mUncommitPackageState = uncommittedPs; } @Override @@ -237,6 +262,10 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { @Override public PackageState getPackageState(@NonNull String packageName) { checkClosed(); + if (mUncommitPackageState != null + && packageName.equals(mUncommitPackageState.getPackageName())) { + return mUncommitPackageState; + } return mSnapshot.getPackageStateFiltered(packageName, mCallingUid, mUserId); } @@ -250,6 +279,11 @@ public class PackageManagerLocalImpl implements PackageManagerLocal { var filteredPackageStates = new ArrayMap<String, PackageState>(); for (int index = 0, size = packageStates.size(); index < size; index++) { var packageState = packageStates.valueAt(index); + if (mUncommitPackageState != null + && packageState.getPackageName().equals( + mUncommitPackageState.getPackageName())) { + packageState = (PackageStateInternal) mUncommitPackageState; + } if (!mSnapshot.shouldFilterApplication(packageState, mCallingUid, mUserId)) { filteredPackageStates.put(packageStates.keyAt(index), packageState); } diff --git a/services/core/java/com/android/server/pm/verify/pkg/VerificationStatusTracker.java b/services/core/java/com/android/server/pm/verify/pkg/VerificationStatusTracker.java new file mode 100644 index 000000000000..db747f9940a0 --- /dev/null +++ b/services/core/java/com/android/server/pm/verify/pkg/VerificationStatusTracker.java @@ -0,0 +1,101 @@ +/* + * 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.verify.pkg; + +import android.annotation.CurrentTimeMillisLong; +import android.annotation.NonNull; + +import com.android.internal.annotations.VisibleForTesting; + +/** + * This class keeps record of the current timeout status of a verification request. + */ +public final class VerificationStatusTracker { + private final @CurrentTimeMillisLong long mStartTime; + private @CurrentTimeMillisLong long mTimeoutTime; + private final @CurrentTimeMillisLong long mMaxTimeoutTime; + @NonNull + private final VerifierController.Injector mInjector; + // Record the package name associated with the verification result + @NonNull + private final String mPackageName; + + /** + * By default, the timeout time is the default timeout duration plus the current time (when + * the timer starts for a verification request). Both the default timeout time and the max + * timeout time cannot be changed after the timer has started, but the actual timeout time + * can be extended via {@link #extendTimeRemaining} to the maximum allowed. + */ + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED) + public VerificationStatusTracker(@NonNull String packageName, + long defaultTimeoutMillis, long maxExtendedTimeoutMillis, + @NonNull VerifierController.Injector injector) { + mPackageName = packageName; + mStartTime = injector.getCurrentTimeMillis(); + mTimeoutTime = mStartTime + defaultTimeoutMillis; + mMaxTimeoutTime = mStartTime + maxExtendedTimeoutMillis; + mInjector = injector; + } + + /** + * Used by the controller to inform the verifier agent about the timestamp when the verification + * request will timeout. + */ + public @CurrentTimeMillisLong long getTimeoutTime() { + return mTimeoutTime; + } + + /** + * Used by the controller to decide when to check for timeout again. + * @return 0 if the timeout time has been reached, otherwise the remaining time in milliseconds + * before the timeout is reached. + */ + public @CurrentTimeMillisLong long getRemainingTime() { + final long remainingTime = mTimeoutTime - mInjector.getCurrentTimeMillis(); + if (remainingTime < 0) { + return 0; + } + return remainingTime; + } + + /** + * Used by the controller to extend the timeout duration of the verification request, upon + * receiving the callback from the verifier agent. + * @return the amount of time in millis that the timeout has been extended, subject to the max + * amount allowed. + */ + public long extendTimeRemaining(@CurrentTimeMillisLong long additionalMs) { + if (mTimeoutTime + additionalMs > mMaxTimeoutTime) { + additionalMs = mMaxTimeoutTime - mTimeoutTime; + } + mTimeoutTime += additionalMs; + return additionalMs; + } + + /** + * Used by the controller to get the timeout status of the request. + * @return False if the request still has some time left before timeout, otherwise return True. + */ + public boolean isTimeout() { + return mInjector.getCurrentTimeMillis() >= mTimeoutTime; + } + + @NonNull + public String getPackageName() { + return mPackageName; + } +} diff --git a/services/core/java/com/android/server/pm/verify/pkg/VerifierController.java b/services/core/java/com/android/server/pm/verify/pkg/VerifierController.java new file mode 100644 index 000000000000..7eac940933c2 --- /dev/null +++ b/services/core/java/com/android/server/pm/verify/pkg/VerifierController.java @@ -0,0 +1,645 @@ +/* + * 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.verify.pkg; + +import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; +import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; +import static android.os.Process.SYSTEM_UID; +import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE; + +import android.Manifest; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.SharedLibraryInfo; +import android.content.pm.SigningInfo; +import android.content.pm.verify.pkg.IVerificationSessionCallback; +import android.content.pm.verify.pkg.IVerificationSessionInterface; +import android.content.pm.verify.pkg.IVerifierService; +import android.content.pm.verify.pkg.VerificationSession; +import android.content.pm.verify.pkg.VerificationStatus; +import android.net.Uri; +import android.os.Build; +import android.os.Handler; +import android.os.PersistableBundle; +import android.os.Process; +import android.os.RemoteException; +import android.os.UserHandle; +import android.provider.DeviceConfig; +import android.util.Pair; +import android.util.Slog; +import android.util.SparseArray; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.infra.AndroidFuture; +import com.android.internal.infra.ServiceConnector; +import com.android.server.pm.Computer; +import com.android.server.pm.PackageInstallerSession; +import com.android.server.pm.pkg.PackageStateInternal; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +/** + * This class manages the bind to the verifier agent installed on the device that implements + * {@link android.content.pm.verify.pkg.VerifierService} and handles all its interactions. + */ +public class VerifierController { + private static final String TAG = "VerifierController"; + private static final boolean DEBUG = false; + + /** + * Configurable maximum amount of time in milliseconds to wait for a verifier to respond to + * a verification request. + * Flag type: {@code long} + * Namespace: NAMESPACE_PACKAGE_MANAGER_SERVICE + */ + private static final String PROPERTY_VERIFICATION_REQUEST_TIMEOUT_MILLIS = + "verification_request_timeout_millis"; + // Default duration to wait for a verifier to respond to a verification request. + private static final long DEFAULT_VERIFICATION_REQUEST_TIMEOUT_MILLIS = + TimeUnit.MINUTES.toMillis(1); + /** + * Configurable maximum amount of time in milliseconds that the verifier can request to extend + * the verification request timeout duration to. This is the maximum amount of time the system + * can wait for a request before it times out. + * Flag type: {@code long} + * Namespace: NAMESPACE_PACKAGE_MANAGER_SERVICE + */ + private static final String PROPERTY_MAX_VERIFICATION_REQUEST_EXTENDED_TIMEOUT_MILLIS = + "max_verification_request_extended_timeout_millis"; + // Max duration allowed to wait for a verifier to respond to a verification request. + private static final long DEFAULT_MAX_VERIFICATION_REQUEST_EXTENDED_TIMEOUT_MILLIS = + TimeUnit.MINUTES.toMillis(10); + // The maximum amount of time to wait from the moment when the session requires a verification, + // till when the request is delivered to the verifier, pending the connection to be established. + private static final long CONNECTION_TIMEOUT_SECONDS = 10; + // The maximum amount of time to wait before the system unbinds from the verifier. + private static final long UNBIND_TIMEOUT_MILLIS = TimeUnit.HOURS.toMillis(6); + + private final Context mContext; + private final Handler mHandler; + @Nullable + private ServiceConnector<IVerifierService> mRemoteService; + @Nullable + private ComponentName mRemoteServiceComponentName; + @NonNull + private Injector mInjector; + + // Repository of active verification sessions and their status, mapping from id to status. + @NonNull + @GuardedBy("mVerificationStatus") + private final SparseArray<VerificationStatusTracker> mVerificationStatus = new SparseArray<>(); + + public VerifierController(@NonNull Context context, @NonNull Handler handler) { + this(context, handler, new Injector()); + } + + @VisibleForTesting + public VerifierController(@NonNull Context context, @NonNull Handler handler, + @NonNull Injector injector) { + mContext = context; + mHandler = handler; + mInjector = injector; + } + + /** + * Used by the installation session to check if a verifier is installed. + */ + public boolean isVerifierInstalled(Supplier<Computer> snapshotSupplier, int userId) { + if (isVerifierConnected()) { + // Verifier is connected or is being connected, so it must be installed. + return true; + } + // Verifier has been disconnected, or it hasn't been connected. Check if it's installed. + return mInjector.isVerifierInstalled(snapshotSupplier.get(), userId); + } + + /** + * Called to start querying and binding to a qualified verifier agent. + * + * @return False if a qualified verifier agent doesn't exist on device, so that the system can + * handle this situation immediately after the call. + * <p> + * Notice that since this is an async call, even if this method returns true, it doesn't + * necessarily mean that the binding connection was successful. However, the system will only + * try to bind once per installation session, so that it doesn't waste resource by repeatedly + * trying to bind if the verifier agent isn't available during a short amount of time. + * <p> + * If the verifier agent exists but cannot be started for some reason, all the notify* methods + * in this class will fail asynchronously and quietly. The system will learn about the failure + * after receiving the failure from + * {@link PackageInstallerSession.VerifierCallback#onConnectionFailed}. + */ + public boolean bindToVerifierServiceIfNeeded(Supplier<Computer> snapshotSupplier, int userId) { + if (DEBUG) { + Slog.i(TAG, "Requesting to bind to the verifier service."); + } + if (mRemoteService != null) { + // Already connected + if (DEBUG) { + Slog.i(TAG, "Verifier service is already connected."); + } + return true; + } + Pair<ServiceConnector<IVerifierService>, ComponentName> result = + mInjector.getRemoteService(snapshotSupplier.get(), mContext, userId, mHandler); + if (result == null || result.first == null) { + if (DEBUG) { + Slog.i(TAG, "Unable to find a qualified verifier."); + } + return false; + } + mRemoteService = result.first; + mRemoteServiceComponentName = result.second; + if (DEBUG) { + Slog.i(TAG, "Connecting to a qualified verifier: " + mRemoteServiceComponentName); + } + mRemoteService.setServiceLifecycleCallbacks( + new ServiceConnector.ServiceLifecycleCallbacks<>() { + @Override + public void onConnected(@NonNull IVerifierService service) { + Slog.i(TAG, "Verifier " + mRemoteServiceComponentName + " is connected"); + } + + @Override + public void onDisconnected(@NonNull IVerifierService service) { + Slog.w(TAG, + "Verifier " + mRemoteServiceComponentName + " is disconnected"); + destroy(); + } + + @Override + public void onBinderDied() { + Slog.w(TAG, "Verifier " + mRemoteServiceComponentName + " has died"); + destroy(); + } + + private void destroy() { + if (isVerifierConnected()) { + mRemoteService.unbind(); + mRemoteService = null; + mRemoteServiceComponentName = null; + } + } + }); + AndroidFuture<IVerifierService> unusedFuture = mRemoteService.connect(); + return true; + } + + private boolean isVerifierConnected() { + return mRemoteService != null && mRemoteServiceComponentName != null; + } + + /** + * Called to notify the bound verifier agent that a package name is available and will soon be + * requested for verification. + */ + public void notifyPackageNameAvailable(@NonNull String packageName) { + if (!isVerifierConnected()) { + if (DEBUG) { + Slog.i(TAG, "Verifier is not connected. Not notifying package name available"); + } + return; + } + // Best effort. We don't check for the result. + mRemoteService.run(service -> { + if (DEBUG) { + Slog.i(TAG, "Notifying package name available for " + packageName); + } + service.onPackageNameAvailable(packageName); + }); + } + + /** + * Called to notify the bound verifier agent that a package previously notified via + * {@link android.content.pm.verify.pkg.VerifierService#onPackageNameAvailable(String)} + * will no longer be requested for verification, possibly because the installation is canceled. + */ + public void notifyVerificationCancelled(@NonNull String packageName) { + if (!isVerifierConnected()) { + if (DEBUG) { + Slog.i(TAG, "Verifier is not connected. Not notifying verification cancelled"); + } + return; + } + // Best effort. We don't check for the result. + mRemoteService.run(service -> { + if (DEBUG) { + Slog.i(TAG, "Notifying verification cancelled for " + packageName); + } + service.onVerificationCancelled(packageName); + }); + } + + /** + * Called to notify the bound verifier agent that a package that's pending installation needs + * to be verified right now. + * <p>The verification request must be sent to the verifier as soon as the verifier is + * connected. If the connection cannot be made within {@link #CONNECTION_TIMEOUT_SECONDS}</p> + * of when the request is sent out, we consider the verification to be failed and notify the + * installation session.</p> + * <p>If a response is not returned from the verifier agent within a timeout duration from the + * time the request is sent to the verifier, the verification will be considered a failure.</p> + * + * @param retry whether this request is for retrying a previously incomplete verification. + */ + public boolean startVerificationSession(Supplier<Computer> snapshotSupplier, int userId, + int installationSessionId, String packageName, + Uri stagedPackageUri, SigningInfo signingInfo, + List<SharedLibraryInfo> declaredLibraries, + PersistableBundle extensionParams, PackageInstallerSession.VerifierCallback callback, + boolean retry) { + // Try connecting to the verifier if not already connected + if (!bindToVerifierServiceIfNeeded(snapshotSupplier, userId)) { + return false; + } + if (!isVerifierConnected()) { + if (DEBUG) { + Slog.i(TAG, "Verifier is not connected. Not notifying verification required"); + } + // Normally this should not happen because we just tried to bind. But if the verifier + // just crashed or just became unavailable, we should notify the installation session so + // it can finish with a verification failure. + return false; + } + // For now, the verification id is the same as the installation session id. + final int verificationId = installationSessionId; + final VerificationSession session = new VerificationSession( + /* id= */ verificationId, + /* installSessionId= */ installationSessionId, + packageName, stagedPackageUri, signingInfo, declaredLibraries, extensionParams, + new VerificationSessionInterface(), + new VerificationSessionCallback(callback)); + AndroidFuture<Void> unusedFuture = mRemoteService.post(service -> { + if (!retry) { + if (DEBUG) { + Slog.i(TAG, "Notifying verification required for session " + verificationId); + } + service.onVerificationRequired(session); + } else { + if (DEBUG) { + Slog.i(TAG, "Notifying verification retry for session " + verificationId); + } + service.onVerificationRetry(session); + } + }).orTimeout(CONNECTION_TIMEOUT_SECONDS, TimeUnit.SECONDS).whenComplete((res, err) -> { + if (err != null) { + Slog.e(TAG, "Error notifying verification request for session " + verificationId, + err); + // Notify the installation session so it can finish with verification failure. + callback.onConnectionFailed(); + } + }); + // Keep track of the session status with the ID. Start counting down the session timeout. + final long defaultTimeoutMillis = mInjector.getVerificationRequestTimeoutMillis(); + final long maxExtendedTimeoutMillis = mInjector.getMaxVerificationExtendedTimeoutMillis(); + final VerificationStatusTracker tracker = new VerificationStatusTracker( + packageName, defaultTimeoutMillis, maxExtendedTimeoutMillis, mInjector); + synchronized (mVerificationStatus) { + mVerificationStatus.put(verificationId, tracker); + } + startTimeoutCountdown(verificationId, tracker, callback, defaultTimeoutMillis); + return true; + } + + private void startTimeoutCountdown(int verificationId, VerificationStatusTracker tracker, + PackageInstallerSession.VerifierCallback callback, long delayMillis) { + mHandler.postDelayed(() -> { + if (DEBUG) { + Slog.i(TAG, "Checking request timeout for " + verificationId); + } + if (!tracker.isTimeout()) { + if (DEBUG) { + Slog.i(TAG, "Timeout is not met for " + verificationId + "; check later."); + } + // If the current session is not timed out yet, check again later. + startTimeoutCountdown(verificationId, tracker, callback, + /* delayMillis= */ tracker.getRemainingTime()); + } else { + if (DEBUG) { + Slog.i(TAG, "Request " + verificationId + " has timed out."); + } + // The request has timed out. Notify the installation session. + callback.onTimeout(); + // Remove status tracking and stop the timeout countdown + removeStatusTracker(verificationId); + } + }, /* token= */ tracker, delayMillis); + } + + /** + * Called to notify the bound verifier agent that a verification request has timed out. + */ + public void notifyVerificationTimeout(int verificationId) { + if (!isVerifierConnected()) { + if (DEBUG) { + Slog.i(TAG, + "Verifier is not connected. Not notifying timeout for " + verificationId); + } + return; + } + AndroidFuture<Void> unusedFuture = mRemoteService.post(service -> { + if (DEBUG) { + Slog.i(TAG, "Notifying timeout for " + verificationId); + } + service.onVerificationTimeout(verificationId); + }).whenComplete((res, err) -> { + if (err != null) { + Slog.e(TAG, "Error notifying VerificationTimeout for session " + + verificationId, (Throwable) err); + } + }); + } + + /** + * Remove a status tracker after it's no longer needed. + */ + private void removeStatusTracker(int verificationId) { + if (DEBUG) { + Slog.i(TAG, "Removing status tracking for verification " + verificationId); + } + synchronized (mVerificationStatus) { + VerificationStatusTracker tracker = mVerificationStatus.removeReturnOld(verificationId); + // Cancel the timeout counters if there's any + if (tracker != null) { + mInjector.stopTimeoutCountdown(mHandler, tracker); + } + } + } + + @RequiresPermission(Manifest.permission.VERIFICATION_AGENT) + private void checkCallerPermission() { + // TODO: think of a better way to test it on non-eng builds + if (Build.IS_ENG) { + return; + } + if (mContext.checkCallingOrSelfPermission(Manifest.permission.VERIFICATION_AGENT) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("You need the" + + " com.android.permission.VERIFICATION_AGENT permission" + + " to use VerificationSession APIs."); + } + } + + // This class handles requests from the remote verifier + private class VerificationSessionInterface extends IVerificationSessionInterface.Stub { + @Override + public long getTimeoutTime(int verificationId) { + checkCallerPermission(); + synchronized (mVerificationStatus) { + final VerificationStatusTracker tracker = mVerificationStatus.get(verificationId); + if (tracker == null) { + throw new IllegalStateException("Verification session " + verificationId + + " doesn't exist or has finished"); + } + return tracker.getTimeoutTime(); + } + } + + @Override + public long extendTimeRemaining(int verificationId, long additionalMs) { + checkCallerPermission(); + synchronized (mVerificationStatus) { + final VerificationStatusTracker tracker = mVerificationStatus.get(verificationId); + if (tracker == null) { + throw new IllegalStateException("Verification session " + verificationId + + " doesn't exist or has finished"); + } + return tracker.extendTimeRemaining(additionalMs); + } + } + } + + private class VerificationSessionCallback extends IVerificationSessionCallback.Stub { + private final PackageInstallerSession.VerifierCallback mCallback; + + VerificationSessionCallback(PackageInstallerSession.VerifierCallback callback) { + mCallback = callback; + } + + @Override + public void reportVerificationIncomplete(int id, int reason) throws RemoteException { + checkCallerPermission(); + final VerificationStatusTracker tracker; + synchronized (mVerificationStatus) { + tracker = mVerificationStatus.get(id); + if (tracker == null) { + throw new IllegalStateException("Verification session " + id + + " doesn't exist or has finished"); + } + mCallback.onVerificationIncompleteReceived(reason); + } + // Remove status tracking and stop the timeout countdown + removeStatusTracker(id); + } + + @Override + public void reportVerificationComplete(int id, VerificationStatus verificationStatus) + throws RemoteException { + reportVerificationCompleteWithExtensionResponse(id, verificationStatus, + /* extensionResponse= */ null); + } + + @Override + public void reportVerificationCompleteWithExtensionResponse(int id, + VerificationStatus verificationStatus, PersistableBundle extensionResponse) + throws RemoteException { + checkCallerPermission(); + final VerificationStatusTracker tracker; + synchronized (mVerificationStatus) { + tracker = mVerificationStatus.get(id); + if (tracker == null) { + throw new IllegalStateException("Verification session " + id + + " doesn't exist or has finished"); + } + } + mCallback.onVerificationCompleteReceived(verificationStatus, extensionResponse); + // Remove status tracking and stop the timeout countdown + removeStatusTracker(id); + } + } + + @VisibleForTesting + public static class Injector { + /** + * Mock this method to inject the remote service to enable unit testing. + */ + @Nullable + public Pair<ServiceConnector<IVerifierService>, ComponentName> getRemoteService( + @NonNull Computer snapshot, @NonNull Context context, int userId, + @NonNull Handler handler) { + final ComponentName verifierComponent = resolveVerifierComponentName(snapshot, userId); + if (verifierComponent == null) { + return null; + } + final Intent intent = new Intent(PackageManager.ACTION_VERIFY_PACKAGE); + intent.setComponent(verifierComponent); + return new Pair<>(new ServiceConnector.Impl<IVerifierService>( + context, intent, Context.BIND_AUTO_CREATE, userId, + IVerifierService.Stub::asInterface) { + @Override + protected Handler getJobHandler() { + return handler; + } + + @Override + protected long getRequestTimeoutMs() { + return getVerificationRequestTimeoutMillis(); + } + + @Override + protected long getAutoDisconnectTimeoutMs() { + return UNBIND_TIMEOUT_MILLIS; + } + }, verifierComponent); + } + + /** + * Check if a verifier is installed on this device. + */ + public boolean isVerifierInstalled(Computer snapshot, int userId) { + return resolveVerifierComponentName(snapshot, userId) != null; + } + + /** + * Find the ComponentName of the verifier service agent, using the intent action. + * If multiple qualified verifier services are present, the one with the highest intent + * filter priority will be chosen. + */ + private static @Nullable ComponentName resolveVerifierComponentName(Computer snapshot, + int userId) { + final Intent intent = new Intent(PackageManager.ACTION_VERIFY_PACKAGE); + final int resolveFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE; + final List<ResolveInfo> matchedServices = snapshot.queryIntentServicesInternal( + intent, null, + resolveFlags, userId, SYSTEM_UID, Process.INVALID_PID, + /*includeInstantApps*/ false, /*resolveForStart*/ false); + if (matchedServices.isEmpty()) { + Slog.w(TAG, + "Failed to find any matching verifier service agent"); + return null; + } + ResolveInfo best = null; + int numMatchedServices = matchedServices.size(); + for (int i = 0; i < numMatchedServices; i++) { + ResolveInfo cur = matchedServices.get(i); + if (!isQualifiedVerifier(snapshot, cur, userId)) { + continue; + } + if (best == null || cur.priority > best.priority) { + best = cur; + } + } + if (best != null) { + Slog.i(TAG, "Found verifier service agent: " + + best.getComponentInfo().getComponentName().toShortString()); + return best.getComponentInfo().getComponentName(); + } + Slog.w(TAG, "Didn't find any qualified verifier service agent."); + return null; + } + + @SuppressLint("AndroidFrameworkRequiresPermission") + private static boolean isQualifiedVerifier(Computer snapshot, ResolveInfo ri, int userId) { + // Basic null checks + if (ri.getComponentInfo() == null) { + return false; + } + final ApplicationInfo applicationInfo = ri.getComponentInfo().applicationInfo; + if (applicationInfo == null) { + return false; + } + // Check for installed state + PackageStateInternal ps = snapshot.getPackageStateInternal( + ri.getComponentInfo().packageName, SYSTEM_UID); + if (ps == null || !ps.getUserStateOrDefault(userId).isInstalled()) { + return false; + } + // Check for enabled state + if (!snapshot.isComponentEffectivelyEnabled(ri.getComponentInfo(), + UserHandle.of(userId))) { + return false; + } + // Allow binding to a non-privileged app on an ENG build + // TODO: think of a better way to test it on non-eng builds + if (Build.IS_ENG) { + return true; + } + // Check if the app is platform-signed or is privileged + if (!applicationInfo.isSignedWithPlatformKey() && !applicationInfo.isPrivilegedApp()) { + return false; + } + // Check for permission + return (snapshot.checkUidPermission( + android.Manifest.permission.VERIFICATION_AGENT, applicationInfo.uid) + != PackageManager.PERMISSION_GRANTED); + } + + /** + * This is added so we can mock timeouts in the unit tests. + */ + public long getCurrentTimeMillis() { + return System.currentTimeMillis(); + } + + /** + * This is added so that we don't need to mock Handler.removeCallbacksAndEqualMessages + * which is final. + */ + public void stopTimeoutCountdown(Handler handler, Object token) { + handler.removeCallbacksAndEqualMessages(token); + } + + /** + * This is added so that we can mock the verification request timeout duration without + * calling into DeviceConfig. + */ + public long getVerificationRequestTimeoutMillis() { + return getVerificationRequestTimeoutMillisFromDeviceConfig(); + } + + /** + * This is added so that we can mock the maximum request timeout duration without + * calling into DeviceConfig. + */ + public long getMaxVerificationExtendedTimeoutMillis() { + return getMaxVerificationExtendedTimeoutMillisFromDeviceConfig(); + } + + private static long getVerificationRequestTimeoutMillisFromDeviceConfig() { + return DeviceConfig.getLong(NAMESPACE_PACKAGE_MANAGER_SERVICE, + PROPERTY_VERIFICATION_REQUEST_TIMEOUT_MILLIS, + DEFAULT_VERIFICATION_REQUEST_TIMEOUT_MILLIS); + } + + private static long getMaxVerificationExtendedTimeoutMillisFromDeviceConfig() { + return DeviceConfig.getLong(NAMESPACE_PACKAGE_MANAGER_SERVICE, + PROPERTY_MAX_VERIFICATION_REQUEST_EXTENDED_TIMEOUT_MILLIS, + DEFAULT_MAX_VERIFICATION_REQUEST_EXTENDED_TIMEOUT_MILLIS); + } + } +} diff --git a/services/core/java/com/android/server/policy/ModifierShortcutManager.java b/services/core/java/com/android/server/policy/ModifierShortcutManager.java index 027e69cbc09b..66ec53e6500e 100644 --- a/services/core/java/com/android/server/policy/ModifierShortcutManager.java +++ b/services/core/java/com/android/server/policy/ModifierShortcutManager.java @@ -667,9 +667,11 @@ public class ModifierShortcutManager { public KeyboardShortcutGroup getApplicationLaunchKeyboardShortcuts(int deviceId) { List<KeyboardShortcutInfo> shortcuts = new ArrayList(); if (modifierShortcutManagerRefactor()) { + Context context = modifierShortcutManagerMultiuser() + ? mContext.createContextAsUser(mCurrentUser, 0) : mContext; for (Bookmark b : mBookmarks.values()) { KeyboardShortcutInfo info = shortcutInfoFromIntent( - b.getShortcutChar(), b.getIntent(mContext), b.isShift()); + b.getShortcutChar(), b.getIntent(context), b.isShift()); if (info != null) { shortcuts.add(info); } diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index 4fae798f0cef..eb62b5631c43 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -709,7 +709,7 @@ public class Notifier { SparseBooleanArray newDisplayInteractivities = new SparseBooleanArray(); for (int i = 0; i < displaysByGroupId.size(); i++) { final int groupId = displaysByGroupId.keyAt(i); - for (int displayId : displaysByGroupId.get(i)) { + for (int displayId : displaysByGroupId.get(groupId)) { // If we already know display interactivity, use that if (mDisplayInteractivities.indexOfKey(displayId) > 0) { newDisplayInteractivities.put( diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 21ab7812e604..65f22416a535 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -743,6 +743,7 @@ public final class PowerManagerService extends SystemService int reason, int uid, int opUid, String opPackageName, String details) { mWakefulnessChanging = true; mDirty |= DIRTY_WAKEFULNESS; + mInjector.invalidateIsInteractiveCaches(); if (wakefulness == WAKEFULNESS_AWAKE) { // Kick user activity to prevent newly awake group from timing out instantly. // The dream may end without user activity if the dream app crashes / is updated, @@ -2035,7 +2036,7 @@ public final class PowerManagerService extends SystemService } @SuppressWarnings("deprecation") - private boolean isWakeLockLevelSupportedInternal(int level) { + private boolean isWakeLockLevelSupportedInternal(int level, int displayId) { synchronized (mLock) { switch (level) { case PowerManager.PARTIAL_WAKE_LOCK: @@ -2047,7 +2048,8 @@ public final class PowerManagerService extends SystemService return true; case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: - return mSystemReady && mDisplayManagerInternal.isProximitySensorAvailable(); + return mSystemReady + && mDisplayManagerInternal.isProximitySensorAvailable(displayId); case PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK: return mSystemReady && mFeatureFlags.isEarlyScreenTimeoutDetectorEnabled() && mScreenTimeoutOverridePolicy != null; @@ -2264,7 +2266,6 @@ public final class PowerManagerService extends SystemService int opUid, String opPackageName, String details) { mPowerGroups.get(groupId).setWakefulnessLocked(wakefulness, eventTime, uid, reason, opUid, opPackageName, details); - mInjector.invalidateIsInteractiveCaches(); } @SuppressWarnings("deprecation") @@ -2329,8 +2330,6 @@ public final class PowerManagerService extends SystemService Trace.traceBegin(Trace.TRACE_TAG_POWER, traceMethodName); try { // Phase 2: Handle wakefulness change and bookkeeping. - // Under lock, invalidate before set ensures caches won't return stale values. - mInjector.invalidateIsInteractiveCaches(); mWakefulnessRaw = newWakefulness; mWakefulnessChanging = true; mDirty |= DIRTY_WAKEFULNESS; @@ -2428,6 +2427,7 @@ public final class PowerManagerService extends SystemService void onPowerGroupEventLocked(int event, PowerGroup powerGroup) { mWakefulnessChanging = true; mDirty |= DIRTY_WAKEFULNESS; + mInjector.invalidateIsInteractiveCaches(); final int groupId = powerGroup.getGroupId(); if (event == DisplayGroupPowerChangeListener.DISPLAY_GROUP_REMOVED) { mPowerGroups.delete(groupId); @@ -3975,6 +3975,9 @@ public final class PowerManagerService extends SystemService private boolean isInteractiveInternal(int displayId, int uid) { synchronized (mLock) { + if (!mSystemReady) { + return isGloballyInteractiveInternal(); + } DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); if (displayInfo == null) { Slog.w(TAG, "Did not find DisplayInfo for displayId " + displayId); @@ -5975,7 +5978,17 @@ public final class PowerManagerService extends SystemService public boolean isWakeLockLevelSupported(int level) { final long ident = Binder.clearCallingIdentity(); try { - return isWakeLockLevelSupportedInternal(level); + return isWakeLockLevelSupportedInternal(level, Display.DEFAULT_DISPLAY); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call + public boolean isWakeLockLevelSupportedWithDisplayId(int level, int displayId) { + final long ident = Binder.clearCallingIdentity(); + try { + return isWakeLockLevelSupportedInternal(level, displayId); } finally { Binder.restoreCallingIdentity(ident); } diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java index dc482422f9d9..2c0ce252df18 100644 --- a/services/core/java/com/android/server/power/hint/HintManagerService.java +++ b/services/core/java/com/android/server/power/hint/HintManagerService.java @@ -21,6 +21,7 @@ import static android.os.Flags.adpfUseFmqChannel; import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; import static com.android.server.power.hint.Flags.adpfSessionTag; import static com.android.server.power.hint.Flags.powerhintThreadCleanup; +import static com.android.server.power.hint.Flags.resetOnForkEnabled; import android.annotation.NonNull; import android.annotation.Nullable; @@ -1057,6 +1058,25 @@ public final class HintManagerService extends SystemService { Slogf.w(TAG, errMsg); throw new SecurityException(errMsg); } + if (resetOnForkEnabled()){ + try { + for (int tid : tids) { + int policy = Process.getThreadScheduler(tid); + // If the thread is not using the default scheduling policy (SCHED_OTHER), + // we don't change it. + if (policy != Process.SCHED_OTHER) { + continue; + } + // set the SCHED_RESET_ON_FORK flag. + int prio = Process.getThreadPriority(tid); + Process.setThreadScheduler(tid, Process.SCHED_OTHER | Process.SCHED_RESET_ON_FORK, 0); + Process.setThreadPriority(tid, prio); + } + } catch (Exception e) { + Slog.e(TAG, "Failed to set SCHED_RESET_ON_FORK for tids " + + Arrays.toString(tids), e); + } + } if (adpfSessionTag() && tag == SessionTag.APP) { // If the category of the app is a game, @@ -1447,6 +1467,25 @@ public final class HintManagerService extends SystemService { Slogf.w(TAG, errMsg); throw new SecurityException(errMsg); } + if (resetOnForkEnabled()){ + try { + for (int tid : tids) { + int policy = Process.getThreadScheduler(tid); + // If the thread is not using the default scheduling policy (SCHED_OTHER), + // we don't change it. + if (policy != Process.SCHED_OTHER) { + continue; + } + // set the SCHED_RESET_ON_FORK flag. + int prio = Process.getThreadPriority(tid); + Process.setThreadScheduler(tid, Process.SCHED_OTHER | Process.SCHED_RESET_ON_FORK, 0); + Process.setThreadPriority(tid, prio); + } + } catch (Exception e) { + Slog.e(TAG, "Failed to set SCHED_RESET_ON_FORK for tids " + + Arrays.toString(tids), e); + } + } if (powerhintThreadCleanup()) { synchronized (mNonIsolatedTidsLock) { for (int i = nonIsolated.size() - 1; i >= 0; i--) { diff --git a/services/core/java/com/android/server/power/hint/flags.aconfig b/services/core/java/com/android/server/power/hint/flags.aconfig index 55afa05f66fe..e56b68c93480 100644 --- a/services/core/java/com/android/server/power/hint/flags.aconfig +++ b/services/core/java/com/android/server/power/hint/flags.aconfig @@ -14,3 +14,10 @@ flag { description: "Feature flag for adding session tag to hint session atom" bug: "345011125" } + +flag { + name: "reset_on_fork_enabled" + namespace: "game" + description: "Set reset_on_fork flag." + bug: "370988407" +} diff --git a/services/core/java/com/android/server/uri/UriPermission.java b/services/core/java/com/android/server/uri/UriPermission.java index 0d1f36794f49..0ff23eab472a 100644 --- a/services/core/java/com/android/server/uri/UriPermission.java +++ b/services/core/java/com/android/server/uri/UriPermission.java @@ -25,6 +25,8 @@ import android.util.ArraySet; import android.util.Log; import android.util.Slog; +import com.android.internal.annotations.GuardedBy; + import com.google.android.collect.Sets; import java.io.PrintWriter; @@ -82,7 +84,9 @@ final class UriPermission { static final long INVALID_TIME = Long.MIN_VALUE; + @GuardedBy("this") private ArraySet<UriPermissionOwner> mReadOwners; + @GuardedBy("this") private ArraySet<UriPermissionOwner> mWriteOwners; private String stringName; @@ -204,14 +208,16 @@ final class UriPermission { persistedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; } globalModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; - if (mReadOwners != null && includingOwners) { - ownedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; - for (UriPermissionOwner r : mReadOwners) { - if (r != null) { - r.removeReadPermission(this); + synchronized (this) { + if (mReadOwners != null && includingOwners) { + ownedModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; + for (UriPermissionOwner r : mReadOwners) { + if (r != null) { + r.removeReadPermission(this); + } } + mReadOwners = null; } - mReadOwners = null; } } if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) { @@ -220,14 +226,16 @@ final class UriPermission { persistedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; } globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; - if (mWriteOwners != null && includingOwners) { - ownedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; - for (UriPermissionOwner r : mWriteOwners) { - if (r != null) { - r.removeWritePermission(this); + synchronized (this) { + if (mWriteOwners != null && includingOwners) { + ownedModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + for (UriPermissionOwner r : mWriteOwners) { + if (r != null) { + r.removeWritePermission(this); + } } + mWriteOwners = null; } - mWriteOwners = null; } } @@ -256,7 +264,7 @@ final class UriPermission { } } - private void addReadOwner(UriPermissionOwner owner) { + private synchronized void addReadOwner(UriPermissionOwner owner) { if (mReadOwners == null) { mReadOwners = Sets.newArraySet(); ownedModeFlags |= Intent.FLAG_GRANT_READ_URI_PERMISSION; @@ -270,7 +278,7 @@ final class UriPermission { /** * Remove given read owner, updating {@Link #modeFlags} as needed. */ - void removeReadOwner(UriPermissionOwner owner) { + synchronized void removeReadOwner(UriPermissionOwner owner) { if (mReadOwners == null || !mReadOwners.remove(owner)) { Slog.wtf(TAG, "Unknown read owner " + owner + " in " + this); return; @@ -282,7 +290,7 @@ final class UriPermission { } } - private void addWriteOwner(UriPermissionOwner owner) { + private synchronized void addWriteOwner(UriPermissionOwner owner) { if (mWriteOwners == null) { mWriteOwners = Sets.newArraySet(); ownedModeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION; @@ -296,7 +304,7 @@ final class UriPermission { /** * Remove given write owner, updating {@Link #modeFlags} as needed. */ - void removeWriteOwner(UriPermissionOwner owner) { + synchronized void removeWriteOwner(UriPermissionOwner owner) { if (mWriteOwners == null || !mWriteOwners.remove(owner)) { Slog.wtf(TAG, "Unknown write owner " + owner + " in " + this); return; @@ -339,20 +347,22 @@ final class UriPermission { } pw.println(); - if (mReadOwners != null) { - pw.print(prefix); - pw.println("readOwners:"); - for (UriPermissionOwner owner : mReadOwners) { + synchronized (this) { + if (mReadOwners != null) { pw.print(prefix); - pw.println(" * " + owner); + pw.println("readOwners:"); + for (UriPermissionOwner owner : mReadOwners) { + pw.print(prefix); + pw.println(" * " + owner); + } } - } - if (mWriteOwners != null) { - pw.print(prefix); - pw.println("writeOwners:"); - for (UriPermissionOwner owner : mWriteOwners) { + if (mWriteOwners != null) { pw.print(prefix); - pw.println(" * " + owner); + pw.println("writeOwners:"); + for (UriPermissionOwner owner : mWriteOwners) { + pw.print(prefix); + pw.println(" * " + owner); + } } } } diff --git a/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java b/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java index 111e075a7374..245d9020d5a2 100644 --- a/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java +++ b/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java @@ -26,10 +26,10 @@ import java.util.List; /** * Adapter that clips frequency values to the supported range specified by - * {@link VibratorInfo.FrequencyProfile}, then clips amplitude values to the max supported one at + * {@link VibratorInfo.FrequencyProfileLegacy}, then clips amplitude values to the max supported one at * each frequency. * - * <p>The {@link VibratorInfo.FrequencyProfile} is only applicable to PWLE compositions. This + * <p>The {@link VibratorInfo.FrequencyProfileLegacy} is only applicable to PWLE compositions. This * adapter is only applied to {@link RampSegment} and all other segments will remain unchanged. */ final class ClippingAmplitudeAndFrequencyAdapter implements VibrationSegmentsAdapter { @@ -59,7 +59,7 @@ final class ClippingAmplitudeAndFrequencyAdapter implements VibrationSegmentsAda } private float clampFrequency(VibratorInfo info, float frequencyHz) { - Range<Float> frequencyRangeHz = info.getFrequencyProfile().getFrequencyRangeHz(); + Range<Float> frequencyRangeHz = info.getFrequencyProfileLegacy().getFrequencyRangeHz(); if (frequencyHz == 0 || frequencyRangeHz == null) { return Float.isNaN(info.getResonantFrequencyHz()) ? 0 : info.getResonantFrequencyHz(); } @@ -67,7 +67,7 @@ final class ClippingAmplitudeAndFrequencyAdapter implements VibrationSegmentsAda } private float clampAmplitude(VibratorInfo info, float frequencyHz, float amplitude) { - VibratorInfo.FrequencyProfile mapping = info.getFrequencyProfile(); + VibratorInfo.FrequencyProfileLegacy mapping = info.getFrequencyProfileLegacy(); if (mapping.isEmpty()) { // No frequency mapping was specified so leave amplitude unchanged. // The frequency will be clamped to the device's resonant frequency. diff --git a/services/core/java/com/android/server/vibrator/ExternalVibrationSession.java b/services/core/java/com/android/server/vibrator/ExternalVibrationSession.java index b5a7fcb72982..e650c52b68b4 100644 --- a/services/core/java/com/android/server/vibrator/ExternalVibrationSession.java +++ b/services/core/java/com/android/server/vibrator/ExternalVibrationSession.java @@ -56,24 +56,26 @@ final class ExternalVibrationSession extends Vibration } @Override + public long getCreateUptimeMillis() { + return stats.getCreateUptimeMillis(); + } + + @Override public CallerInfo getCallerInfo() { return callerInfo; } @Override - public VibrationSession.DebugInfo getDebugInfo() { - return new Vibration.DebugInfoImpl(getStatus(), stats, /* playedEffect= */ null, - /* originalEffect= */ null, mScale.scaleLevel, mScale.adaptiveHapticsScale, - callerInfo); + public IBinder getCallerToken() { + return mExternalVibration.getToken(); } @Override - public VibrationStats.StatsInfo getStatsInfo(long completionUptimeMillis) { - return new VibrationStats.StatsInfo( - mExternalVibration.getUid(), - FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__EXTERNAL, - mExternalVibration.getVibrationAttributes().getUsage(), getStatus(), stats, - completionUptimeMillis); + public VibrationSession.DebugInfo getDebugInfo() { + return new Vibration.DebugInfoImpl(getStatus(), callerInfo, + FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__EXTERNAL, stats, + /* playedEffect= */ null, /* originalEffect= */ null, mScale.scaleLevel, + mScale.adaptiveHapticsScale); } @Override @@ -86,6 +88,12 @@ final class ExternalVibrationSession extends Vibration } @Override + public boolean wasEndRequested() { + // End request is immediate, so just check if vibration has already ended. + return hasEnded(); + } + + @Override public boolean linkToDeath(Runnable callback) { synchronized (mLock) { mBinderDeathCallback = callback; @@ -104,10 +112,12 @@ final class ExternalVibrationSession extends Vibration @Override public void binderDied() { + Runnable callback; synchronized (mLock) { - if (mBinderDeathCallback != null) { - mBinderDeathCallback.run(); - } + callback = mBinderDeathCallback; + } + if (callback != null) { + callback.run(); } } @@ -131,6 +141,16 @@ final class ExternalVibrationSession extends Vibration end(new EndInfo(status, endedBy)); } + @Override + public void notifyVibratorCallback(int vibratorId, long vibrationId) { + // ignored, external control does not expect callbacks from the vibrator + } + + @Override + public void notifySyncedVibratorsCallback(long vibrationId) { + // ignored, external control does not expect callbacks from the vibrator manager + } + boolean isHoldingSameVibration(ExternalVibration vib) { return mExternalVibration.equals(vib); } diff --git a/services/core/java/com/android/server/vibrator/HalVibration.java b/services/core/java/com/android/server/vibrator/HalVibration.java index ce9c47ba6ba4..fbcc856d0974 100644 --- a/services/core/java/com/android/server/vibrator/HalVibration.java +++ b/services/core/java/com/android/server/vibrator/HalVibration.java @@ -19,15 +19,16 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.CombinedVibration; -import android.os.IBinder; import android.os.VibrationAttributes; import android.os.VibrationEffect; +import android.os.vibrator.PrebakedSegment; +import android.os.vibrator.VibrationEffectSegment; import android.util.SparseArray; -import com.android.internal.util.FrameworkStatsLog; - +import java.util.List; import java.util.Objects; import java.util.concurrent.CountDownLatch; +import java.util.function.IntFunction; /** * Represents a vibration defined by a {@link CombinedVibration} that will be performed by @@ -36,7 +37,6 @@ import java.util.concurrent.CountDownLatch; final class HalVibration extends Vibration { public final SparseArray<VibrationEffect> mFallbacks = new SparseArray<>(); - public final IBinder callerToken; /** A {@link CountDownLatch} to enable waiting for completion. */ private final CountDownLatch mCompletionLatch = new CountDownLatch(1); @@ -56,10 +56,9 @@ final class HalVibration extends Vibration { private int mScaleLevel; private float mAdaptiveScale; - HalVibration(@NonNull IBinder callerToken, @NonNull CombinedVibration effect, - @NonNull VibrationSession.CallerInfo callerInfo) { + HalVibration(@NonNull VibrationSession.CallerInfo callerInfo, + @NonNull CombinedVibration effect) { super(callerInfo); - this.callerToken = callerToken; mOriginalEffect = effect; mEffectToPlay = effect; mScaleLevel = VibrationScaler.SCALE_NONE; @@ -87,11 +86,11 @@ final class HalVibration extends Vibration { } /** - * Add a fallback {@link VibrationEffect} to be played when given effect id is not supported, - * which might be necessary for replacement in realtime. + * Add a fallback {@link VibrationEffect} to be played for each predefined effect id, which + * might be necessary for replacement in realtime. */ - public void addFallback(int effectId, VibrationEffect effect) { - mFallbacks.put(effectId, effect); + public void fillFallbacks(IntFunction<VibrationEffect> fallbackProvider) { + fillFallbacksForEffect(mEffectToPlay, fallbackProvider); } /** @@ -131,11 +130,6 @@ final class HalVibration extends Vibration { // No need to update fallback effects, they are already configured per device. } - @Override - public boolean isRepeating() { - return mOriginalEffect.getDuration() == Long.MAX_VALUE; - } - /** Return the effect that should be played by this vibration. */ public CombinedVibration getEffectToPlay() { return mEffectToPlay; @@ -146,20 +140,9 @@ final class HalVibration extends Vibration { // Clear the original effect if it's the same as the effect that was played, for simplicity CombinedVibration originalEffect = Objects.equals(mOriginalEffect, mEffectToPlay) ? null : mOriginalEffect; - return new Vibration.DebugInfoImpl(getStatus(), stats, mEffectToPlay, originalEffect, - mScaleLevel, mAdaptiveScale, callerInfo); - } - - @Override - public VibrationStats.StatsInfo getStatsInfo(long completionUptimeMillis) { - int vibrationType = mEffectToPlay.hasVendorEffects() - ? FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__VENDOR - : isRepeating() - ? FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__REPEATED - : FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__SINGLE; - return new VibrationStats.StatsInfo( - callerInfo.uid, vibrationType, callerInfo.attrs.getUsage(), getStatus(), - stats, completionUptimeMillis); + return new Vibration.DebugInfoImpl(getStatus(), callerInfo, + VibrationStats.StatsInfo.findVibrationType(mEffectToPlay), stats, mEffectToPlay, + originalEffect, mScaleLevel, mAdaptiveScale); } /** @@ -174,6 +157,42 @@ final class HalVibration extends Vibration { return callerInfo.uid == vib.callerInfo.uid && callerInfo.attrs.isFlagSet( VibrationAttributes.FLAG_PIPELINED_EFFECT) && vib.callerInfo.attrs.isFlagSet(VibrationAttributes.FLAG_PIPELINED_EFFECT) - && !isRepeating(); + && (mOriginalEffect.getDuration() != Long.MAX_VALUE); + } + + private void fillFallbacksForEffect(CombinedVibration effect, + IntFunction<VibrationEffect> fallbackProvider) { + if (effect instanceof CombinedVibration.Mono) { + fillFallbacksForEffect(((CombinedVibration.Mono) effect).getEffect(), fallbackProvider); + } else if (effect instanceof CombinedVibration.Stereo) { + SparseArray<VibrationEffect> effects = + ((CombinedVibration.Stereo) effect).getEffects(); + for (int i = 0; i < effects.size(); i++) { + fillFallbacksForEffect(effects.valueAt(i), fallbackProvider); + } + } else if (effect instanceof CombinedVibration.Sequential) { + List<CombinedVibration> effects = + ((CombinedVibration.Sequential) effect).getEffects(); + for (int i = 0; i < effects.size(); i++) { + fillFallbacksForEffect(effects.get(i), fallbackProvider); + } + } + } + + private void fillFallbacksForEffect(VibrationEffect effect, + IntFunction<VibrationEffect> fallbackProvider) { + if (!(effect instanceof VibrationEffect.Composed composed)) { + return; + } + int segmentCount = composed.getSegments().size(); + for (int i = 0; i < segmentCount; i++) { + VibrationEffectSegment segment = composed.getSegments().get(i); + if ((segment instanceof PrebakedSegment prebaked) && prebaked.shouldFallback()) { + VibrationEffect fallback = fallbackProvider.apply(prebaked.getEffectId()); + if (fallback != null) { + mFallbacks.put(prebaked.getEffectId(), fallback); + } + } + } } } diff --git a/services/core/java/com/android/server/vibrator/SingleVibrationSession.java b/services/core/java/com/android/server/vibrator/SingleVibrationSession.java new file mode 100644 index 000000000000..f80407d03e5c --- /dev/null +++ b/services/core/java/com/android/server/vibrator/SingleVibrationSession.java @@ -0,0 +1,173 @@ +/* + * 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.vibrator; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.CombinedVibration; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Slog; + +import com.android.internal.annotations.GuardedBy; + +import java.util.NoSuchElementException; + +/** + * A vibration session holding a single {@link CombinedVibration} request, performed by a + * {@link VibrationStepConductor}. + */ +final class SingleVibrationSession implements VibrationSession, IBinder.DeathRecipient { + private static final String TAG = "SingleVibrationSession"; + + private final Object mLock = new Object(); + private final IBinder mCallerToken; + private final HalVibration mVibration; + + @GuardedBy("mLock") + private VibrationStepConductor mConductor; + + @GuardedBy("mLock") + @Nullable + private Runnable mBinderDeathCallback; + + SingleVibrationSession(@NonNull IBinder callerToken, @NonNull CallerInfo callerInfo, + @NonNull CombinedVibration vibration) { + mCallerToken = callerToken; + mVibration = new HalVibration(callerInfo, vibration); + } + + public void setVibrationConductor(@Nullable VibrationStepConductor conductor) { + synchronized (mLock) { + mConductor = conductor; + } + } + + public HalVibration getVibration() { + return mVibration; + } + + @Override + public long getCreateUptimeMillis() { + return mVibration.stats.getCreateUptimeMillis(); + } + + @Override + public boolean isRepeating() { + return mVibration.getEffectToPlay().getDuration() == Long.MAX_VALUE; + } + + @Override + public CallerInfo getCallerInfo() { + return mVibration.callerInfo; + } + + @Override + public IBinder getCallerToken() { + return mCallerToken; + } + + @Override + public DebugInfo getDebugInfo() { + return mVibration.getDebugInfo(); + } + + @Override + public boolean wasEndRequested() { + if (mVibration.hasEnded()) { + return true; + } + synchronized (mLock) { + return mConductor != null && mConductor.wasNotifiedToCancel(); + } + } + + @Override + public void binderDied() { + Slog.d(TAG, "Binder died, cancelling vibration..."); + requestEnd(Status.CANCELLED_BINDER_DIED, /* endedBy= */ null, /* immediate= */ false); + Runnable callback; + synchronized (mLock) { + callback = mBinderDeathCallback; + } + if (callback != null) { + callback.run(); + } + } + + @Override + public boolean linkToDeath(@Nullable Runnable callback) { + synchronized (mLock) { + mBinderDeathCallback = callback; + } + try { + mCallerToken.linkToDeath(this, 0); + } catch (RemoteException e) { + Slog.e(TAG, "Error linking vibration to token death", e); + return false; + } + return true; + } + + @Override + public void unlinkToDeath() { + try { + mCallerToken.unlinkToDeath(this, 0); + } catch (NoSuchElementException e) { + Slog.wtf(TAG, "Failed to unlink vibration to token death", e); + } + synchronized (mLock) { + mBinderDeathCallback = null; + } + } + + @Override + public void requestEnd(@NonNull Status status, @Nullable CallerInfo endedBy, + boolean immediate) { + synchronized (mLock) { + if (mConductor != null) { + mConductor.notifyCancelled(new Vibration.EndInfo(status, endedBy), immediate); + } else { + mVibration.end(new Vibration.EndInfo(status, endedBy)); + } + } + } + + @Override + public void notifyVibratorCallback(int vibratorId, long vibrationId) { + if (vibrationId != mVibration.id) { + return; + } + synchronized (mLock) { + if (mConductor != null) { + mConductor.notifyVibratorComplete(vibratorId); + } + } + } + + @Override + public void notifySyncedVibratorsCallback(long vibrationId) { + if (vibrationId != mVibration.id) { + return; + } + synchronized (mLock) { + if (mConductor != null) { + mConductor.notifySyncedVibrationComplete(); + } + } + } +} diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java index 21fd4ce0acd0..bb2a17c698ee 100644 --- a/services/core/java/com/android/server/vibrator/Vibration.java +++ b/services/core/java/com/android/server/vibrator/Vibration.java @@ -88,15 +88,9 @@ abstract class Vibration { stats.reportEnded(endInfo.endedBy); } - /** Return true if vibration is a repeating vibration. */ - abstract boolean isRepeating(); - /** Return {@link VibrationSession.DebugInfo} with read-only debug data about this vibration. */ abstract VibrationSession.DebugInfo getDebugInfo(); - /** Return {@link VibrationStats.StatsInfo} with read-only metrics about this vibration. */ - abstract VibrationStats.StatsInfo getStatsInfo(long completionUptimeMillis); - /** Immutable info passed as a signal to end a vibration. */ static final class EndInfo { /** The vibration status to be set when it ends with this info. */ @@ -146,35 +140,41 @@ abstract class Vibration { * potentially expensive or resource-linked objects, such as {@link IBinder}. */ static final class DebugInfoImpl implements VibrationSession.DebugInfo { - final VibrationSession.Status mStatus; - final long mCreateTime; - final VibrationSession.CallerInfo mCallerInfo; + private final VibrationSession.Status mStatus; + private final VibrationStats.StatsInfo mStatsInfo; + private final VibrationSession.CallerInfo mCallerInfo; @Nullable - final CombinedVibration mPlayedEffect; - - private final long mStartTime; - private final long mEndTime; - private final long mDurationMs; + private final CombinedVibration mPlayedEffect; @Nullable private final CombinedVibration mOriginalEffect; private final int mScaleLevel; private final float mAdaptiveScale; - DebugInfoImpl(VibrationSession.Status status, VibrationStats stats, - @Nullable CombinedVibration playedEffect, - @Nullable CombinedVibration originalEffect, int scaleLevel, - float adaptiveScale, @NonNull VibrationSession.CallerInfo callerInfo) { + private final long mCreateUptime; + private final long mCreateTime; + private final long mStartTime; + private final long mEndTime; + private final long mDurationMs; + + DebugInfoImpl(VibrationSession.Status status, + @NonNull VibrationSession.CallerInfo callerInfo, int vibrationType, + VibrationStats stats, @Nullable CombinedVibration playedEffect, + @Nullable CombinedVibration originalEffect, int scaleLevel, float adaptiveScale) { Objects.requireNonNull(callerInfo); - mCreateTime = stats.getCreateTimeDebug(); - mStartTime = stats.getStartTimeDebug(); - mEndTime = stats.getEndTimeDebug(); - mDurationMs = stats.getDurationDebug(); + mCallerInfo = callerInfo; + mStatsInfo = stats.toStatsInfo(callerInfo.uid, vibrationType, + callerInfo.attrs.getUsage(), status); mPlayedEffect = playedEffect; mOriginalEffect = originalEffect; mScaleLevel = scaleLevel; mAdaptiveScale = adaptiveScale; - mCallerInfo = callerInfo; mStatus = status; + + mCreateUptime = stats.getCreateUptimeMillis(); + mCreateTime = stats.getCreateTimeDebug(); + mStartTime = stats.getStartTimeDebug(); + mEndTime = stats.getEndTimeDebug(); + mDurationMs = stats.getDurationDebug(); } @Override @@ -184,7 +184,7 @@ abstract class Vibration { @Override public long getCreateUptimeMillis() { - return mCreateTime; + return mCreateUptime; } @Override @@ -216,6 +216,7 @@ abstract class Vibration { @Override public void logMetrics(VibratorFrameworkStatsLogger statsLogger) { statsLogger.logVibrationAdaptiveHapticScale(mCallerInfo.uid, mAdaptiveScale); + statsLogger.writeVibrationReportedAsync(mStatsInfo); } @Override diff --git a/services/core/java/com/android/server/vibrator/VibrationSession.java b/services/core/java/com/android/server/vibrator/VibrationSession.java index 70477a26b759..4de8f78f7836 100644 --- a/services/core/java/com/android/server/vibrator/VibrationSession.java +++ b/services/core/java/com/android/server/vibrator/VibrationSession.java @@ -39,9 +39,18 @@ import java.util.Objects; */ interface VibrationSession { + /** Returns the session creation time from {@link android.os.SystemClock#uptimeMillis()}. */ + long getCreateUptimeMillis(); + + /** Return true if vibration session plays a repeating vibration. */ + boolean isRepeating(); + /** Returns data about the client app that triggered this vibration session. */ CallerInfo getCallerInfo(); + /** Returns the binder token from the client app attached to this vibration session. */ + IBinder getCallerToken(); + /** Returns debug data for logging and metric reports. */ DebugInfo getDebugInfo(); @@ -58,6 +67,19 @@ interface VibrationSession { /** Removes link to the app process death. */ void unlinkToDeath(); + /** Returns true if this session was requested to end by {@link #requestEnd}. */ + boolean wasEndRequested(); + + /** + * Request the end of this session, which might be acted upon asynchronously. + * + * <p>This is the same as {@link #requestEnd(Status, CallerInfo, boolean)}, with no + * {@link CallerInfo} and with {@code immediate} flag set to false. + */ + default void requestEnd(@NonNull Status status) { + requestEnd(status, /* endedBy= */ null, /* immediate= */ false); + } + /** * Notify the session end was requested, which might be acted upon asynchronously. * @@ -71,6 +93,25 @@ interface VibrationSession { void requestEnd(@NonNull Status status, @Nullable CallerInfo endedBy, boolean immediate); /** + * Notify a vibrator has completed the last command during the playback of given vibration. + * + * <p>This will be called by the vibrator hardware callback indicating the last vibrate call is + * complete (e.g. on(), perform(), compose()). This does not mean the vibration is complete, + * since its playback might have one or more interactions with the vibrator hardware. + */ + void notifyVibratorCallback(int vibratorId, long vibrationId); + + /** + * Notify all synced vibrators have completed the last synchronized command during the playback + * of given vibration. + * + * <p>This will be called by the vibrator manager hardware callback indicating the last + * synchronized vibrate call is complete. This does not mean the vibration is complete, since + * its playback might have one or more interactions with the vibrator hardware. + */ + void notifySyncedVibratorsCallback(long vibrationId); + + /** * Session status with reference to values from vibratormanagerservice.proto for logging. */ enum Status { diff --git a/services/core/java/com/android/server/vibrator/VibrationStats.java b/services/core/java/com/android/server/vibrator/VibrationStats.java index fc0c6e7bf05e..637a5a180063 100644 --- a/services/core/java/com/android/server/vibrator/VibrationStats.java +++ b/services/core/java/com/android/server/vibrator/VibrationStats.java @@ -18,6 +18,7 @@ package com.android.server.vibrator; import android.annotation.NonNull; import android.annotation.Nullable; +import android.os.CombinedVibration; import android.os.SystemClock; import android.os.vibrator.PrebakedSegment; import android.os.vibrator.PrimitiveSegment; @@ -37,11 +38,11 @@ final class VibrationStats { // vibrate request. // - Start: time a vibration started to play, which is closer to the time that the // VibrationEffect started playing the very first segment. - // - End: time a vibration ended, even if it never started to play. This can be as soon as the - // vibrator HAL reports it has finished the last command, or before it has even started - // when the vibration is ignored or cancelled. - // Create and end times set by VibratorManagerService only, guarded by its lock. - // Start times set by VibrationThread only (single-threaded). + // - End: time a vibration ended with a status, even if it never started to play. This can be as + // soon as the vibrator HAL reports it has finished the last command, or before it has + // even started when the vibration is ignored or cancelled. + // Created and ended times set by VibratorManagerService only, guarded by its lock. + // Start time set by VibrationThread only (single-threaded). private long mCreateUptimeMillis; private long mStartUptimeMillis; private long mEndUptimeMillis; @@ -97,6 +98,10 @@ final class VibrationStats { mInterruptedUsage = -1; } + StatsInfo toStatsInfo(int uid, int vibrationType, int usage, VibrationSession.Status status) { + return new VibrationStats.StatsInfo(uid, vibrationType, usage, status, this); + } + long getCreateUptimeMillis() { return mCreateUptimeMillis; } @@ -300,7 +305,7 @@ final class VibrationStats { * {@link com.android.internal.util.FrameworkStatsLog} as a * {@link com.android.internal.util.FrameworkStatsLog#VIBRATION_REPORTED}. */ - static final class StatsInfo { + public static final class StatsInfo { public final int uid; public final int vibrationType; public final int usage; @@ -331,7 +336,7 @@ final class VibrationStats { private boolean mIsWritten; StatsInfo(int uid, int vibrationType, int usage, VibrationSession.Status status, - VibrationStats stats, long completionUptimeMillis) { + VibrationStats stats) { this.uid = uid; this.vibrationType = vibrationType; this.usage = usage; @@ -342,6 +347,9 @@ final class VibrationStats { interruptedUsage = stats.mInterruptedUsage; repeatCount = stats.mRepeatCount; + // Consider this vibration is being completed now. + long completionUptimeMillis = SystemClock.uptimeMillis(); + // This duration goes from the time this object was created until the time it was // completed. We can use latencies to detect the times between first and last // interaction with vibrator. @@ -419,5 +427,25 @@ final class VibrationStats { } return res; } + + /** + * Returns the vibration type value from {@code ReportedVibration} that best represents this + * {@link CombinedVibration}. + * + * <p>This does not include external vibrations, as those are not represented by a single + * vibration effect. + */ + public static int findVibrationType(@Nullable CombinedVibration effect) { + if (effect == null) { + return FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__SINGLE; + } + if (effect.hasVendorEffects()) { + return FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__VENDOR; + } + if (effect.getDuration() == Long.MAX_VALUE) { + return FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__REPEATED; + } + return FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__SINGLE; + } } } diff --git a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java index 1d52e3c87d17..4bb0c16d9655 100644 --- a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java +++ b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java @@ -20,8 +20,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Build; import android.os.CombinedVibration; -import android.os.IBinder; -import android.os.RemoteException; import android.os.VibrationEffect; import android.os.vibrator.Flags; import android.os.vibrator.PrebakedSegment; @@ -39,7 +37,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.NoSuchElementException; import java.util.PriorityQueue; import java.util.Queue; import java.util.concurrent.CancellationException; @@ -55,7 +52,7 @@ import java.util.concurrent.TimeoutException; * VibrationThread. The only thread-safe methods for calling from other threads are the "notify" * methods (which should never be used from the VibrationThread thread). */ -final class VibrationStepConductor implements IBinder.DeathRecipient { +final class VibrationStepConductor { private static final boolean DEBUG = VibrationThread.DEBUG; private static final String TAG = VibrationThread.TAG; @@ -346,42 +343,6 @@ final class VibrationStepConductor implements IBinder.DeathRecipient { } /** - * Binder death notification. VibrationThread registers this when it's running a conductor. - * Note that cancellation could theoretically happen immediately, before the conductor has - * started, but in this case it will be processed in the first signals loop. - */ - @Override - public void binderDied() { - if (DEBUG) { - Slog.d(TAG, "Binder died, cancelling vibration..."); - } - notifyCancelled(new Vibration.EndInfo(Status.CANCELLED_BINDER_DIED), - /* immediate= */ false); - } - - /** - * Returns true if successfully linked this conductor to the death of the binder that requested - * the vibration. - */ - public boolean linkToDeath() { - try { - mVibration.callerToken.linkToDeath(this, 0); - } catch (RemoteException e) { - Slog.e(TAG, "Error linking vibration to token death", e); - return false; - } - return true; - } - - public void unlinkToDeath() { - try { - mVibration.callerToken.unlinkToDeath(this, 0); - } catch (NoSuchElementException e) { - Slog.wtf(TAG, "Failed to unlink vibration to token death", e); - } - } - - /** * Notify the execution that cancellation is requested. This will be acted upon * asynchronously in the VibrationThread. * diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index 07473d10b217..9b7bdece69f9 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -51,7 +51,6 @@ import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.ShellCallback; import android.os.ShellCommand; -import android.os.SystemClock; import android.os.Trace; import android.os.VibrationAttributes; import android.os.VibrationEffect; @@ -159,9 +158,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @GuardedBy("mLock") private final SparseArray<AlwaysOnVibration> mAlwaysOnEffects = new SparseArray<>(); @GuardedBy("mLock") - private VibrationStepConductor mCurrentVibration; + private SingleVibrationSession mCurrentVibration; @GuardedBy("mLock") - private VibrationStepConductor mNextVibration; + private SingleVibrationSession mNextVibration; @GuardedBy("mLock") private ExternalVibrationSession mCurrentExternalVibration; @GuardedBy("mLock") @@ -188,24 +187,20 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // When the system is entering a non-interactive state, we want to cancel // vibrations in case a misbehaving app has abandoned them. if (shouldCancelOnScreenOffLocked(mNextVibration)) { - clearNextVibrationLocked(new Vibration.EndInfo( - Status.CANCELLED_BY_SCREEN_OFF)); + clearNextVibrationLocked(Status.CANCELLED_BY_SCREEN_OFF); } if (shouldCancelOnScreenOffLocked(mCurrentVibration)) { - mCurrentVibration.notifyCancelled(new Vibration.EndInfo( - Status.CANCELLED_BY_SCREEN_OFF), /* immediate= */ false); + mCurrentVibration.requestEnd(Status.CANCELLED_BY_SCREEN_OFF); } } } else if (android.multiuser.Flags.addUiForSoundsFromBackgroundUsers() && intent.getAction().equals(BackgroundUserSoundNotifier.ACTION_MUTE_SOUND)) { synchronized (mLock) { if (shouldCancelOnFgUserRequest(mNextVibration)) { - clearNextVibrationLocked(new Vibration.EndInfo( - Status.CANCELLED_BY_FOREGROUND_USER)); + clearNextVibrationLocked(Status.CANCELLED_BY_FOREGROUND_USER); } if (shouldCancelOnFgUserRequest(mCurrentVibration)) { - mCurrentVibration.notifyCancelled(new Vibration.EndInfo( - Status.CANCELLED_BY_FOREGROUND_USER), /* immediate= */ false); + mCurrentVibration.requestEnd(Status.CANCELLED_BY_FOREGROUND_USER); } } } @@ -222,12 +217,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } synchronized (mLock) { if (shouldCancelAppOpModeChangedLocked(mNextVibration)) { - clearNextVibrationLocked(new Vibration.EndInfo( - Status.CANCELLED_BY_APP_OPS)); + clearNextVibrationLocked(Status.CANCELLED_BY_APP_OPS); } if (shouldCancelAppOpModeChangedLocked(mCurrentVibration)) { - mCurrentVibration.notifyCancelled(new Vibration.EndInfo( - Status.CANCELLED_BY_APP_OPS), /* immediate= */ false); + mCurrentVibration.requestEnd(Status.CANCELLED_BY_APP_OPS); } } } @@ -602,8 +595,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return null; } // Create Vibration.Stats as close to the received request as possible, for tracking. - HalVibration vib = new HalVibration(token, effect, callerInfo); - fillVibrationFallbacks(vib, effect); + SingleVibrationSession session = new SingleVibrationSession(token, callerInfo, effect); + HalVibration vib = session.getVibration(); + vib.fillFallbacks(mVibrationSettings::getFallbackEffect); if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) { // Force update of user settings before checking if this vibration effect should @@ -617,21 +611,26 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } // Check if user settings or DnD is set to ignore this vibration. - Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(vib.callerInfo); + Status ignoreStatus = shouldIgnoreVibrationLocked(callerInfo); + CallerInfo ignoredBy = null; // Check if ongoing vibration is more important than this vibration. - if (vibrationEndInfo == null) { - vibrationEndInfo = shouldIgnoreVibrationForOngoingLocked(vib); + if (ignoreStatus == null) { + Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationForOngoingLocked(session); + if (vibrationEndInfo != null) { + ignoreStatus = vibrationEndInfo.status; + ignoredBy = vibrationEndInfo.endedBy; + } } // If not ignored so far then try to start this vibration. - if (vibrationEndInfo == null) { + if (ignoreStatus == null) { final long ident = Binder.clearCallingIdentity(); try { if (mCurrentExternalVibration != null) { vib.stats.reportInterruptedAnotherVibration( mCurrentExternalVibration.getCallerInfo()); - endExternalVibrateLocked(Status.CANCELLED_SUPERSEDED, vib.callerInfo, + endExternalVibrateLocked(Status.CANCELLED_SUPERSEDED, callerInfo, /* continueExternalControl= */ false); } else if (mCurrentVibration != null) { if (mCurrentVibration.getVibration().canPipelineWith(vib)) { @@ -645,21 +644,19 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } else { vib.stats.reportInterruptedAnotherVibration( mCurrentVibration.getVibration().callerInfo); - mCurrentVibration.notifyCancelled( - new Vibration.EndInfo(Status.CANCELLED_SUPERSEDED, - vib.callerInfo), + mCurrentVibration.requestEnd(Status.CANCELLED_SUPERSEDED, callerInfo, /* immediate= */ false); } } - vibrationEndInfo = startVibrationLocked(vib); + ignoreStatus = startVibrationLocked(session); } finally { Binder.restoreCallingIdentity(ident); } } // Ignored or failed to start the vibration, end it and report metrics right away. - if (vibrationEndInfo != null) { - endVibrationLocked(vib, vibrationEndInfo); + if (ignoreStatus != null) { + endVibrationLocked(session, ignoreStatus, ignoredBy); } return vib; } @@ -677,27 +674,18 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { if (DEBUG) { Slog.d(TAG, "Canceling vibration"); } - Vibration.EndInfo cancelledByUserInfo = - new Vibration.EndInfo(Status.CANCELLED_BY_USER); final long ident = Binder.clearCallingIdentity(); try { - if (mNextVibration != null - && shouldCancelVibration(mNextVibration.getVibration(), - usageFilter, token)) { - clearNextVibrationLocked(cancelledByUserInfo); + if (shouldCancelVibration(mNextVibration, usageFilter, token)) { + clearNextVibrationLocked(Status.CANCELLED_BY_USER); } - if (mCurrentVibration != null - && shouldCancelVibration(mCurrentVibration.getVibration(), - usageFilter, token)) { - mCurrentVibration.notifyCancelled( - cancelledByUserInfo, /* immediate= */false); + if (shouldCancelVibration(mCurrentVibration, usageFilter, token)) { + mCurrentVibration.requestEnd(Status.CANCELLED_BY_USER); } - if (mCurrentExternalVibration != null - && shouldCancelVibration( - mCurrentExternalVibration.getCallerInfo().attrs, - usageFilter)) { - endExternalVibrateLocked(cancelledByUserInfo.status, - cancelledByUserInfo.endedBy, /* continueExternalControl= */ false); + // TODO(b/370948466): investigate why token is not checked here and fix it. + if (shouldCancelVibration(mCurrentExternalVibration, usageFilter, null)) { + endExternalVibrateLocked(Status.CANCELLED_BY_USER, + /* endedBy= */ null, /* continueExternalControl= */ false); } } finally { Binder.restoreCallingIdentity(ident); @@ -842,18 +830,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { return; } - HalVibration vib = mCurrentVibration.getVibration(); - Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(vib.callerInfo); - - if (inputDevicesChanged || (vibrationEndInfo != null)) { + Status ignoreStatus = shouldIgnoreVibrationLocked(mCurrentVibration.getCallerInfo()); + if (inputDevicesChanged || (ignoreStatus != null)) { if (DEBUG) { Slog.d(TAG, "Canceling vibration because settings changed: " - + (inputDevicesChanged ? "input devices changed" - : vibrationEndInfo.status)); + + (inputDevicesChanged ? "input devices changed" : ignoreStatus)); } - mCurrentVibration.notifyCancelled( - new Vibration.EndInfo(Status.CANCELLED_BY_SETTINGS_UPDATE), - /* immediate= */ false); + mCurrentVibration.requestEnd(Status.CANCELLED_BY_SETTINGS_UPDATE); } } } @@ -873,8 +856,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { if (vibrator == null) { continue; } - Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(vib.callerInfo); - if (vibrationEndInfo == null) { + Status ignoreStatus = shouldIgnoreVibrationLocked(vib.callerInfo); + if (ignoreStatus == null) { effect = mVibrationScaler.scale(effect, vib.callerInfo.attrs.getUsage()); } else { // Vibration should not run, use null effect to remove registered effect. @@ -886,25 +869,21 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @GuardedBy("mLock") @Nullable - private Vibration.EndInfo startVibrationLocked(HalVibration vib) { + private Status startVibrationLocked(SingleVibrationSession session) { Trace.traceBegin(TRACE_TAG_VIBRATOR, "startVibrationLocked"); try { if (mInputDeviceDelegate.isAvailable()) { - return startVibrationOnInputDevicesLocked(vib); + return startVibrationOnInputDevicesLocked(session.getVibration()); } - - VibrationStepConductor conductor = createVibrationStepConductor(vib); - if (mCurrentVibration == null) { - return startVibrationOnThreadLocked(conductor); + return startVibrationOnThreadLocked(session); } // If there's already a vibration queued (waiting for the previous one to finish // cancelling), end it cleanly and replace it with the new one. // Note that we don't consider pipelining here, because new pipelined ones should // replace pending non-executing pipelined ones anyway. - clearNextVibrationLocked( - new Vibration.EndInfo(Status.IGNORED_SUPERSEDED, vib.callerInfo)); - mNextVibration = conductor; + clearNextVibrationLocked(Status.IGNORED_SUPERSEDED, session.getCallerInfo()); + mNextVibration = session; return null; } finally { Trace.traceEnd(TRACE_TAG_VIBRATOR); @@ -913,50 +892,45 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @GuardedBy("mLock") @Nullable - private Vibration.EndInfo startVibrationOnThreadLocked(VibrationStepConductor conductor) { - HalVibration vib = conductor.getVibration(); - int mode = startAppOpModeLocked(vib.callerInfo); + private Status startVibrationOnThreadLocked(SingleVibrationSession session) { + VibrationStepConductor conductor = createVibrationStepConductor(session.getVibration()); + session.setVibrationConductor(conductor); + int mode = startAppOpModeLocked(session.getCallerInfo()); switch (mode) { case AppOpsManager.MODE_ALLOWED: Trace.asyncTraceBegin(TRACE_TAG_VIBRATOR, "vibration", 0); // Make sure mCurrentVibration is set while triggering the VibrationThread. - mCurrentVibration = conductor; - if (!mCurrentVibration.linkToDeath()) { + mCurrentVibration = session; + if (!mCurrentVibration.linkToDeath(null)) { // Shouldn't happen. The method call already logs a wtf. mCurrentVibration = null; // Aborted. - return new Vibration.EndInfo(Status.IGNORED_ERROR_TOKEN); + return Status.IGNORED_ERROR_TOKEN; } - if (!mVibrationThread.runVibrationOnVibrationThread(mCurrentVibration)) { + if (!mVibrationThread.runVibrationOnVibrationThread(conductor)) { // Shouldn't happen. The method call already logs a wtf. + mCurrentVibration.setVibrationConductor(null); mCurrentVibration = null; // Aborted. - return new Vibration.EndInfo(Status.IGNORED_ERROR_SCHEDULING); + return Status.IGNORED_ERROR_SCHEDULING; } return null; case AppOpsManager.MODE_ERRORED: Slog.w(TAG, "Start AppOpsManager operation errored for uid " - + vib.callerInfo.uid); - return new Vibration.EndInfo(Status.IGNORED_ERROR_APP_OPS); + + session.getCallerInfo().uid); + return Status.IGNORED_ERROR_APP_OPS; default: - return new Vibration.EndInfo(Status.IGNORED_APP_OPS); + return Status.IGNORED_APP_OPS; } } @GuardedBy("mLock") - private void endVibrationLocked(Vibration vib, Status status) { - endVibrationLocked(vib, new Vibration.EndInfo(status)); - } - - @GuardedBy("mLock") - private void endVibrationLocked(Vibration vib, Vibration.EndInfo vibrationEndInfo) { - vib.end(vibrationEndInfo); - reportEndedVibrationLocked(vib); + private void endVibrationLocked(VibrationSession session, Status status) { + endVibrationLocked(session, status, /* endedBy= */ null); } @GuardedBy("mLock") - private void reportEndedVibrationLocked(Vibration vib) { - logAndRecordVibration(vib.getDebugInfo()); - mFrameworkStatsLogger.writeVibrationReportedAsync( - vib.getStatsInfo(/* completionUptimeMillis= */ SystemClock.uptimeMillis())); + private void endVibrationLocked(VibrationSession session, Status status, CallerInfo endedBy) { + session.requestEnd(status, endedBy, /* immediate= */ false); + logAndRecordVibration(session.getDebugInfo()); } private VibrationStepConductor createVibrationStepConductor(HalVibration vib) { @@ -975,12 +949,11 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mFrameworkStatsLogger, requestVibrationParamsFuture, mVibrationThreadCallbacks); } - private Vibration.EndInfo startVibrationOnInputDevicesLocked(HalVibration vib) { + private Status startVibrationOnInputDevicesLocked(HalVibration vib) { // Scale resolves the default amplitudes from the effect before scaling them. vib.scaleEffects(mVibrationScaler); mInputDeviceDelegate.vibrateIfAvailable(vib.callerInfo, vib.getEffectToPlay()); - - return new Vibration.EndInfo(Status.FORWARDED_TO_INPUT_DEVICES); + return Status.FORWARDED_TO_INPUT_DEVICES; } private void logAndRecordPerformHapticFeedbackAttempt(int uid, int deviceId, String opPkg, @@ -994,9 +967,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { private void logAndRecordVibrationAttempt(@Nullable CombinedVibration effect, CallerInfo callerInfo, Status status) { logAndRecordVibration( - new Vibration.DebugInfoImpl(status, new VibrationStats(), + new Vibration.DebugInfoImpl(status, callerInfo, + VibrationStats.StatsInfo.findVibrationType(effect), new VibrationStats(), effect, /* originalEffect= */ null, VibrationScaler.SCALE_NONE, - VibrationScaler.ADAPTIVE_SCALE_NONE, callerInfo)); + VibrationScaler.ADAPTIVE_SCALE_NONE)); } private void logAndRecordVibration(DebugInfo info) { @@ -1050,39 +1024,25 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } } - @GuardedBy("mLock") - private void reportFinishedVibrationLocked() { - Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); - mCurrentVibration.unlinkToDeath(); - HalVibration vib = mCurrentVibration.getVibration(); - if (DEBUG) { - Slog.d(TAG, "Reporting vibration " + vib.id + " finished with " + vib.getStatus()); - } - finishAppOpModeLocked(vib.callerInfo); - reportEndedVibrationLocked(vib); - } - private void onSyncedVibrationComplete(long vibrationId) { synchronized (mLock) { - if (mCurrentVibration != null - && mCurrentVibration.getVibration().id == vibrationId) { + if (mCurrentVibration != null) { if (DEBUG) { Slog.d(TAG, "Synced vibration " + vibrationId + " complete, notifying thread"); } - mCurrentVibration.notifySyncedVibrationComplete(); + mCurrentVibration.notifySyncedVibratorsCallback(vibrationId); } } } private void onVibrationComplete(int vibratorId, long vibrationId) { synchronized (mLock) { - if (mCurrentVibration != null - && mCurrentVibration.getVibration().id == vibrationId) { + if (mCurrentVibration != null) { if (DEBUG) { Slog.d(TAG, "Vibration " + vibrationId + " on vibrator " + vibratorId + " complete, notifying thread"); } - mCurrentVibration.notifyVibratorComplete(vibratorId); + mCurrentVibration.notifyVibratorCallback(vibratorId, vibrationId); } } } @@ -1094,14 +1054,14 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { */ @GuardedBy("mLock") @Nullable - private Vibration.EndInfo shouldIgnoreVibrationForOngoingLocked(Vibration vib) { + private Vibration.EndInfo shouldIgnoreVibrationForOngoingLocked(VibrationSession session) { if (mCurrentExternalVibration != null) { - return shouldIgnoreVibrationForOngoing(vib, mCurrentExternalVibration); + return shouldIgnoreVibrationForOngoing(session, mCurrentExternalVibration); } if (mNextVibration != null) { - Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationForOngoing(vib, - mNextVibration.getVibration()); + Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationForOngoing(session, + mNextVibration); if (vibrationEndInfo != null) { // Next vibration has higher importance than the new one, so the new vibration // should be ignored. @@ -1110,14 +1070,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } if (mCurrentVibration != null) { - HalVibration currentVibration = mCurrentVibration.getVibration(); - if (currentVibration.hasEnded() || mCurrentVibration.wasNotifiedToCancel()) { - // Current vibration has ended or is cancelling, should not block incoming - // vibrations. + if (mCurrentVibration.wasEndRequested()) { + // Current session has ended or is cancelling, should not block incoming vibrations. return null; } - return shouldIgnoreVibrationForOngoing(vib, currentVibration); + return shouldIgnoreVibrationForOngoing(session, mCurrentVibration); } return null; @@ -1125,32 +1083,33 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { /** * Checks if the ongoing vibration has higher importance than the new one. If they have similar - * importance, then {@link Vibration#isRepeating()} is used as a tiebreaker. + * importance, then {@link VibrationSession#isRepeating()} is used as a tiebreaker. * * @return a Vibration.EndInfo if the vibration should be ignored, null otherwise. */ @Nullable private static Vibration.EndInfo shouldIgnoreVibrationForOngoing( - @NonNull Vibration newVibration, @NonNull Vibration ongoingVibration) { + @NonNull VibrationSession newSession, @NonNull VibrationSession ongoingSession) { - int newVibrationImportance = getVibrationImportance(newVibration); - int ongoingVibrationImportance = getVibrationImportance(ongoingVibration); + int newSessionImportance = getVibrationImportance(newSession); + int ongoingSessionImportance = getVibrationImportance(ongoingSession); - if (newVibrationImportance > ongoingVibrationImportance) { + if (newSessionImportance > ongoingSessionImportance) { // New vibration has higher importance and should not be ignored. return null; } - if (ongoingVibrationImportance > newVibrationImportance) { + if (ongoingSessionImportance > newSessionImportance) { // Existing vibration has higher importance and should not be cancelled. return new Vibration.EndInfo(Status.IGNORED_FOR_HIGHER_IMPORTANCE, - ongoingVibration.callerInfo); + ongoingSession.getCallerInfo()); } // Same importance, use repeating as a tiebreaker. - if (ongoingVibration.isRepeating() && !newVibration.isRepeating()) { + if (ongoingSession.isRepeating() && !newSession.isRepeating()) { // Ongoing vibration is repeating and new one is not, give priority to ongoing - return new Vibration.EndInfo(Status.IGNORED_FOR_ONGOING, ongoingVibration.callerInfo); + return new Vibration.EndInfo(Status.IGNORED_FOR_ONGOING, + ongoingSession.getCallerInfo()); } // New vibration is repeating or this is a complete tie between them, // give priority to new vibration. @@ -1164,10 +1123,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { * @return a numeric representation for the vibration importance, larger values represent a * higher importance */ - private static int getVibrationImportance(Vibration vibration) { - int usage = vibration.callerInfo.attrs.getUsage(); + private static int getVibrationImportance(VibrationSession session) { + int usage = session.getCallerInfo().attrs.getUsage(); if (usage == VibrationAttributes.USAGE_UNKNOWN) { - if (vibration.isRepeating()) { + if (session.isRepeating()) { usage = VibrationAttributes.USAGE_RINGTONE; } else { usage = VibrationAttributes.USAGE_TOUCH; @@ -1201,10 +1160,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { */ @GuardedBy("mLock") @Nullable - private Vibration.EndInfo shouldIgnoreVibrationLocked(CallerInfo callerInfo) { + private Status shouldIgnoreVibrationLocked(CallerInfo callerInfo) { Status statusFromSettings = mVibrationSettings.shouldIgnoreVibration(callerInfo); if (statusFromSettings != null) { - return new Vibration.EndInfo(statusFromSettings); + return statusFromSettings; } int mode = checkAppOpModeLocked(callerInfo); @@ -1212,9 +1171,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { if (mode == AppOpsManager.MODE_ERRORED) { // We might be getting calls from within system_server, so we don't actually // want to throw a SecurityException here. - return new Vibration.EndInfo(Status.IGNORED_ERROR_APP_OPS); + return Status.IGNORED_ERROR_APP_OPS; } else { - return new Vibration.EndInfo(Status.IGNORED_APP_OPS); + return Status.IGNORED_APP_OPS; } } @@ -1239,32 +1198,29 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { /** * Return true if the vibration has the same token and usage belongs to given usage class. * - * @param vib The ongoing or pending vibration to be cancelled. + * @param session The ongoing or pending vibration session to be cancelled. * @param usageFilter The vibration usages to be cancelled, any bitwise combination of * VibrationAttributes.USAGE_* values. - * @param token The binder token to identify the vibration origin. Only vibrations + * @param tokenFilter The binder token to identify the vibration origin. Only vibrations * started with the same token can be cancelled with it. */ - private boolean shouldCancelVibration(HalVibration vib, int usageFilter, IBinder token) { - return (vib.callerToken == token) && shouldCancelVibration(vib.callerInfo.attrs, - usageFilter); - } - - /** - * Return true if the external vibration usage belongs to given usage class. - * - * @param attrs The attributes of an ongoing or pending vibration to be cancelled. - * @param usageFilter The vibration usages to be cancelled, any bitwise combination of - * VibrationAttributes.USAGE_* values. - */ - private boolean shouldCancelVibration(VibrationAttributes attrs, int usageFilter) { - if (attrs.getUsage() == VibrationAttributes.USAGE_UNKNOWN) { + private boolean shouldCancelVibration(@Nullable VibrationSession session, int usageFilter, + @Nullable IBinder tokenFilter) { + if (session == null) { + return false; + } + if ((tokenFilter != null) && (tokenFilter != session.getCallerToken())) { + // Vibration from a different app, this should not cancel it. + return false; + } + int usage = session.getCallerInfo().attrs.getUsage(); + if (usage == VibrationAttributes.USAGE_UNKNOWN) { // Special case, usage UNKNOWN would match all filters. Instead it should only match if // it's cancelling that usage specifically, or if cancelling all usages. return usageFilter == VibrationAttributes.USAGE_UNKNOWN || usageFilter == VibrationAttributes.USAGE_FILTER_MATCH_ALL; } - return (usageFilter & attrs.getUsage()) == attrs.getUsage(); + return (usageFilter & usage) == usage; } /** @@ -1340,45 +1296,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } /** - * Sets fallback effects to all prebaked ones in given combination of effects, based on {@link - * VibrationSettings#getFallbackEffect}. - */ - private void fillVibrationFallbacks(HalVibration vib, CombinedVibration effect) { - if (effect instanceof CombinedVibration.Mono) { - fillVibrationFallbacks(vib, ((CombinedVibration.Mono) effect).getEffect()); - } else if (effect instanceof CombinedVibration.Stereo) { - SparseArray<VibrationEffect> effects = - ((CombinedVibration.Stereo) effect).getEffects(); - for (int i = 0; i < effects.size(); i++) { - fillVibrationFallbacks(vib, effects.valueAt(i)); - } - } else if (effect instanceof CombinedVibration.Sequential) { - List<CombinedVibration> effects = - ((CombinedVibration.Sequential) effect).getEffects(); - for (int i = 0; i < effects.size(); i++) { - fillVibrationFallbacks(vib, effects.get(i)); - } - } - } - - private void fillVibrationFallbacks(HalVibration vib, VibrationEffect effect) { - if (!(effect instanceof VibrationEffect.Composed composed)) { - return; - } - int segmentCount = composed.getSegments().size(); - for (int i = 0; i < segmentCount; i++) { - VibrationEffectSegment segment = composed.getSegments().get(i); - if (segment instanceof PrebakedSegment prebaked) { - VibrationEffect fallback = mVibrationSettings.getFallbackEffect( - prebaked.getEffectId()); - if (prebaked.shouldFallback() && fallback != null) { - vib.addFallback(prebaked.getEffectId(), fallback); - } - } - } - } - - /** * Return new {@link VibrationAttributes} that only applies flags that this user has permissions * to use. */ @@ -1475,30 +1392,28 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } @GuardedBy("mLock") - private boolean shouldCancelOnScreenOffLocked(@Nullable VibrationStepConductor conductor) { - if (conductor == null) { + private boolean shouldCancelOnScreenOffLocked(@Nullable VibrationSession session) { + if (session == null) { return false; } - HalVibration vib = conductor.getVibration(); - return mVibrationSettings.shouldCancelVibrationOnScreenOff(vib.callerInfo, - vib.stats.getCreateUptimeMillis()); + return mVibrationSettings.shouldCancelVibrationOnScreenOff(session.getCallerInfo(), + session.getCreateUptimeMillis()); } @GuardedBy("mLock") - private boolean shouldCancelAppOpModeChangedLocked(@Nullable VibrationStepConductor conductor) { - if (conductor == null) { + private boolean shouldCancelAppOpModeChangedLocked(@Nullable VibrationSession session) { + if (session == null) { return false; } - return checkAppOpModeLocked(conductor.getVibration().callerInfo) - != AppOpsManager.MODE_ALLOWED; + return checkAppOpModeLocked(session.getCallerInfo()) != AppOpsManager.MODE_ALLOWED; } @GuardedBy("mLock") - private boolean shouldCancelOnFgUserRequest(@Nullable VibrationStepConductor conductor) { - if (conductor == null) { + private boolean shouldCancelOnFgUserRequest(@Nullable VibrationSession session) { + if (session == null) { return false; } - return conductor.getVibration().callerInfo.attrs.getUsageClass() == USAGE_CLASS_ALARM; + return session.getCallerInfo().attrs.getUsageClass() == USAGE_CLASS_ALARM; } @GuardedBy("mLock") @@ -1660,17 +1575,21 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } if (mCurrentVibration != null) { // This is when we consider the current vibration complete, report metrics. - reportFinishedVibrationLocked(); + if (DEBUG) { + Slog.d(TAG, "Reporting vibration " + vibrationId + " finished."); + } + mCurrentVibration.unlinkToDeath(); + finishAppOpModeLocked(mCurrentVibration.getCallerInfo()); + logAndRecordVibration(mCurrentVibration.getDebugInfo()); + Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); mCurrentVibration = null; } if (mNextVibration != null) { - VibrationStepConductor nextConductor = mNextVibration; + SingleVibrationSession nextVibration = mNextVibration; mNextVibration = null; - Vibration.EndInfo vibrationEndInfo = startVibrationOnThreadLocked( - nextConductor); - if (vibrationEndInfo != null) { - // Failed to start the vibration, end it and report metrics right away. - endVibrationLocked(nextConductor.getVibration(), vibrationEndInfo); + Status startErrorStatus = startVibrationOnThreadLocked(nextVibration); + if (startErrorStatus != null) { + endVibrationLocked(nextVibration, startErrorStatus); } } } @@ -1892,17 +1811,22 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mInfo.dump(proto, fieldId); } } + /** Clears mNextVibration if set, ending it cleanly */ + @GuardedBy("mLock") + private void clearNextVibrationLocked(Status status) { + clearNextVibrationLocked(status, /* endedBy= */ null); + } /** Clears mNextVibration if set, ending it cleanly */ @GuardedBy("mLock") - private void clearNextVibrationLocked(Vibration.EndInfo vibrationEndInfo) { + private void clearNextVibrationLocked(Status status, CallerInfo endedBy) { if (mNextVibration != null) { if (DEBUG) { - Slog.d(TAG, "Dropping pending vibration " + mNextVibration.getVibration().id - + " with end info: " + vibrationEndInfo); + Slog.d(TAG, "Dropping pending vibration from " + mNextVibration.getCallerInfo() + + " with status: " + status); } // Clearing next vibration before playing it, end it and report metrics right away. - endVibrationLocked(mNextVibration.getVibration(), vibrationEndInfo); + endVibrationLocked(mNextVibration, status, endedBy); mNextVibration = null; } } @@ -1927,7 +1851,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { setExternalControl(false, mCurrentExternalVibration.stats); } // The external control was turned off, end it and report metrics right away. - reportEndedVibrationLocked(mCurrentExternalVibration); + logAndRecordVibration(mCurrentExternalVibration.getDebugInfo()); mCurrentExternalVibration = null; } @@ -1987,16 +1911,16 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { try { // Create Vibration.Stats as close to the received request as possible, for // tracking. - ExternalVibrationSession externalVibration = new ExternalVibrationSession(vib); + ExternalVibrationSession session = new ExternalVibrationSession(vib); // Mute the request until we run all the checks and accept the vibration. - externalVibration.muteScale(); + session.muteScale(); boolean alreadyUnderExternalControl = false; boolean waitForCompletion = false; synchronized (mLock) { if (!hasExternalControlCapability()) { - endVibrationLocked(externalVibration, Status.IGNORED_UNSUPPORTED); - return externalVibration.getScale(); + endVibrationLocked(session, Status.IGNORED_UNSUPPORTED); + return session.getScale(); } if (ActivityManager.checkComponentPermission( @@ -2006,29 +1930,30 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { Slog.w(TAG, "pkg=" + vib.getPackage() + ", uid=" + vib.getUid() + " tried to play externally controlled vibration" + " without VIBRATE permission, ignoring."); - endVibrationLocked(externalVibration, Status.IGNORED_MISSING_PERMISSION); - return externalVibration.getScale(); + endVibrationLocked(session, Status.IGNORED_MISSING_PERMISSION); + return session.getScale(); } - Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked( - externalVibration.callerInfo); + Status ignoreStatus = shouldIgnoreVibrationLocked(session.callerInfo); + if (ignoreStatus != null) { + endVibrationLocked(session, ignoreStatus); + return session.getScale(); + } - if (vibrationEndInfo == null - && mCurrentExternalVibration != null + if (mCurrentExternalVibration != null && mCurrentExternalVibration.isHoldingSameVibration(vib)) { // We are already playing this external vibration, so we can return the same // scale calculated in the previous call to this method. return mCurrentExternalVibration.getScale(); } - if (vibrationEndInfo == null) { - // Check if ongoing vibration is more important than this vibration. - vibrationEndInfo = shouldIgnoreVibrationForOngoingLocked(externalVibration); - } - + // Check if ongoing vibration is more important than this vibration. + Vibration.EndInfo vibrationEndInfo = + shouldIgnoreVibrationForOngoingLocked(session); if (vibrationEndInfo != null) { - endVibrationLocked(externalVibration, vibrationEndInfo); - return externalVibration.getScale(); + endVibrationLocked(session, vibrationEndInfo.status, + vibrationEndInfo.endedBy); + return session.getScale(); } if (mCurrentExternalVibration == null) { @@ -2036,15 +1961,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // vibration that may be playing and ready the vibrator for external // control. if (mCurrentVibration != null) { - externalVibration.stats.reportInterruptedAnotherVibration( + session.stats.reportInterruptedAnotherVibration( mCurrentVibration.getVibration().callerInfo); - clearNextVibrationLocked( - new Vibration.EndInfo(Status.IGNORED_FOR_EXTERNAL, - externalVibration.callerInfo)); - mCurrentVibration.notifyCancelled( - new Vibration.EndInfo(Status.CANCELLED_SUPERSEDED, - externalVibration.callerInfo), - /* immediate= */ true); + clearNextVibrationLocked(Status.IGNORED_FOR_EXTERNAL, + session.callerInfo); + mCurrentVibration.requestEnd(Status.CANCELLED_SUPERSEDED, + session.callerInfo, /* immediate= */ true); waitForCompletion = true; } } else { @@ -2060,10 +1982,10 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // as we would need to mute the old one still if it came from a different // controller. alreadyUnderExternalControl = true; - externalVibration.stats.reportInterruptedAnotherVibration( + session.stats.reportInterruptedAnotherVibration( mCurrentExternalVibration.getCallerInfo()); endExternalVibrateLocked(Status.CANCELLED_SUPERSEDED, - externalVibration.callerInfo, /* continueExternalControl= */ true); + session.callerInfo, /* continueExternalControl= */ true); } } // Wait for lock and interact with HAL to set external control outside main lock. @@ -2071,8 +1993,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { if (!mVibrationThread.waitForThreadIdle(VIBRATION_CANCEL_WAIT_MILLIS)) { Slog.e(TAG, "Timed out waiting for vibration to cancel"); synchronized (mLock) { - endVibrationLocked(externalVibration, Status.IGNORED_ERROR_CANCELLING); - return externalVibration.getScale(); + endVibrationLocked(session, Status.IGNORED_ERROR_CANCELLING); + return session.getScale(); } } } @@ -2080,7 +2002,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { if (DEBUG) { Slog.d(TAG, "Vibrator going under external control."); } - setExternalControl(true, externalVibration.stats); + setExternalControl(true, session.stats); } synchronized (mLock) { if (DEBUG) { @@ -2095,14 +2017,14 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mVibrationSettings.update(); } - mCurrentExternalVibration = externalVibration; - externalVibration.linkToDeath(this::onExternalVibrationBinderDied); - externalVibration.scale(mVibrationScaler, attrs.getUsage()); + mCurrentExternalVibration = session; + session.linkToDeath(this::onExternalVibrationBinderDied); + session.scale(mVibrationScaler, attrs.getUsage()); // Vibrator will start receiving data from external channels after this point. // Report current time as the vibration start time, for debugging. - externalVibration.stats.reportStarted(); - return externalVibration.getScale(); + session.stats.reportStarted(); + return session.getScale(); } } finally { Trace.traceEnd(TRACE_TAG_VIBRATOR); diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index 517f631a0c1c..ae30fcde39e1 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -442,6 +442,8 @@ class ActivityClientController extends IActivityClientController.Stub { throw new IllegalArgumentException("File descriptors passed in Intent"); } + mService.mAmInternal.addCreatorToken(resultData); + final ActivityRecord r; synchronized (mGlobalLock) { r = ActivityRecord.isInRootTaskLocked(token); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 5372abe970c7..31f4d081d913 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -230,6 +230,7 @@ import static com.android.server.wm.IdentifierProto.HASH_CODE; import static com.android.server.wm.IdentifierProto.TITLE; import static com.android.server.wm.IdentifierProto.USER_ID; import static com.android.server.wm.StartingData.AFTER_TRANSACTION_COPY_TO_CLIENT; +import static com.android.server.wm.StartingData.AFTER_TRANSACTION_IDLE; import static com.android.server.wm.StartingData.AFTER_TRANSACTION_REMOVE_DIRECTLY; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_PREDICT_BACK; @@ -286,6 +287,9 @@ import android.app.servertransaction.StopActivityItem; import android.app.servertransaction.TopResumedActivityChangeItem; import android.app.servertransaction.TransferSplashScreenViewStateItem; import android.app.usage.UsageEvents.Event; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; +import android.compat.annotation.Overridable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -465,6 +469,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // finished destroying itself. private static final int DESTROY_TIMEOUT = 10 * 1000; + @ChangeId + @Overridable + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) + static final long UNIVERSAL_RESIZABLE_BY_DEFAULT = 357141415; + final ActivityTaskManagerService mAtmService; final ActivityCallerState mCallerState; @NonNull @@ -871,8 +880,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A }) @interface SplashScreenBehavior { } - // TODO: Have a WindowContainer state for tracking exiting/deferred removal. - boolean mIsExiting; // Force an app transition to be ran in the case the visibility of the app did not change. // We use this for the case of moving a Root Task to the back with multiple activities, and the // top activity enters PIP; the bottom activity's visibility stays the same, but we need to @@ -1218,10 +1225,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn); pw.println(")"); } - if (mStartingData != null || firstWindowDrawn || mIsExiting) { + if (mStartingData != null || firstWindowDrawn) { pw.print(prefix); pw.print("startingData="); pw.print(mStartingData); - pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn); - pw.print(" mIsExiting="); pw.println(mIsExiting); + pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn); } if (mStartingWindow != null || mStartingData != null || mStartingSurface != null || startingMoved || mVisibleSetFromTransferredStartingWindow) { @@ -2635,8 +2641,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (finishing || !mHandleExitSplashScreen || mStartingSurface == null || mStartingWindow == null || mTransferringSplashScreenState == TRANSFER_SPLASH_SCREEN_FINISH - // skip copy splash screen to client if it was resized - || (mStartingData != null && mStartingData.mResizedFromTransfer) + // Skip copy splash screen to client if it was resized, or the starting data already + // requested to be removed after transaction commit. + || (mStartingData != null && (mStartingData.mResizedFromTransfer + || mStartingData.mRemoveAfterTransaction != AFTER_TRANSACTION_IDLE)) || isRelaunching()) { return false; } @@ -3179,11 +3187,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * will be ignored. */ boolean isUniversalResizeable() { - return mWmService.mConstants.mIgnoreActivityOrientationRequest - && info.applicationInfo.category != ApplicationInfo.CATEGORY_GAME - // If the user preference respects aspect ratio, then it becomes non-resizable. - && !mAppCompatController.getAppCompatOverrides().getAppCompatAspectRatioOverrides() - .shouldApplyUserMinAspectRatioOverride(); + if (info.applicationInfo.category == ApplicationInfo.CATEGORY_GAME) { + return false; + } + final boolean compatEnabled = Flags.universalResizableByDefault() + && mDisplayContent != null && mDisplayContent.getConfiguration() + .smallestScreenWidthDp >= WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP + && mDisplayContent.getIgnoreOrientationRequest() + && info.isChangeEnabled(UNIVERSAL_RESIZABLE_BY_DEFAULT); + if (!compatEnabled && !mWmService.mConstants.mIgnoreActivityOrientationRequest) { + return false; + } + // If the user preference respects aspect ratio, then it becomes non-resizable. + return !mAppCompatController.getAppCompatOverrides().getAppCompatAspectRatioOverrides() + .shouldApplyUserMinAspectRatioOverride(); } boolean isResizeable() { @@ -4350,21 +4367,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A super.removeImmediately(); } - @Override - void removeIfPossible() { - mIsExiting = false; - removeAllWindowsIfPossible(); - removeImmediately(); - } - - @Override - boolean handleCompleteDeferredRemoval() { - if (mIsExiting) { - removeIfPossible(); - } - return super.handleCompleteDeferredRemoval(); - } - void onRemovedFromDisplay() { if (mRemovingFromDisplay) { return; @@ -6409,11 +6411,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // and the token could be null. return; } - final AppCompatCameraPolicy cameraPolicy = AppCompatCameraPolicy - .getAppCompatCameraPolicy(r); - if (cameraPolicy != null) { - cameraPolicy.onActivityRefreshed(r); - } + AppCompatCameraPolicy.onActivityRefreshed(r); } static void splashScreenAttachedLocked(IBinder token) { @@ -8179,7 +8177,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @ActivityInfo.ScreenOrientation protected int getOverrideOrientation() { int candidateOrientation = super.getOverrideOrientation(); - if (isUniversalResizeable() && ActivityInfo.isFixedOrientation(candidateOrientation)) { + if (ActivityInfo.isFixedOrientation(candidateOrientation) && isUniversalResizeable()) { candidateOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; } return mAppCompatController.getOrientationPolicy() @@ -9456,11 +9454,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return; } - final AppCompatCameraPolicy cameraPolicy = AppCompatCameraPolicy.getAppCompatCameraPolicy( - this); - if (cameraPolicy != null) { - cameraPolicy.onActivityConfigurationChanging(this, newConfig, lastReportedConfig); - } + AppCompatCameraPolicy.onActivityConfigurationChanging(this, newConfig, lastReportedConfig); } /** Get process configuration, or global config if the process is not set. */ diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 49380d4b8797..87fa62ac0e3b 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2759,10 +2759,7 @@ class ActivityStarter { mInTask = null; // Launch ResolverActivity in the source task, so that it stays in the task bounds // when in freeform workspace. - // Also put noDisplay activities in the source task. These by itself can be placed - // in any task/root-task, however it could launch other activities like - // ResolverActivity, and we want those to stay in the original task. - if ((mStartActivity.isResolverOrDelegateActivity() || mStartActivity.noDisplay) + if (mStartActivity.isResolverOrDelegateActivity() && mSourceRecord != null && mSourceRecord.inFreeformWindowingMode()) { mAddingToTask = true; } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index dc960a02e6e5..3dfc8f4e5bf9 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -1228,6 +1228,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) { + mAmInternal.addCreatorToken(intent); return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, UserHandle.getCallingUserId()); @@ -1240,6 +1241,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { assertPackageMatchesCallingUid(callingPackage); final String reason = "startActivities"; enforceNotIsolatedCaller(reason); + if (intents != null) { + for (Intent intent : intents) { + mAmInternal.addCreatorToken(intent); + } + } userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, reason); // TODO: Switch to user app stacks here. return getActivityStartController().startActivities(caller, -1, 0, -1, callingPackage, @@ -1269,6 +1275,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Nullable String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) { + mAmInternal.addCreatorToken(intent); final SafeActivityOptions opts = SafeActivityOptions.fromBundle(bOptions); assertPackageMatchesCallingUid(callingPackage); @@ -1323,6 +1330,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } // Remove existing mismatch flag so it can be properly updated later fillInIntent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH); + mAmInternal.addCreatorToken(fillInIntent); } if (!(target instanceof PendingIntentRecord)) { @@ -1352,6 +1360,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (intent != null && intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); } + + mAmInternal.addCreatorToken(intent); + SafeActivityOptions options = SafeActivityOptions.fromBundle(bOptions); synchronized (mGlobalLock) { diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java index 0e666296dc33..d59046f44129 100644 --- a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java +++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java @@ -255,13 +255,10 @@ class AppCompatAspectRatioOverrides { mActivityRecord.getOverrideOrientation()); final AppCompatCameraOverrides cameraOverrides = mActivityRecord.mAppCompatController.getAppCompatCameraOverrides(); - final AppCompatCameraPolicy cameraPolicy = AppCompatCameraPolicy.getAppCompatCameraPolicy( - mActivityRecord); // Don't resize to split screen size when in book mode if letterbox position is centered return (isBookMode && isNotCenteredHorizontally || isTabletopMode && isLandscape) || cameraOverrides.isCameraCompatSplitScreenAspectRatioAllowed() - && (cameraPolicy != null - && cameraPolicy.isTreatmentEnabledForActivity(mActivityRecord)); + && AppCompatCameraPolicy.isTreatmentEnabledForActivity(mActivityRecord); } /** diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java index 3b023fe451bf..548c0a34bf99 100644 --- a/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java +++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java @@ -74,11 +74,9 @@ class AppCompatAspectRatioPolicy { @NonNull Rect parentBounds) { // If in camera compat mode, aspect ratio from the camera compat policy has priority over // default letterbox aspect ratio. - final AppCompatCameraPolicy cameraPolicy = AppCompatCameraPolicy.getAppCompatCameraPolicy( - mActivityRecord); - if (cameraPolicy != null && cameraPolicy.shouldCameraCompatControlAspectRatio( + if (AppCompatCameraPolicy.shouldCameraCompatControlAspectRatio( mActivityRecord)) { - return cameraPolicy.getCameraCompatAspectRatio(mActivityRecord); + return AppCompatCameraPolicy.getCameraCompatAspectRatio(mActivityRecord); } final float letterboxAspectRatioOverride = @@ -128,12 +126,8 @@ class AppCompatAspectRatioPolicy { if (aspectRatioOverrides.shouldApplyUserMinAspectRatioOverride()) { return aspectRatioOverrides.getUserMinAspectRatio(); } - final AppCompatCameraPolicy cameraPolicy = AppCompatCameraPolicy.getAppCompatCameraPolicy( - mActivityRecord); - final boolean shouldOverrideMinAspectRatioForCamera = cameraPolicy != null - && cameraPolicy.shouldOverrideMinAspectRatioForCamera(mActivityRecord); if (!aspectRatioOverrides.shouldOverrideMinAspectRatio() - && !shouldOverrideMinAspectRatioForCamera) { + && !AppCompatCameraPolicy.shouldOverrideMinAspectRatioForCamera(mActivityRecord)) { if (mActivityRecord.isUniversalResizeable()) { return 0; } diff --git a/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java b/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java index f6090eb89345..8c5689c1ef57 100644 --- a/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java +++ b/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java @@ -22,6 +22,7 @@ import static com.android.server.wm.AppCompatConfiguration.MIN_FIXED_ORIENTATION import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.CameraCompatTaskInfo; import android.content.pm.ActivityInfo.ScreenOrientation; import android.content.res.Configuration; import android.widget.Toast; @@ -70,9 +71,10 @@ class AppCompatCameraPolicy { } } - void onActivityRefreshed(@NonNull ActivityRecord activity) { - if (mActivityRefresher != null) { - mActivityRefresher.onActivityRefreshed(activity); + static void onActivityRefreshed(@NonNull ActivityRecord activity) { + final AppCompatCameraPolicy cameraPolicy = getAppCompatCameraPolicy(activity); + if (cameraPolicy != null && cameraPolicy.mActivityRefresher != null) { + cameraPolicy.mActivityRefresher.onActivityRefreshed(activity); } } @@ -88,10 +90,11 @@ class AppCompatCameraPolicy { * camera preview and can lead to sideways or stretching issues persisting even after force * rotation. */ - void onActivityConfigurationChanging(@NonNull ActivityRecord activity, + static void onActivityConfigurationChanging(@NonNull ActivityRecord activity, @NonNull Configuration newConfig, @NonNull Configuration lastReportedConfig) { - if (mActivityRefresher != null) { - mActivityRefresher.onActivityConfigurationChanging(activity, newConfig, + final AppCompatCameraPolicy cameraPolicy = getAppCompatCameraPolicy(activity); + if (cameraPolicy != null && cameraPolicy.mActivityRefresher != null) { + cameraPolicy.mActivityRefresher.onActivityConfigurationChanging(activity, newConfig, lastReportedConfig); } } @@ -108,11 +111,11 @@ class AppCompatCameraPolicy { } } - boolean isActivityEligibleForOrientationOverride(@NonNull ActivityRecord activity) { - if (mDisplayRotationCompatPolicy != null) { - return mDisplayRotationCompatPolicy.isActivityEligibleForOrientationOverride(activity); - } - return false; + static boolean isActivityEligibleForOrientationOverride(@NonNull ActivityRecord activity) { + final AppCompatCameraPolicy cameraPolicy = getAppCompatCameraPolicy(activity); + return cameraPolicy != null && cameraPolicy.mDisplayRotationCompatPolicy != null + && cameraPolicy.mDisplayRotationCompatPolicy + .isActivityEligibleForOrientationOverride(activity); } /** @@ -125,11 +128,11 @@ class AppCompatCameraPolicy { * <li>The activity has fixed orientation but not "locked" or "nosensor" one. * </ul> */ - boolean isTreatmentEnabledForActivity(@Nullable ActivityRecord activity) { - if (mDisplayRotationCompatPolicy != null) { - return mDisplayRotationCompatPolicy.isTreatmentEnabledForActivity(activity); - } - return false; + static boolean isTreatmentEnabledForActivity(@NonNull ActivityRecord activity) { + final AppCompatCameraPolicy cameraPolicy = getAppCompatCameraPolicy(activity); + return cameraPolicy != null && cameraPolicy.mDisplayRotationCompatPolicy != null + && cameraPolicy.mDisplayRotationCompatPolicy + .isTreatmentEnabledForActivity(activity); } void start() { @@ -176,23 +179,31 @@ class AppCompatCameraPolicy { } // TODO(b/369070416): have policies implement the same interface. - boolean shouldCameraCompatControlOrientation(@NonNull ActivityRecord activity) { - return (mDisplayRotationCompatPolicy != null - && mDisplayRotationCompatPolicy.shouldCameraCompatControlOrientation( - activity)) - || (mCameraCompatFreeformPolicy != null - && mCameraCompatFreeformPolicy.shouldCameraCompatControlOrientation( - activity)); + static boolean shouldCameraCompatControlOrientation(@NonNull ActivityRecord activity) { + final AppCompatCameraPolicy cameraPolicy = getAppCompatCameraPolicy(activity); + if (cameraPolicy == null) { + return false; + } + return (cameraPolicy.mDisplayRotationCompatPolicy != null + && cameraPolicy.mDisplayRotationCompatPolicy + .shouldCameraCompatControlOrientation(activity)) + || (cameraPolicy.mCameraCompatFreeformPolicy != null + && cameraPolicy.mCameraCompatFreeformPolicy + .shouldCameraCompatControlOrientation(activity)); } // TODO(b/369070416): have policies implement the same interface. - boolean shouldCameraCompatControlAspectRatio(@NonNull ActivityRecord activity) { - return (mDisplayRotationCompatPolicy != null - && mDisplayRotationCompatPolicy.shouldCameraCompatControlAspectRatio( - activity)) - || (mCameraCompatFreeformPolicy != null - && mCameraCompatFreeformPolicy.shouldCameraCompatControlAspectRatio( - activity)); + static boolean shouldCameraCompatControlAspectRatio(@NonNull ActivityRecord activity) { + final AppCompatCameraPolicy cameraPolicy = getAppCompatCameraPolicy(activity); + if (cameraPolicy == null) { + return false; + } + return (cameraPolicy.mDisplayRotationCompatPolicy != null + && cameraPolicy.mDisplayRotationCompatPolicy + .shouldCameraCompatControlAspectRatio(activity)) + || (cameraPolicy.mCameraCompatFreeformPolicy != null + && cameraPolicy.mCameraCompatFreeformPolicy + .shouldCameraCompatControlAspectRatio(activity)); } // TODO(b/369070416): have policies implement the same interface. @@ -200,40 +211,60 @@ class AppCompatCameraPolicy { * @return {@code true} if the Camera is active for the provided {@link ActivityRecord} and * any camera compat treatment could be triggered for the current windowing mode. */ - private boolean isCameraRunningAndWindowingModeEligible(@NonNull ActivityRecord activity) { - return (mDisplayRotationCompatPolicy != null - && mDisplayRotationCompatPolicy.isCameraRunningAndWindowingModeEligible(activity, - /* mustBeFullscreen */ true)) - || (mCameraCompatFreeformPolicy != null && mCameraCompatFreeformPolicy - .isCameraRunningAndWindowingModeEligible(activity)); + private static boolean isCameraRunningAndWindowingModeEligible( + @NonNull ActivityRecord activity) { + final AppCompatCameraPolicy cameraPolicy = getAppCompatCameraPolicy(activity); + if (cameraPolicy == null) { + return false; + } + return (cameraPolicy.mDisplayRotationCompatPolicy != null + && cameraPolicy.mDisplayRotationCompatPolicy + .isCameraRunningAndWindowingModeEligible(activity, + /* mustBeFullscreen */ true)) + || (cameraPolicy.mCameraCompatFreeformPolicy != null + && cameraPolicy.mCameraCompatFreeformPolicy + .isCameraRunningAndWindowingModeEligible(activity)); } @Nullable String getSummaryForDisplayRotationHistoryRecord() { - if (mDisplayRotationCompatPolicy != null) { - return mDisplayRotationCompatPolicy.getSummaryForDisplayRotationHistoryRecord(); - } - return null; + return mDisplayRotationCompatPolicy != null + ? mDisplayRotationCompatPolicy.getSummaryForDisplayRotationHistoryRecord() + : null; } // TODO(b/369070416): have policies implement the same interface. - float getCameraCompatAspectRatio(@NonNull ActivityRecord activity) { - float displayRotationCompatPolicyAspectRatio = mDisplayRotationCompatPolicy != null - ? mDisplayRotationCompatPolicy.getCameraCompatAspectRatio(activity) + static float getCameraCompatAspectRatio(@NonNull ActivityRecord activity) { + final AppCompatCameraPolicy cameraPolicy = getAppCompatCameraPolicy(activity); + if (cameraPolicy == null) { + return 1.0f; + } + float displayRotationCompatPolicyAspectRatio = + cameraPolicy.mDisplayRotationCompatPolicy != null + ? cameraPolicy.mDisplayRotationCompatPolicy.getCameraCompatAspectRatio(activity) : MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO; - float cameraCompatFreeformPolicyAspectRatio = mCameraCompatFreeformPolicy != null - ? mCameraCompatFreeformPolicy.getCameraCompatAspectRatio(activity) + float cameraCompatFreeformPolicyAspectRatio = + cameraPolicy.mCameraCompatFreeformPolicy != null + ? cameraPolicy.mCameraCompatFreeformPolicy.getCameraCompatAspectRatio(activity) : MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO; return Math.max(displayRotationCompatPolicyAspectRatio, cameraCompatFreeformPolicyAspectRatio); } + @CameraCompatTaskInfo.FreeformCameraCompatMode + static int getCameraCompatFreeformMode(@NonNull ActivityRecord activity) { + final AppCompatCameraPolicy cameraPolicy = getAppCompatCameraPolicy(activity); + return cameraPolicy != null && cameraPolicy.mCameraCompatFreeformPolicy != null + ? cameraPolicy.mCameraCompatFreeformPolicy.getCameraCompatMode(activity) + : CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_NONE; + } + /** * Whether we should apply the min aspect ratio per-app override only when an app is connected * to the camera. */ - boolean shouldOverrideMinAspectRatioForCamera(@NonNull ActivityRecord activityRecord) { - return isCameraRunningAndWindowingModeEligible(activityRecord) + static boolean shouldOverrideMinAspectRatioForCamera(@NonNull ActivityRecord activityRecord) { + return AppCompatCameraPolicy.isCameraRunningAndWindowingModeEligible(activityRecord) && activityRecord.mAppCompatController.getAppCompatCameraOverrides() .isOverrideMinAspectRatioForCameraEnabled(); } diff --git a/services/core/java/com/android/server/wm/AppCompatOrientationOverrides.java b/services/core/java/com/android/server/wm/AppCompatOrientationOverrides.java index bd01351251a5..c84711d4be51 100644 --- a/services/core/java/com/android/server/wm/AppCompatOrientationOverrides.java +++ b/services/core/java/com/android/server/wm/AppCompatOrientationOverrides.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION; @@ -106,6 +107,16 @@ class AppCompatOrientationOverrides { return isChangeEnabled(mActivityRecord, OVERRIDE_RESPECT_REQUESTED_ORIENTATION); } + boolean shouldRespectRequestedOrientationDueToOverride() { + // Checking TaskFragment rather than ActivityRecord to ensure that transition + // between fullscreen and PiP would work well. Checking TaskFragment rather than + // Task to ensure that Activity Embedding is excluded. + return mActivityRecord.isVisibleRequested() && mActivityRecord.getTaskFragment() != null + && mActivityRecord.getTaskFragment().getWindowingMode() == WINDOWING_MODE_FULLSCREEN + && mActivityRecord.mAppCompatController.getAppCompatOrientationOverrides() + .isOverrideRespectRequestedOrientationEnabled(); + } + /** * Whether an app is calling {@link android.app.Activity#setRequestedOrientation} * in a loop and orientation request should be ignored. diff --git a/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java b/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java index 5bd4aeb64b90..f5d58eac1113 100644 --- a/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java +++ b/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java @@ -58,10 +58,8 @@ class AppCompatOrientationPolicy { && displayContent.getIgnoreOrientationRequest(); final boolean shouldApplyUserFullscreenOverride = mAppCompatOverrides .getAppCompatAspectRatioOverrides().shouldApplyUserFullscreenOverride(); - final AppCompatCameraPolicy cameraPolicy = AppCompatCameraPolicy - .getAppCompatCameraPolicy(mActivityRecord); - final boolean shouldCameraCompatControlOrientation = cameraPolicy != null - && cameraPolicy.shouldCameraCompatControlOrientation(mActivityRecord); + final boolean shouldCameraCompatControlOrientation = + AppCompatCameraPolicy.shouldCameraCompatControlOrientation(mActivityRecord); if (shouldApplyUserFullscreenOverride && isIgnoreOrientationRequestEnabled // Do not override orientation to fullscreen for camera activities. // Fixed-orientation activities are rarely tested in other orientations, and it @@ -98,7 +96,7 @@ class AppCompatOrientationPolicy { if (displayContent != null && mAppCompatOverrides.getAppCompatCameraOverrides() .isOverrideOrientationOnlyForCameraEnabled() - && !displayContent.mAppCompatCameraPolicy + && !AppCompatCameraPolicy .isActivityEligibleForOrientationOverride(mActivityRecord)) { return candidate; } @@ -213,5 +211,4 @@ class AppCompatOrientationPolicy { } return false; } - } diff --git a/services/core/java/com/android/server/wm/AppCompatUtils.java b/services/core/java/com/android/server/wm/AppCompatUtils.java index 69421d0d5c96..8d8424820990 100644 --- a/services/core/java/com/android/server/wm/AppCompatUtils.java +++ b/services/core/java/com/android/server/wm/AppCompatUtils.java @@ -185,8 +185,8 @@ final class AppCompatUtils { && aspectRatioOverrides.shouldEnableUserAspectRatioSettings(); appCompatTaskInfo.setEligibleForUserAspectRatioButton(eligibleForAspectRatioButton); appCompatTaskInfo.setTopActivityLetterboxed(top.areBoundsLetterboxed()); - appCompatTaskInfo.cameraCompatTaskInfo.freeformCameraCompatMode = top.mAppCompatController - .getAppCompatCameraOverrides().getFreeformCameraCompatMode(); + appCompatTaskInfo.cameraCompatTaskInfo.freeformCameraCompatMode = + AppCompatCameraPolicy.getCameraCompatFreeformMode(top); appCompatTaskInfo.setHasMinAspectRatioOverride(top.mAppCompatController .getDesktopAppCompatAspectRatioPolicy().hasMinAspectRatioOverride(task)); } diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java index d699af872c7f..4d17ed24e734 100644 --- a/services/core/java/com/android/server/wm/AppTaskImpl.java +++ b/services/core/java/com/android/server/wm/AppTaskImpl.java @@ -160,6 +160,7 @@ class AppTaskImpl extends IAppTask.Stub { Intent intent, String resolvedType, Bundle bOptions) { checkCallerOrSystemOrRoot(); mService.assertPackageMatchesCallingUid(callingPackage); + mService.mAmInternal.addCreatorToken(intent); int callingUser = UserHandle.getCallingUserId(); Task task; diff --git a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java index 1073713cca52..264c8beb44bf 100644 --- a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java +++ b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java @@ -146,7 +146,7 @@ class BackgroundLaunchProcessController { "process bound by foreground uid"); } // Allow if the caller has an activity in any foreground task. - if (checkConfiguration.checkVisibility && hasActivityInVisibleTask + if (checkConfiguration.checkOtherExemptions && hasActivityInVisibleTask && appSwitchState != APP_SWITCH_DISALLOW) { return new BalVerdict(BAL_ALLOW_FOREGROUND, /*background*/ false, "process has activity in foreground task"); diff --git a/services/core/java/com/android/server/wm/CameraCompatFreeformPolicy.java b/services/core/java/com/android/server/wm/CameraCompatFreeformPolicy.java index 4f0cbf9ca6bd..2a0252ab06fd 100644 --- a/services/core/java/com/android/server/wm/CameraCompatFreeformPolicy.java +++ b/services/core/java/com/android/server/wm/CameraCompatFreeformPolicy.java @@ -21,6 +21,8 @@ import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_LANDSCAPE_ import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_NONE; import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_PORTRAIT_DEVICE_IN_LANDSCAPE; import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_PORTRAIT_DEVICE_IN_PORTRAIT; +import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS; +import static android.app.WindowConfiguration.WINDOW_CONFIG_DISPLAY_ROTATION; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; @@ -35,6 +37,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.CameraCompatTaskInfo; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.view.DisplayInfo; @@ -64,8 +67,6 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa @NonNull private final CameraStateMonitor mCameraStateMonitor; - private boolean mIsCameraCompatTreatmentPending = false; - @Nullable private Task mCameraTask; @@ -100,13 +101,27 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa return mIsRunning; } - // Refreshing only when configuration changes after rotation or camera split screen aspect ratio - // treatment is enabled. + // Refreshing only when configuration changes after applying camera compat treatment. @Override public boolean shouldRefreshActivity(@NonNull ActivityRecord activity, @NonNull Configuration newConfig, @NonNull Configuration lastReportedConfig) { - return isTreatmentEnabledForActivity(activity) && mIsCameraCompatTreatmentPending; + return isTreatmentEnabledForActivity(activity, /* shouldCheckOrientation= */ true) + && haveCameraCompatAttributesChanged(newConfig, lastReportedConfig); + } + + private boolean haveCameraCompatAttributesChanged(@NonNull Configuration newConfig, + @NonNull Configuration lastReportedConfig) { + // Camera compat treatment changes the following: + // - Letterboxes app bounds to camera compat aspect ratio in app's requested orientation, + // - Changes display rotation so it matches what the app expects in its chosen orientation, + // - Rotate-and-crop camera feed to match that orientation (this changes iff the display + // rotation changes, so no need to check). + final long diff = newConfig.windowConfiguration.diff(lastReportedConfig.windowConfiguration, + /* compareUndefined= */ true); + final boolean appBoundsChanged = (diff & WINDOW_CONFIG_APP_BOUNDS) != 0; + final boolean displayRotationChanged = (diff & WINDOW_CONFIG_DISPLAY_ROTATION) != 0; + return appBoundsChanged || displayRotationChanged; } /** @@ -132,22 +147,26 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa @Override public void onCameraOpened(@NonNull ActivityRecord cameraActivity, @NonNull String cameraId) { - if (!isTreatmentEnabledForActivity(cameraActivity)) { + // Do not check orientation outside of the config recompute, as the app's orientation intent + // might be obscured by a fullscreen override. Especially for apps which have a camera + // functionality which is not the main focus of the app: while most of the app might work + // well in fullscreen, often the camera setup still assumes it will run on a portrait device + // in its natural orientation and comes out stretched or sideways. + // Config recalculation will later check the original orientation to avoid applying + // treatment to apps optimized for large screens. + if (!isTreatmentEnabledForActivity(cameraActivity, /* shouldCheckOrientation= */ false)) { return; } - final int existingCameraCompatMode = cameraActivity.mAppCompatController - .getAppCompatCameraOverrides() - .getFreeformCameraCompatMode(); - final int newCameraCompatMode = getCameraCompatMode(cameraActivity); - if (newCameraCompatMode != existingCameraCompatMode) { - mIsCameraCompatTreatmentPending = true; - mCameraTask = cameraActivity.getTask(); - cameraActivity.mAppCompatController.getAppCompatCameraOverrides() - .setFreeformCameraCompatMode(newCameraCompatMode); - forceUpdateActivityAndTask(cameraActivity); - } else { - mIsCameraCompatTreatmentPending = false; - } + + cameraActivity.recomputeConfiguration(); + updateCameraCompatMode(cameraActivity); + cameraActivity.getTask().dispatchTaskInfoChangedIfNeeded(/* force= */ true); + cameraActivity.ensureActivityConfiguration(/* ignoreVisibility= */ false); + } + + private void updateCameraCompatMode(@NonNull ActivityRecord cameraActivity) { + cameraActivity.mAppCompatController.getAppCompatCameraOverrides() + .setFreeformCameraCompatMode(getCameraCompatMode(cameraActivity)); } @Override @@ -167,7 +186,6 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa } } mCameraTask = null; - mIsCameraCompatTreatmentPending = false; return true; } @@ -184,13 +202,12 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa // Camera compat should direct aspect ratio when in camera compat mode, unless an app has a // different camera compat aspect ratio set: this allows per-app camera compat override // aspect ratio to be smaller than the default. - return isInCameraCompatMode(activity) && !activity.mAppCompatController + return isInFreeformCameraCompatMode(activity) && !activity.mAppCompatController .getAppCompatCameraOverrides().isOverrideMinAspectRatioForCameraEnabled(); } - private boolean isInCameraCompatMode(@NonNull ActivityRecord activity) { - return activity.mAppCompatController.getAppCompatCameraOverrides() - .getFreeformCameraCompatMode() != CAMERA_COMPAT_FREEFORM_NONE; + boolean isInFreeformCameraCompatMode(@NonNull ActivityRecord activity) { + return getCameraCompatMode(activity) != CAMERA_COMPAT_FREEFORM_NONE; } float getCameraCompatAspectRatio(@NonNull ActivityRecord activityRecord) { @@ -201,16 +218,11 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa return MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO; } - private void forceUpdateActivityAndTask(ActivityRecord cameraActivity) { - cameraActivity.recomputeConfiguration(); - cameraActivity.updateReportedConfigurationAndSend(); - Task cameraTask = cameraActivity.getTask(); - if (cameraTask != null) { - cameraTask.dispatchTaskInfoChangedIfNeeded(/* force= */ true); + @CameraCompatTaskInfo.FreeformCameraCompatMode + int getCameraCompatMode(@NonNull ActivityRecord topActivity) { + if (!isTreatmentEnabledForActivity(topActivity, /* shouldCheckOrientation= */ true)) { + return CAMERA_COMPAT_FREEFORM_NONE; } - } - - private static int getCameraCompatMode(@NonNull ActivityRecord topActivity) { final int appOrientation = topActivity.getRequestedConfigurationOrientation(); // It is very important to check the original (actual) display rotation, and not the // sandboxed rotation that camera compat treatment sets. @@ -250,15 +262,24 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa * <ul> * <li>Treatment is enabled. * <li>Camera is active for the package. - * <li>The app has a fixed orientation. + * <li>The app has a fixed orientation if {@code checkOrientation} is true. * <li>The app is in freeform windowing mode. * </ul> + * + * @param checkOrientation Whether to take apps orientation into account for this check. Only + * fixed-orientation apps should be targeted, but this might be + * obscured by OEMs via fullscreen override and the app's original + * intent inaccessible when the camera opens. Thus, policy would pass + * {@code false} here when considering whether to trigger config + * recalculation, and later pass {@code true} during recalculation. */ - private boolean isTreatmentEnabledForActivity(@NonNull ActivityRecord activity) { + @VisibleForTesting + boolean isTreatmentEnabledForActivity(@NonNull ActivityRecord activity, + boolean checkOrientation) { int orientation = activity.getRequestedConfigurationOrientation(); return isCameraCompatForFreeformEnabledForActivity(activity) && mCameraStateMonitor.isCameraRunningForActivity(activity) - && orientation != ORIENTATION_UNDEFINED + && (!checkOrientation || orientation != ORIENTATION_UNDEFINED) && activity.inFreeformWindowingMode() // "locked" and "nosensor" values are often used by camera apps that can't // handle dynamic changes so we shouldn't force-letterbox them. @@ -270,7 +291,7 @@ final class CameraCompatFreeformPolicy implements CameraStateMonitor.CameraCompa private boolean isActivityForCameraIdRefreshing(@NonNull ActivityRecord topActivity, @NonNull String cameraId) { - if (!isTreatmentEnabledForActivity(topActivity) + if (!isTreatmentEnabledForActivity(topActivity, /* checkOrientation= */ true) || mCameraStateMonitor.isCameraWithIdRunningForActivity(topActivity, cameraId)) { return false; } diff --git a/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java b/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java index 3b2f723fb172..c8cb62132b4c 100644 --- a/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java +++ b/services/core/java/com/android/server/wm/DesktopAppCompatAspectRatioPolicy.java @@ -194,12 +194,8 @@ public class DesktopAppCompatAspectRatioPolicy { return aspectRatioOverrides.getUserMinAspectRatio(); } - final AppCompatCameraPolicy cameraPolicy = AppCompatCameraPolicy.getAppCompatCameraPolicy( - mActivityRecord); - final boolean shouldOverrideMinAspectRatioForCamera = cameraPolicy != null - && cameraPolicy.shouldOverrideMinAspectRatioForCamera(mActivityRecord); if (!aspectRatioOverrides.shouldOverrideMinAspectRatio() - && !shouldOverrideMinAspectRatioForCamera) { + && !AppCompatCameraPolicy.shouldOverrideMinAspectRatioForCamera(mActivityRecord)) { if (mActivityRecord.isUniversalResizeable()) { return 0; } diff --git a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java index 34b5f6a24d41..1a8f5fc46827 100644 --- a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java +++ b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java @@ -30,7 +30,6 @@ import static com.android.server.wm.LaunchParamsUtil.calculateLayoutBounds; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityOptions; -import android.app.TaskInfo; import android.content.pm.ActivityInfo.ScreenOrientation; import android.content.pm.ActivityInfo.WindowLayout; import android.graphics.Rect; @@ -98,7 +97,6 @@ public final class DesktopModeBoundsCalculator { private static Rect calculateInitialBounds(@NonNull Task task, @NonNull ActivityRecord activity, @NonNull Rect stableBounds ) { - final TaskInfo taskInfo = task.getTaskInfo(); // Display bounds not taking into account insets. final TaskDisplayArea displayArea = task.getDisplayArea(); final Rect screenBounds = displayArea.getBounds(); @@ -118,14 +116,15 @@ public final class DesktopModeBoundsCalculator { float appAspectRatio = desktopAppCompatAspectRatioPolicy.calculateAspectRatio(task); final float tdaWidth = stableBounds.width(); final float tdaHeight = stableBounds.height(); + final int taskConfigOrientation = task.getConfiguration().orientation; final int activityOrientation = getActivityOrientation(activity, task); - final Size initialSize = switch (taskInfo.configuration.orientation) { + final Size initialSize = switch (taskConfigOrientation) { case ORIENTATION_LANDSCAPE -> { // Device in landscape orientation. if (appAspectRatio == 0) { appAspectRatio = 1; } - if (canChangeAspectRatio(desktopAppCompatAspectRatioPolicy, taskInfo, task)) { + if (canChangeAspectRatio(desktopAppCompatAspectRatioPolicy, task)) { if (isFixedOrientationPortrait(activityOrientation)) { // For portrait resizeable activities, respect apps fullscreen width but // apply ideal size height. @@ -143,7 +142,7 @@ public final class DesktopModeBoundsCalculator { // Device in portrait orientation. final int customPortraitWidthForLandscapeApp = screenBounds.width() - (DESKTOP_MODE_LANDSCAPE_APP_PADDING * 2); - if (canChangeAspectRatio(desktopAppCompatAspectRatioPolicy, taskInfo, task)) { + if (canChangeAspectRatio(desktopAppCompatAspectRatioPolicy, task)) { if (isFixedOrientationLandscape(activityOrientation)) { if (appAspectRatio == 0) { appAspectRatio = tdaWidth / (tdaWidth - 1); @@ -182,8 +181,8 @@ public final class DesktopModeBoundsCalculator { */ private static boolean canChangeAspectRatio( @NonNull DesktopAppCompatAspectRatioPolicy desktopAppCompatAspectRatioPolicy, - @NonNull TaskInfo taskInfo, @NonNull Task task) { - return taskInfo.isResizeable + @NonNull Task task) { + return task.isResizeable() && !desktopAppCompatAspectRatioPolicy.hasMinAspectRatioOverride(task); } diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java index a74b0063588a..4824c1613f53 100644 --- a/services/core/java/com/android/server/wm/Dimmer.java +++ b/services/core/java/com/android/server/wm/Dimmer.java @@ -21,6 +21,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Rect; import android.util.Log; import android.view.Surface; @@ -128,7 +129,7 @@ class Dimmer { /** * Set the parameters to prepare the dim to be relative parented to the dimming container */ - void prepareReparent(@NonNull WindowContainer<?> geometryParent, + void prepareReparent(@Nullable WindowContainer<?> geometryParent, @NonNull WindowState relativeParent) { mAnimationHelper.setRequestedRelativeParent(relativeParent); mAnimationHelper.setRequestedGeometryParent(geometryParent); @@ -221,7 +222,7 @@ class Dimmer { * @param dimmingContainer The container that is dimming. The dim layer will be rel-z * parented below it */ - public void adjustPosition(@NonNull WindowContainer<?> geometryParent, + public void adjustPosition(@Nullable WindowContainer<?> geometryParent, @NonNull WindowState dimmingContainer) { if (mDimState != null) { mDimState.prepareReparent(geometryParent, dimmingContainer); diff --git a/services/core/java/com/android/server/wm/DimmerAnimationHelper.java b/services/core/java/com/android/server/wm/DimmerAnimationHelper.java index 298edaeaa6d2..3999e03c8a53 100644 --- a/services/core/java/com/android/server/wm/DimmerAnimationHelper.java +++ b/services/core/java/com/android/server/wm/DimmerAnimationHelper.java @@ -108,7 +108,7 @@ public class DimmerAnimationHelper { } // Sets the requested layer to reparent the dim to without applying it immediately - void setRequestedGeometryParent(WindowContainer<?> geometryParent) { + void setRequestedGeometryParent(@Nullable WindowContainer<?> geometryParent) { if (geometryParent != null) { mRequestedProperties.mGeometryParent = geometryParent; } diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index 0416f74aa488..29ffda7537ac 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -16,7 +16,6 @@ package com.android.server.wm; -import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; @@ -260,15 +259,14 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { if (mDisplayContent == null) { return false; } - ActivityRecord activity = mDisplayContent.topRunningActivity( - /* considerKeyguardState= */ true); - return activity != null && activity.getTaskFragment() != null - // Checking TaskFragment rather than ActivityRecord to ensure that transition - // between fullscreen and PiP would work well. Checking TaskFragment rather than - // Task to ensure that Activity Embedding is excluded. - && activity.getTaskFragment().getWindowingMode() == WINDOWING_MODE_FULLSCREEN - && activity.mAppCompatController.getAppCompatOrientationOverrides() - .isOverrideRespectRequestedOrientationEnabled(); + + // Top running activity can be freeform and ignore orientation request from bottom activity + // that should be respected, Check all activities in display to make sure any eligible + // activity should be respected. + final ActivityRecord activity = mDisplayContent.getActivity((r) -> + r.mAppCompatController.getAppCompatOrientationOverrides() + .shouldRespectRequestedOrientationDueToOverride()); + return activity != null; } boolean getIgnoreOrientationRequest() { diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index c062f5adf755..04a625b4a237 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -79,6 +79,7 @@ import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.L import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.window.flags.Flags.enableFullyImmersiveInDesktop; import android.annotation.NonNull; import android.annotation.Nullable; @@ -2515,10 +2516,16 @@ public class DisplayPolicy { defaultTaskDisplayArea.getRootTask(task -> task.isVisible() && task.getTopLeafTask().getAdjacentTask() != null) != null; - final boolean freeformRootTaskVisible = - defaultTaskDisplayArea.isRootTaskVisible(WINDOWING_MODE_FREEFORM); - - getInsetsPolicy().updateSystemBars(win, adjacentTasksVisible, freeformRootTaskVisible); + final Task topFreeformTask = defaultTaskDisplayArea + .getTopRootTaskInWindowingMode(WINDOWING_MODE_FREEFORM); + final boolean freeformRootTaskVisible = topFreeformTask != null + && topFreeformTask.isVisible(); + final boolean inNonFullscreenFreeformMode = freeformRootTaskVisible + && !topFreeformTask.getBounds().equals(mDisplayContent.getBounds()); + + getInsetsPolicy().updateSystemBars(win, adjacentTasksVisible, + enableFullyImmersiveInDesktop() + ? inNonFullscreenFreeformMode : freeformRootTaskVisible); final boolean topAppHidesStatusBar = topAppHidesSystemBar(Type.statusBars()); if (getStatusBar() != null) { diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index b414a862f874..24a6f118ad04 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -47,6 +47,7 @@ import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsAnimation; import android.view.WindowInsetsAnimation.Bounds; import android.view.WindowManager; +import android.view.inputmethod.Flags; import android.view.inputmethod.ImeTracker; import android.view.inputmethod.InputMethodManager; @@ -412,6 +413,22 @@ class InsetsPolicy { state.addSource(imeSource); return state; } + } else if (Flags.refactorInsetsController() + && (w.mMergedExcludeInsetsTypes & WindowInsets.Type.ime()) != 0) { + // In some cases (e.g. split screen from when the IME was requested and the animation + // actually starts) the insets should not be send, unless the flag is unset. + final InsetsSource originalImeSource = originalState.peekSource(ID_IME); + if (originalImeSource != null && originalImeSource.isVisible()) { + final InsetsState state = copyState + ? new InsetsState(originalState) + : originalState; + final InsetsSource imeSource = new InsetsSource(originalImeSource); + // Setting the height to zero, pretending we're in floating mode + imeSource.setFrame(0, 0, 0, 0); + imeSource.setVisibleFrame(imeSource.getFrame()); + state.addSource(imeSource); + return state; + } } return originalState; } @@ -611,8 +628,9 @@ class InsetsPolicy { return (mForcedShowingTypes & types) == types; } - void updateSystemBars(WindowState win, boolean inSplitScreenMode, boolean inFreeformMode) { - mForcedShowingTypes = (inSplitScreenMode || inFreeformMode) + void updateSystemBars(WindowState win, boolean inSplitScreenMode, + boolean inNonFullscreenFreeformMode) { + mForcedShowingTypes = (inSplitScreenMode || inNonFullscreenFreeformMode) ? (Type.statusBars() | Type.navigationBars()) : forceShowingNavigationBars(win) ? Type.navigationBars() diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index ede587c9e64b..5dddf36a8d8b 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -458,6 +458,12 @@ class InsetsStateController { mDisplayContent.notifyInsetsChanged(mDispatchInsetsChanged); } + void notifyInsetsChanged(ArraySet<WindowState> changedWindows) { + for (int i = changedWindows.size() - 1; i >= 0; i--) { + mDispatchInsetsChanged.accept(changedWindows.valueAt(i)); + } + } + /** * Checks if the control target has pending controls. * diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java index 252590e0b696..ca47133a0674 100644 --- a/services/core/java/com/android/server/wm/Letterbox.java +++ b/services/core/java/com/android/server/wm/Letterbox.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; import static android.view.SurfaceControl.HIDDEN; import static android.window.TaskConstants.TASK_CHILD_LAYER_LETTERBOX_BACKGROUND; +import static android.window.TaskConstants.TASK_CHILD_LAYER_TASK_OVERLAY; import android.annotation.NonNull; import android.graphics.Color; @@ -37,6 +38,7 @@ import android.view.SurfaceControl; import android.view.WindowManager; import com.android.server.UiThread; +import com.android.window.flags.Flags; import java.util.function.Supplier; @@ -66,6 +68,7 @@ public class Letterbox { // for overlaping an app window and letterbox surfaces. private final LetterboxSurface mFullWindowSurface = new LetterboxSurface("fullWindow"); private final LetterboxSurface[] mSurfaces = { mLeft, mTop, mRight, mBottom }; + @NonNull private final AppCompatReachabilityPolicy mAppCompatReachabilityPolicy; @NonNull @@ -222,12 +225,14 @@ public class Letterbox { void onMovedToDisplay(int displayId) { for (LetterboxSurface surface : mSurfaces) { - if (surface.mInputInterceptor != null) { - surface.mInputInterceptor.mWindowHandle.displayId = displayId; - } + setSurfaceDisplayID(surface, displayId); } - if (mFullWindowSurface.mInputInterceptor != null) { - mFullWindowSurface.mInputInterceptor.mWindowHandle.displayId = displayId; + setSurfaceDisplayID(mFullWindowSurface, displayId); + } + + private void setSurfaceDisplayID(LetterboxSurface surface, int displayId) { + if (surface.mInputInterceptor != null) { + surface.mInputInterceptor.mWindowHandle.displayId = displayId; } } @@ -242,14 +247,13 @@ public class Letterbox { private final class TapEventReceiver extends InputEventReceiver { private final GestureDetector mDoubleTapDetector; - private final DoubleTapListener mDoubleTapListener; TapEventReceiver(InputChannel inputChannel, WindowManagerService wmService, Handler uiHandler) { super(inputChannel, uiHandler.getLooper()); - mDoubleTapListener = new DoubleTapListener(wmService); - mDoubleTapDetector = new GestureDetector(wmService.mContext, mDoubleTapListener, - uiHandler); + final DoubleTapListener doubleTapListener = new DoubleTapListener(wmService); + mDoubleTapDetector = + new GestureDetector(wmService.mContext, doubleTapListener, uiHandler); } @Override @@ -293,7 +297,8 @@ public class Letterbox { InputInterceptor(String namePrefix, WindowState win) { mWmService = win.mWmService; mHandler = UiThread.getHandler(); - final String name = namePrefix + (win.mActivityRecord != null ? win.mActivityRecord : win); + final String name = namePrefix + + (win.mActivityRecord != null ? win.mActivityRecord : win); mClientChannel = mWmService.mInputManager.createInputChannel(name); mInputEventReceiver = new TapEventReceiver(mClientChannel, mWmService, mHandler); @@ -303,12 +308,15 @@ public class Letterbox { win.getDisplayId()); mWindowHandle.name = name; mWindowHandle.token = mToken; - mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; + mWindowHandle.layoutParamsType = Flags.scrollingFromLetterbox() + ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY + : WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; mWindowHandle.ownerPid = WindowManagerService.MY_PID; mWindowHandle.ownerUid = WindowManagerService.MY_UID; mWindowHandle.scaleFactor = 1.0f; - mWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE | InputConfig.SLIPPERY; + mWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE + | (Flags.scrollingFromLetterbox() ? InputConfig.SPY : InputConfig.SLIPPERY); } void updateTouchableRegion(Rect frame) { @@ -341,6 +349,7 @@ public class Letterbox { private final String mType; private SurfaceControl mSurface; + private SurfaceControl mInputSurface; private Color mColor; private boolean mHasWallpaperBackground; private SurfaceControl mParentSurface; @@ -373,22 +382,36 @@ public class Letterbox { .setColorSpaceAgnostic(mSurface, true); } + private void createInputSurface(SurfaceControl.Transaction t) { + mInputSurface = mSurfaceControlFactory.get() + .setName("LetterboxInput - " + mType) + .setFlags(HIDDEN) + .setContainerLayer() + .setOpaque(true) + .setCallsite("LetterboxSurface.createInputSurface") + .build(); + + t.setLayer(mInputSurface, TASK_CHILD_LAYER_TASK_OVERLAY); + } + void attachInput(WindowState win) { if (mInputInterceptor != null) { mInputInterceptor.dispose(); } + // TODO(b/371179559): only detect double tap on LB surfaces not used for cutout area. + // Potentially, the input interceptor may still be needed for slippery feature. mInputInterceptor = new InputInterceptor("Letterbox_" + mType + "_", win); } - boolean isRemoved() { - return mSurface != null || mInputInterceptor != null; - } - public void remove() { if (mSurface != null) { mTransactionFactory.get().remove(mSurface).apply(); mSurface = null; } + if (mInputSurface != null) { + mTransactionFactory.get().remove(mInputSurface).apply(); + mInputSurface = null; + } if (mInputInterceptor != null) { mInputInterceptor.dispose(); mInputInterceptor = null; @@ -415,28 +438,54 @@ public class Letterbox { createSurface(t); } + if (Flags.scrollingFromLetterbox() + && mInputInterceptor != null + && mInputSurface == null) { + createInputSurface(inputT); + } + mColor = mAppCompatLetterboxOverrides.getLetterboxBackgroundColor(); mParentSurface = mParentSurfaceSupplier.get(); t.setColor(mSurface, getRgbColorArray()); - t.setPosition(mSurface, mSurfaceFrameRelative.left, mSurfaceFrameRelative.top); - t.setWindowCrop(mSurface, mSurfaceFrameRelative.width(), - mSurfaceFrameRelative.height()); - t.reparent(mSurface, mParentSurface); + setPositionAndReparent(t, mSurface); mHasWallpaperBackground = mAppCompatLetterboxOverrides .hasWallpaperBackgroundForLetterbox(); updateAlphaAndBlur(t); t.show(mSurface); - } else if (mSurface != null) { - t.hide(mSurface); + + if (mInputSurface != null) { + setPositionAndReparent(inputT, mInputSurface); + inputT.setTrustedOverlay(mInputSurface, true); + inputT.show(mInputSurface); + } + + } else { + if (mSurface != null) { + t.hide(mSurface); + } + if (mInputSurface != null) { + inputT.hide(mInputSurface); + } } - if (mSurface != null && mInputInterceptor != null) { + + SurfaceControl surfaceWithInput = + Flags.scrollingFromLetterbox() ? mInputSurface : mSurface; + if (surfaceWithInput != null && mInputInterceptor != null) { mInputInterceptor.updateTouchableRegion(mSurfaceFrameRelative); - inputT.setInputWindowInfo(mSurface, mInputInterceptor.mWindowHandle); + inputT.setInputWindowInfo(surfaceWithInput, mInputInterceptor.mWindowHandle); } } + private void setPositionAndReparent(@NonNull SurfaceControl.Transaction t, + @NonNull SurfaceControl surface) { + t.setPosition(surface, mSurfaceFrameRelative.left, mSurfaceFrameRelative.top); + t.setWindowCrop(surface, mSurfaceFrameRelative.width(), + mSurfaceFrameRelative.height()); + t.reparent(surface, mParentSurface); + } + private void updateAlphaAndBlur(SurfaceControl.Transaction t) { if (!mHasWallpaperBackground) { // Opaque diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java index b6e4c118e51a..9de96f1440a2 100644 --- a/services/core/java/com/android/server/wm/RecentTasks.java +++ b/services/core/java/com/android/server/wm/RecentTasks.java @@ -551,6 +551,12 @@ class RecentTasks { long currentElapsedTime = SystemClock.elapsedRealtime(); for (int i = 0; i < tasks.size(); i++) { Task task = tasks.get(i); + // Remove the task restored from xml if any existing tasks match. + if (findRemoveIndexForAddTask(task) >= 0) { + tasks.remove(i); + i--; + continue; + } task.lastActiveTime = currentElapsedTime - i; } @@ -561,6 +567,7 @@ class RecentTasks { if (existedTaskIds.size() > 0) { syncPersistentTaskIdsLocked(); } + mTaskNotificationController.notifyTaskListUpdated(); } private boolean isRecentTasksLoaded(int userId) { @@ -679,27 +686,35 @@ class RecentTasks { if (isRecentTasksLoaded(userId)) { Slog.i(TAG, "Unloading recents for user " + userId + " from memory."); mUsersWithRecentsLoaded.delete(userId); - removeTasksForUserLocked(userId); + removeTasksForUserFromMemoryLocked(userId); } mPersistedTaskIds.delete(userId); mTaskPersister.unloadUserDataFromMemory(userId); } /** Remove recent tasks for a user. */ - private void removeTasksForUserLocked(int userId) { + private void removeTasksForUserFromMemoryLocked(int userId) { if (userId <= 0) { Slog.i(TAG, "Can't remove recent task on user " + userId); return; } + boolean notifyTaskUpdated = false; for (int i = mTasks.size() - 1; i >= 0; --i) { Task task = mTasks.get(i); if (task.mUserId == userId) { ProtoLog.i(WM_DEBUG_TASKS, "remove RecentTask %s when finishing user " + "%d", task, userId); - remove(task); + mTasks.remove(task); + mService.mWindowManager.mSnapshotController.mTaskSnapshotController + .removeSnapshotCache(task.mTaskId); + // Only notify if list has changed. + notifyTaskUpdated = true; } } + if (notifyTaskUpdated) { + mTaskNotificationController.notifyTaskListUpdated(); + } } void onPackagesSuspendedChanged(String[] packages, boolean suspended, int userId) { diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 188b368c47c5..1659f7bc6eed 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -1753,7 +1753,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } } - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) static boolean containsChangeFor(WindowContainer wc, ArrayList<ChangeInfo> list) { for (int i = list.size() - 1; i >= 0; --i) { if (list.get(i).mContainer == wc) return true; diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index b7fe32713100..87bdfa4f5d75 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -471,6 +471,16 @@ class TransitionController { return false; } + /** Returns {@code true} if the `wc` is a target of a playing transition. */ + boolean isPlayingTarget(@NonNull WindowContainer<?> wc) { + for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) { + if (Transition.containsChangeFor(wc, mPlayingTransitions.get(i).mTargets)) { + return true; + } + } + return false; + } + /** Returns {@code true} if the finishing transition contains `wc`. */ boolean inFinishingTransition(WindowContainer<?> wc) { return mFinishingTransition != null && mFinishingTransition.isInTransition(wc); diff --git a/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java b/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java index 8e32813f7ecc..242883612124 100644 --- a/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java +++ b/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java @@ -156,7 +156,7 @@ public class TrustedPresentationListenerController { Listeners mRegisteredListeners = new Listeners(); - private InputWindowHandle[] mLastWindowHandles; + private Pair<InputWindowHandle[], WindowInfosListener.DisplayInfo[]> mLastWindowHandles; private void startHandlerThreadIfNeeded() { synchronized (mHandlerThreadLock) { @@ -222,10 +222,10 @@ public class TrustedPresentationListenerController { @Override public void onWindowInfosChanged(InputWindowHandle[] windowHandles, DisplayInfo[] displayInfos) { - mHandler.post(() -> computeTpl(windowHandles)); + mHandler.post(() -> computeTpl(new Pair<>(windowHandles, displayInfos))); } }; - mLastWindowHandles = mWindowInfosListener.register().first; + mLastWindowHandles = mWindowInfosListener.register(); } private void unregisterWindowInfosListener() { @@ -238,28 +238,52 @@ public class TrustedPresentationListenerController { mLastWindowHandles = null; } - private void computeTpl(InputWindowHandle[] windowHandles) { + private void computeTpl( + Pair<InputWindowHandle[], WindowInfosListener.DisplayInfo[]> windowHandles) { mLastWindowHandles = windowHandles; - if (mLastWindowHandles == null || mLastWindowHandles.length == 0 + if (mLastWindowHandles == null || mLastWindowHandles.first.length == 0 || mRegisteredListeners.isEmpty()) { return; } Rect tmpRect = new Rect(); + RectF tmpRectF = new RectF(); + Rect tmpLogicalDisplaySize = new Rect(); Matrix tmpInverseMatrix = new Matrix(); float[] tmpMatrix = new float[9]; Region coveredRegionsAbove = new Region(); long currTimeMs = System.currentTimeMillis(); - ProtoLog.v(WM_DEBUG_TPL, "Checking %d windows", mLastWindowHandles.length); + ProtoLog.v(WM_DEBUG_TPL, "Checking %d windows", mLastWindowHandles.first.length); ArrayMap<ITrustedPresentationListener, Pair<IntArray, IntArray>> listenerUpdates = new ArrayMap<>(); - for (var windowHandle : mLastWindowHandles) { + for (var windowHandle : mLastWindowHandles.first) { if (!windowHandle.canOccludePresentation) { ProtoLog.v(WM_DEBUG_TPL, "Skipping %s", windowHandle.name); continue; } - tmpRect.set(windowHandle.frame); + var displayFound = false; + tmpRectF.set(windowHandle.frame); + for (var displayHandle : mLastWindowHandles.second) { + if (displayHandle.mDisplayId == windowHandle.displayId) { + // Transform the window frame into display logical space and then + // crop by the logical display size + displayHandle.mTransform.mapRect(tmpRectF); + tmpRectF.round(tmpRect); + tmpLogicalDisplaySize.set(0, 0, displayHandle.mLogicalSize.getWidth(), + displayHandle.mLogicalSize.getHeight()); + tmpRect.intersect(tmpLogicalDisplaySize); + displayFound = true; + break; + } + } + + if (!displayFound) { + ProtoLog.v(WM_DEBUG_TPL, "Skipping %s, no associated display %d", windowHandle.name, + windowHandle.displayId); + continue; + } + var listeners = mRegisteredListeners.get(windowHandle.getWindowToken()); if (listeners != null) { Region region = new Region(); diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index da64a5f07aeb..af57c8422881 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -32,6 +32,7 @@ import static android.content.res.Configuration.ORIENTATION_UNDEFINED; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.os.UserHandle.USER_NULL; import static android.view.SurfaceControl.Transaction; +import static android.view.WindowInsets.Type.InsetsType; import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.window.TaskFragmentAnimationParams.DEFAULT_ANIMATION_BACKGROUND_COLOR; @@ -173,6 +174,13 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< */ protected SparseArray<InsetsSourceProvider> mInsetsSourceProviders = null; + /** + * The combined excluded insets types (combined mExcludeInsetsTypes and the + * mMergedExcludeInsetsTypes from its parent) + */ + protected @InsetsType int mMergedExcludeInsetsTypes = 0; + private @InsetsType int mExcludeInsetsTypes = 0; + @Nullable private ArrayMap<IBinder, DeathRecipient> mInsetsOwnerDeathRecipientMap; @@ -555,6 +563,49 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< return mControllableInsetProvider; } + /** + * Sets the excludeInsetsTypes of this window and updates the mMergedExcludeInsetsTypes of + * all child nodes in the hierarchy. + * + * @param excludeInsetsTypes the excluded {@link InsetsType} that should be set on this + * WindowContainer + */ + void setExcludeInsetsTypes(@InsetsType int excludeInsetsTypes) { + if (excludeInsetsTypes == mExcludeInsetsTypes) { + return; + } + mExcludeInsetsTypes = excludeInsetsTypes; + mergeExcludeInsetsTypesAndNotifyInsetsChanged( + mParent != null ? mParent.mMergedExcludeInsetsTypes : 0); + } + + private void mergeExcludeInsetsTypesAndNotifyInsetsChanged( + @InsetsType int excludeInsetsTypesFromParent) { + final ArraySet<WindowState> changedWindows = new ArraySet<>(); + updateMergedExcludeInsetsTypes(excludeInsetsTypesFromParent, changedWindows); + if (getDisplayContent() != null) { + getDisplayContent().getInsetsStateController().notifyInsetsChanged(changedWindows); + } + } + + private void updateMergedExcludeInsetsTypes( + @InsetsType int excludeInsetsTypesFromParent, ArraySet<WindowState> changedWindows) { + final int newMergedExcludeInsetsTypes = mExcludeInsetsTypes | excludeInsetsTypesFromParent; + if (newMergedExcludeInsetsTypes == mMergedExcludeInsetsTypes) { + return; + } + mMergedExcludeInsetsTypes = newMergedExcludeInsetsTypes; + + final WindowState win = asWindowState(); + if (win != null) { + changedWindows.add(win); + } + // Apply to all children + for (int i = mChildren.size() - 1; i >= 0; i--) { + final WindowContainer<?> child = mChildren.get(i); + child.updateMergedExcludeInsetsTypes(mMergedExcludeInsetsTypes, changedWindows); + } + } @Override final protected WindowContainer getParent() { @@ -653,6 +704,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) { super.onParentChanged(newParent, oldParent); if (mParent == null) { + mergeExcludeInsetsTypesAndNotifyInsetsChanged(0); return; } @@ -667,6 +719,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< // new parent. reparentSurfaceControl(getSyncTransaction(), mParent.mSurfaceControl); } + mergeExcludeInsetsTypesAndNotifyInsetsChanged(mParent.mMergedExcludeInsetsTypes); // Either way we need to ask the parent to assign us a Z-order. mParent.assignChildLayers(); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index e1e471479393..f4ad0307d24b 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2109,7 +2109,7 @@ public class WindowManagerService extends IWindowManager.Stub ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Removing %s from %s", win, token); // Window will already be removed from token before this post clean-up method is called. if (token.isEmpty() && !token.mPersistOnEmpty) { - token.removeImmediately(); + token.removeIfPossible(); } if (win.mActivityRecord != null) { @@ -6810,30 +6810,36 @@ public class WindowManagerService extends IWindowManager.Stub * @param logLevel Determines the amount of data to be written to the Protobuf. */ void dumpDebugLocked(ProtoOutputStream proto, @WindowTracingLogLevel int logLevel) { - mPolicy.dumpDebug(proto, POLICY); - mRoot.dumpDebug(proto, ROOT_WINDOW_CONTAINER, logLevel); - final DisplayContent topFocusedDisplayContent = mRoot.getTopFocusedDisplayContent(); - if (topFocusedDisplayContent.mCurrentFocus != null) { - topFocusedDisplayContent.mCurrentFocus.writeIdentifierToProto(proto, FOCUSED_WINDOW); - } - if (topFocusedDisplayContent.mFocusedApp != null) { - topFocusedDisplayContent.mFocusedApp.writeNameToProto(proto, FOCUSED_APP); - } - final WindowState imeWindow = mRoot.getCurrentInputMethodWindow(); - if (imeWindow != null) { - imeWindow.writeIdentifierToProto(proto, INPUT_METHOD_WINDOW); - } - proto.write(DISPLAY_FROZEN, mDisplayFrozen); - proto.write(FOCUSED_DISPLAY_ID, topFocusedDisplayContent.getDisplayId()); - proto.write(HARD_KEYBOARD_AVAILABLE, mHardKeyboardAvailable); - - // This is always true for now since we still update the window frames at the server side. - // Once we move the window layout to the client side, this can be false when we are waiting - // for the frames. - proto.write(WINDOW_FRAMES_VALID, true); - - // Write the BackNavigationController's state into the protocol buffer - mAtmService.mBackNavigationController.dumpDebug(proto, BACK_NAVIGATION); + Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "dumpDebugLocked"); + try { + mPolicy.dumpDebug(proto, POLICY); + mRoot.dumpDebug(proto, ROOT_WINDOW_CONTAINER, logLevel); + final DisplayContent topFocusedDisplayContent = mRoot.getTopFocusedDisplayContent(); + if (topFocusedDisplayContent.mCurrentFocus != null) { + topFocusedDisplayContent.mCurrentFocus + .writeIdentifierToProto(proto, FOCUSED_WINDOW); + } + if (topFocusedDisplayContent.mFocusedApp != null) { + topFocusedDisplayContent.mFocusedApp.writeNameToProto(proto, FOCUSED_APP); + } + final WindowState imeWindow = mRoot.getCurrentInputMethodWindow(); + if (imeWindow != null) { + imeWindow.writeIdentifierToProto(proto, INPUT_METHOD_WINDOW); + } + proto.write(DISPLAY_FROZEN, mDisplayFrozen); + proto.write(FOCUSED_DISPLAY_ID, topFocusedDisplayContent.getDisplayId()); + proto.write(HARD_KEYBOARD_AVAILABLE, mHardKeyboardAvailable); + + // This is always true for now since we still update the window frames at the server + // side. Once we move the window layout to the client side, this can be false when we + // are waiting for the frames. + proto.write(WINDOW_FRAMES_VALID, true); + + // Write the BackNavigationController's state into the protocol buffer + mAtmService.mBackNavigationController.dumpDebug(proto, BACK_NAVIGATION); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); + } } private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 09a2bf9647e9..f8d0bc252b0f 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -67,6 +67,7 @@ import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP; +import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT; @@ -1449,6 +1450,16 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } break; } + case HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES: { + final WindowContainer container = WindowContainer.fromBinder(hop.getContainer()); + if (container == null) { + Slog.e(TAG, "Attempt to operate on unknown or detached container: " + + container); + break; + } + container.setExcludeInsetsTypes(hop.getExcludeInsetsTypes()); + break; + } } return effects; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 08789122c607..76f2437cbc3f 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2777,6 +2777,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } if (mTmpRect.isEmpty()) { + // TODO(b/371182877) If the app does not draw under cutout region, the touchable region + // should not include cutout regions (if scrolling from letterbox feature is not desired + // for this region). final Rect transformedBounds = mActivityRecord.getFixedRotationTransformDisplayBounds(); if (transformedBounds != null) { // Task is in the same orientation as display, so the rotated bounds should be @@ -5215,7 +5218,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // but not window manager visible (!isVisibleNow()), it can still be the parent of the // dim, but can not create a new surface or continue a dim alone. Dimmer dimmer; - WindowContainer<?> geometryParent = task; + WindowContainer<?> geometryParent = null; if (Flags.useTasksDimOnly()) { geometryParent = getDimParent(); dimmer = getDimController(); diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 7e7ca12cd44e..5bde8b5a507c 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -90,6 +90,9 @@ class WindowToken extends WindowContainer<WindowState> { // Is key dispatching paused for this token? boolean paused = false; + /** Whether this container should be removed when it no longer animates. */ + boolean mIsExiting; + /** The owner has {@link android.Manifest.permission#MANAGE_APP_TOKENS} */ final boolean mOwnerCanManageAppTokens; @@ -276,6 +279,28 @@ class WindowToken extends WindowContainer<WindowState> { } } + @Override + void removeIfPossible() { + if (mTransitionController.isPlayingTarget(this)) { + // Defer removing this container until the transition is finished. So the removal can + // execute after the finish transaction (see Transition#buildFinishTransaction) which + // may reparent it to original parent. + mIsExiting = true; + return; + } + mIsExiting = false; + removeAllWindowsIfPossible(); + removeImmediately(); + } + + @Override + boolean handleCompleteDeferredRemoval() { + if (mIsExiting) { + removeIfPossible(); + } + return super.handleCompleteDeferredRemoval(); + } + /** * @return The scale for applications running in compatibility mode. Multiply the size in the * application by this scale will be the size in the screen. @@ -725,6 +750,9 @@ class WindowToken extends WindowContainer<WindowState> { pw.print("fixedRotationConfig="); pw.println(mFixedRotationTransformState.mRotatedOverrideConfiguration); } + if (mIsExiting) { + pw.print(prefix); pw.println("isExiting=true"); + } } @Override diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java index fe267261b9e6..68834370c191 100644 --- a/services/core/java/com/android/server/wm/WindowTracing.java +++ b/services/core/java/com/android/server/wm/WindowTracing.java @@ -167,12 +167,7 @@ abstract class WindowTracing { long token = os.start(WINDOW_MANAGER_SERVICE); synchronized (mGlobalLock) { - Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "dumpDebugLocked"); - try { - mService.dumpDebugLocked(os, logLevel); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); - } + mService.dumpDebugLocked(os, logLevel); } os.end(token); } catch (Exception e) { diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp index 39c0c3ef1847..bcd0b94b6877 100644 --- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp +++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp @@ -41,8 +41,8 @@ namespace android { static JavaVM* sJvm = nullptr; static jmethodID sMethodIdOnComplete; -static jclass sFrequencyProfileClass; -static jmethodID sFrequencyProfileCtor; +static jclass sFrequencyProfileLegacyClass; +static jmethodID sFrequencyProfileLegacyCtor; static struct { jmethodID setCapabilities; jmethodID setSupportedEffects; @@ -53,7 +53,7 @@ static struct { jmethodID setPrimitiveDelayMax; jmethodID setCompositionSizeMax; jmethodID setQFactor; - jmethodID setFrequencyProfile; + jmethodID setFrequencyProfileLegacy; jmethodID setMaxEnvelopeEffectSize; jmethodID setMinEnvelopeEffectControlPointDurationMillis; jmethodID setMaxEnvelopeEffectControlPointDurationMillis; @@ -517,11 +517,12 @@ static jboolean vibratorGetInfo(JNIEnv* env, jclass /* clazz */, jlong ptr, env->SetFloatArrayRegion(maxAmplitudes, 0, amplitudes.size(), reinterpret_cast<jfloat*>(amplitudes.data())); } - jobject frequencyProfile = - env->NewObject(sFrequencyProfileClass, sFrequencyProfileCtor, resonantFrequency, - minFrequency, frequencyResolution, maxAmplitudes); - env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setFrequencyProfile, - frequencyProfile); + jobject frequencyProfileLegacy = + env->NewObject(sFrequencyProfileLegacyClass, sFrequencyProfileLegacyCtor, + resonantFrequency, minFrequency, frequencyResolution, maxAmplitudes); + env->CallObjectMethod(vibratorInfoBuilder, + sVibratorInfoBuilderClassInfo.setFrequencyProfileLegacy, + frequencyProfileLegacy); return info.shouldRetry() ? JNI_FALSE : JNI_TRUE; } @@ -566,9 +567,12 @@ int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env sRampClassInfo.endFrequencyHz = GetFieldIDOrDie(env, rampClass, "mEndFrequencyHz", "F"); sRampClassInfo.duration = GetFieldIDOrDie(env, rampClass, "mDuration", "I"); - jclass frequencyProfileClass = FindClassOrDie(env, "android/os/VibratorInfo$FrequencyProfile"); - sFrequencyProfileClass = static_cast<jclass>(env->NewGlobalRef(frequencyProfileClass)); - sFrequencyProfileCtor = GetMethodIDOrDie(env, sFrequencyProfileClass, "<init>", "(FFF[F)V"); + jclass frequencyProfileLegacyClass = + FindClassOrDie(env, "android/os/VibratorInfo$FrequencyProfileLegacy"); + sFrequencyProfileLegacyClass = + static_cast<jclass>(env->NewGlobalRef(frequencyProfileLegacyClass)); + sFrequencyProfileLegacyCtor = + GetMethodIDOrDie(env, sFrequencyProfileLegacyClass, "<init>", "(FFF[F)V"); jclass vibratorInfoBuilderClass = FindClassOrDie(env, "android/os/VibratorInfo$Builder"); sVibratorInfoBuilderClassInfo.setCapabilities = @@ -598,9 +602,9 @@ int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env sVibratorInfoBuilderClassInfo.setQFactor = GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setQFactor", "(F)Landroid/os/VibratorInfo$Builder;"); - sVibratorInfoBuilderClassInfo.setFrequencyProfile = - GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setFrequencyProfile", - "(Landroid/os/VibratorInfo$FrequencyProfile;)" + sVibratorInfoBuilderClassInfo.setFrequencyProfileLegacy = + GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setFrequencyProfileLegacy", + "(Landroid/os/VibratorInfo$FrequencyProfileLegacy;)" "Landroid/os/VibratorInfo$Builder;"); sVibratorInfoBuilderClassInfo.setMaxEnvelopeEffectSize = GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setMaxEnvelopeEffectSize", diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd index a07facf79423..776de2e52061 100644 --- a/services/core/xsd/display-device-config/display-device-config.xsd +++ b/services/core/xsd/display-device-config/display-device-config.xsd @@ -712,6 +712,12 @@ minOccurs="0" maxOccurs="unbounded"> <xs:annotation name="final"/> </xs:element> + <!-- The time after which the stylus is to be assumed to be not under use. This will + enable the logic of changing the brightness with ambient light changes --> + <xs:element name="idleStylusTimeoutMillis" type="xs:nonNegativeInteger" + minOccurs="0" maxOccurs="1"> + <xs:annotation name="final"/> + </xs:element> </xs:sequence> </xs:complexType> diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt index 5309263ed87c..110a5a20da6a 100644 --- a/services/core/xsd/display-device-config/schema/current.txt +++ b/services/core/xsd/display-device-config/schema/current.txt @@ -8,12 +8,14 @@ package com.android.server.display.config { method public final java.math.BigInteger getDarkeningLightDebounceIdleMillis(); method public final java.math.BigInteger getDarkeningLightDebounceMillis(); method public boolean getEnabled(); + method public final java.math.BigInteger getIdleStylusTimeoutMillis(); method public final java.util.List<com.android.server.display.config.LuxToBrightnessMapping> getLuxToBrightnessMapping(); method public final void setBrighteningLightDebounceIdleMillis(java.math.BigInteger); method public final void setBrighteningLightDebounceMillis(java.math.BigInteger); method public final void setDarkeningLightDebounceIdleMillis(java.math.BigInteger); method public final void setDarkeningLightDebounceMillis(java.math.BigInteger); method public void setEnabled(boolean); + method public final void setIdleStylusTimeoutMillis(java.math.BigInteger); } public enum AutoBrightnessModeName { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 4e89b85305d1..2be999fc84e0 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -8031,8 +8031,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { "DevicePolicyManager.wipeDataWithReason() from %s, organization-owned? %s", adminName, calledByProfileOwnerOnOrgOwnedDevice); - wipeDataNoLock(adminComp, flags, internalReason, wipeReasonForUser, userId, - calledOnParentInstance, factoryReset); + wipeDataNoLock(adminComp, flags, internalReason, wipeReasonForUser, userId, factoryReset); } private String getGenericWipeReason( @@ -8188,17 +8187,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * factory reset */ private void wipeDataNoLock(@Nullable ComponentName admin, int flags, String internalReason, - String wipeReasonForUser, int userId, boolean calledOnParentInstance, - @Nullable Boolean factoryReset) { + String wipeReasonForUser, int userId, @Nullable Boolean factoryReset) { wtfIfInLock(); final String adminPackage; if (admin != null) { adminPackage = admin.getPackageName(); } else { - int callerId = mInjector.binderGetCallingUid(); - String[] adminPackages = mInjector.getPackageManager().getPackagesForUid(callerId); + int callerUid = mInjector.binderGetCallingUid(); + String[] adminPackages = mInjector.getPackageManager().getPackagesForUid(callerUid); Preconditions.checkState(adminPackages.length > 0, - "Caller %s does not have any associated packages", callerId); + "Caller %s does not have any associated packages", callerUid); adminPackage = adminPackages[0]; } mInjector.binderWithCleanCallingIdentity(() -> { @@ -8220,32 +8218,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { throw new SecurityException("Cannot wipe data. " + restriction + " restriction is set for user " + userId); } - }); - boolean isSystemUser = userId == UserHandle.USER_SYSTEM; - boolean isMainUser = userId == getMainUserId(); - boolean wipeDevice; - if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR, - adminPackage, - userId)) { - // Legacy mode - wipeDevice = getHeadlessDeviceOwnerModeForDeviceOwner() - == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER ? isMainUser : isSystemUser; - } else { - // Explicit behaviour - if (factoryReset) { - EnforcingAdmin enforcingAdmin = enforcePermissionsAndGetEnforcingAdmin( - /*admin=*/ null, - /*permission=*/ new String[]{MANAGE_DEVICE_POLICY_WIPE_DATA, - MASTER_CLEAR}, - USES_POLICY_WIPE_DATA, - adminPackage, - factoryReset ? UserHandle.USER_ALL : - getAffectedUser(calledOnParentInstance)); - wipeDevice = true; + boolean isSystemUser = userId == UserHandle.USER_SYSTEM; + boolean isMainUser = userId == getMainUserId(); + boolean wipeDevice; + if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR, + adminPackage, + userId)) { + // Legacy mode + wipeDevice = getHeadlessDeviceOwnerModeForDeviceOwner() + == HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER ? isMainUser : isSystemUser; } else { - mInjector.binderWithCleanCallingIdentity(() -> { - Preconditions.checkCallAuthorization(!isSystemUser, + // Explicit behaviour + if (factoryReset) { + wipeDevice = true; + } else { + Preconditions.checkState(!isSystemUser, "User %s is a system user and cannot be removed", userId); boolean isLastNonHeadlessUser = getUserInfo(userId).isFull() && mUserManager.getAliveUsers().stream() @@ -8253,13 +8241,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { .noneMatch(UserInfo::isFull); Preconditions.checkState(!isLastNonHeadlessUser, "Removing user %s would leave the device without any active users. " - + "Consider factory resetting the device instead.", - userId); - }); - wipeDevice = false; + + "Consider factory resetting the device instead.", userId); + wipeDevice = false; + } } - } - mInjector.binderWithCleanCallingIdentity(() -> { + if (wipeDevice) { forceWipeDeviceNoLock( (flags & WIPE_EXTERNAL_STORAGE) != 0, @@ -8600,7 +8586,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { /* reason= */ "reportFailedPasswordAttempt()", getFailedPasswordAttemptWipeMessage(), userId, - /* calledOnParentInstance= */ parent, // factoryReset=null to enable U- behaviour /* factoryReset= */ null); } catch (SecurityException e) { diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt index 7d5532f6e401..5c4716dc751e 100644 --- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt +++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt @@ -57,7 +57,6 @@ import org.junit.BeforeClass import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized -import org.mockito.ArgumentMatchers.eq import org.mockito.Mockito.any import org.mockito.Mockito.anyInt import org.mockito.Mockito.doReturn @@ -384,10 +383,6 @@ class PackageManagerComponentLabelIconOverrideTest { android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)) { PackageManager.PERMISSION_GRANTED } - whenever(this.checkPermission( - eq(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL), anyInt(), anyInt())) { - PackageManager.PERMISSION_GRANTED - } } val mockSharedLibrariesImpl: SharedLibrariesImpl = mock { whenever(this.snapshot()) { this@mock } diff --git a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java index e33ca7775e22..70a2d4847ce7 100644 --- a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java +++ b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java @@ -45,7 +45,7 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.bedstead.harrier.BedsteadJUnit4; import com.android.bedstead.harrier.DeviceState; -import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser; +import com.android.bedstead.multiuser.annotations.EnsureHasSecondaryUser; import com.android.bedstead.nene.users.UserReference; import com.android.compatibility.common.util.PollingCheck; import com.android.compatibility.common.util.TestUtils; diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageInstallerSessionTest.kt b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageInstallerSessionTest.kt index 7aa2ff50dbbd..cbca434a6bb6 100644 --- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageInstallerSessionTest.kt +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageInstallerSessionTest.kt @@ -30,6 +30,7 @@ import android.util.AtomicFile import android.util.Slog import android.util.Xml import com.android.internal.os.BackgroundThread +import com.android.server.pm.verify.pkg.VerifierController import com.android.server.testutils.whenever import com.google.common.truth.Truth.assertThat import libcore.io.IoUtils @@ -195,7 +196,8 @@ class PackageInstallerSessionTest { /* isApplied */ false, /* stagedSessionErrorCode */ PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, /* stagedSessionErrorMessage */ "some error", - /* preVerifiedDomains */ DomainSet(setOf("com.foo", "com.bar")) + /* preVerifiedDomains */ DomainSet(setOf("com.foo", "com.bar")), + /* VerifierController */ mock(VerifierController::class.java) ) } @@ -249,7 +251,8 @@ class PackageInstallerSessionTest { mock(StagingManager::class.java), mTmpDir, mock(PackageSessionProvider::class.java), - mock(SilentUpdatePolicy::class.java) + mock(SilentUpdatePolicy::class.java), + mock(VerifierController::class.java) ) ret.add(session) } catch (e: Exception) { @@ -343,4 +346,4 @@ class PackageInstallerSessionTest { assertThat(expected.mInitiatingPackageName).isEqualTo(actual.mInitiatingPackageName) assertThat(expected.mOriginatingPackageName).isEqualTo(actual.mOriginatingPackageName) } -}
\ No newline at end of file +} diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/verify/pkg/VerificationStatusTrackerTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/verify/pkg/VerificationStatusTrackerTest.java new file mode 100644 index 000000000000..fa076db456ec --- /dev/null +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/verify/pkg/VerificationStatusTrackerTest.java @@ -0,0 +1,113 @@ +/* + * 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.verify.pkg; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; + +import android.platform.test.annotations.Presubmit; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.concurrent.TimeUnit; + +@Presubmit +@RunWith(AndroidJUnit4.class) +@SmallTest +public class VerificationStatusTrackerTest { + private static final String TEST_PACKAGE_NAME = "com.foo"; + private static final long TEST_REQUEST_START_TIME = 100L; + private static final long TEST_TIMEOUT_DURATION_MILLIS = TimeUnit.MINUTES.toMillis(1); + private static final long TEST_TIMEOUT_EXTENDED_MILLIS = TimeUnit.MINUTES.toMillis(2); + private static final long TEST_MAX_TIMEOUT_DURATION_MILLIS = + TimeUnit.MINUTES.toMillis(10); + + @Mock + VerifierController.Injector mInjector; + private VerificationStatusTracker mTracker; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mInjector.getVerificationRequestTimeoutMillis()).thenReturn( + TEST_TIMEOUT_DURATION_MILLIS); + when(mInjector.getMaxVerificationExtendedTimeoutMillis()).thenReturn( + TEST_MAX_TIMEOUT_DURATION_MILLIS); + // Mock time forward as the code continues to check for the current time + when(mInjector.getCurrentTimeMillis()) + .thenReturn(TEST_REQUEST_START_TIME) + .thenReturn(TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS - 1) + .thenReturn(TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS) + .thenReturn(TEST_REQUEST_START_TIME + TEST_MAX_TIMEOUT_DURATION_MILLIS - 100) + .thenReturn(TEST_REQUEST_START_TIME + TEST_MAX_TIMEOUT_DURATION_MILLIS); + mTracker = new VerificationStatusTracker(TEST_PACKAGE_NAME, TEST_TIMEOUT_DURATION_MILLIS, + TEST_MAX_TIMEOUT_DURATION_MILLIS, mInjector); + } + + @Test + public void testTimeout() { + assertThat(mTracker.getTimeoutTime()).isEqualTo( + TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS); + // It takes two calls to set the timeout, because the timeout time hasn't been reached for + // the first calls + assertThat(mTracker.isTimeout()).isFalse(); + assertThat(mTracker.isTimeout()).isTrue(); + } + + @Test + public void testTimeoutExtended() { + assertThat(mTracker.getTimeoutTime()).isEqualTo( + TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS); + assertThat(mTracker.extendTimeRemaining(TEST_TIMEOUT_EXTENDED_MILLIS)) + .isEqualTo(TEST_TIMEOUT_EXTENDED_MILLIS); + assertThat(mTracker.getTimeoutTime()).isEqualTo( + TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS + + TEST_TIMEOUT_EXTENDED_MILLIS); + + // It would take 3 calls to set the timeout, because the timeout time hasn't been reached + // for the first 2 time checks, but querying the remaining time also does a time check. + assertThat(mTracker.isTimeout()).isFalse(); + assertThat(mTracker.getRemainingTime()).isGreaterThan(0); + assertThat(mTracker.isTimeout()).isTrue(); + assertThat(mTracker.getRemainingTime()).isEqualTo(0); + } + + @Test + public void testTimeoutExtendedExceedsMax() { + assertThat(mTracker.getTimeoutTime()).isEqualTo( + TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS); + assertThat(mTracker.extendTimeRemaining(TEST_MAX_TIMEOUT_DURATION_MILLIS)) + .isEqualTo(TEST_MAX_TIMEOUT_DURATION_MILLIS - TEST_TIMEOUT_DURATION_MILLIS); + assertThat(mTracker.getTimeoutTime()).isEqualTo( + TEST_REQUEST_START_TIME + TEST_MAX_TIMEOUT_DURATION_MILLIS); + // It takes 4 calls to set the timeout, because the timeout time hasn't been reached for + // the first 3 calls + assertThat(mTracker.isTimeout()).isFalse(); + assertThat(mTracker.isTimeout()).isFalse(); + assertThat(mTracker.isTimeout()).isFalse(); + assertThat(mTracker.isTimeout()).isTrue(); + assertThat(mTracker.getRemainingTime()).isEqualTo(0); + } +} diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/verify/pkg/VerifierControllerTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/verify/pkg/VerifierControllerTest.java new file mode 100644 index 000000000000..be094b0152bc --- /dev/null +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/verify/pkg/VerifierControllerTest.java @@ -0,0 +1,502 @@ +/* + * 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.verify.pkg; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.testng.Assert.expectThrows; + +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.SharedLibraryInfo; +import android.content.pm.SigningInfo; +import android.content.pm.VersionedPackage; +import android.content.pm.verify.pkg.IVerifierService; +import android.content.pm.verify.pkg.VerificationSession; +import android.content.pm.verify.pkg.VerificationStatus; +import android.net.Uri; +import android.os.Handler; +import android.os.Message; +import android.os.PersistableBundle; +import android.platform.test.annotations.Presubmit; +import android.util.Pair; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import com.android.internal.infra.AndroidFuture; +import com.android.internal.infra.ServiceConnector; +import com.android.server.pm.Computer; +import com.android.server.pm.PackageInstallerSession; + +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; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +@Presubmit +@RunWith(AndroidJUnit4.class) +@SmallTest +public class VerifierControllerTest { + private static final int TEST_ID = 100; + private static final String TEST_PACKAGE_NAME = "com.foo"; + private static final ComponentName TEST_VERIFIER_COMPONENT_NAME = + new ComponentName("com.verifier", "com.verifier.Service"); + private static final Uri TEST_PACKAGE_URI = Uri.parse("test://test"); + private static final SigningInfo TEST_SIGNING_INFO = new SigningInfo(); + private static final SharedLibraryInfo TEST_SHARED_LIBRARY_INFO1 = + new SharedLibraryInfo("sharedLibPath1", TEST_PACKAGE_NAME, + Collections.singletonList("path1"), "sharedLib1", 101, + SharedLibraryInfo.TYPE_DYNAMIC, new VersionedPackage(TEST_PACKAGE_NAME, 1), + null, null, false); + private static final SharedLibraryInfo TEST_SHARED_LIBRARY_INFO2 = + new SharedLibraryInfo("sharedLibPath2", TEST_PACKAGE_NAME, + Collections.singletonList("path2"), "sharedLib2", 102, + SharedLibraryInfo.TYPE_DYNAMIC, + new VersionedPackage(TEST_PACKAGE_NAME, 2), null, null, false); + private static final String TEST_KEY = "test key"; + private static final String TEST_VALUE = "test value"; + private static final String TEST_FAILURE_MESSAGE = "verification failed!"; + private static final long TEST_REQUEST_START_TIME = 0L; + private static final long TEST_TIMEOUT_DURATION_MILLIS = TimeUnit.MINUTES.toMillis(1); + private static final long TEST_MAX_TIMEOUT_DURATION_MILLIS = + TimeUnit.MINUTES.toMillis(10); + + private final ArrayList<SharedLibraryInfo> mTestDeclaredLibraries = new ArrayList<>(); + private final PersistableBundle mTestExtensionParams = new PersistableBundle(); + @Mock + Context mContext; + @Mock + Handler mHandler; + @Mock + VerifierController.Injector mInjector; + @Mock + ServiceConnector<IVerifierService> mMockServiceConnector; + @Mock + IVerifierService mMockService; + @Mock + Computer mSnapshot; + Supplier<Computer> mSnapshotSupplier = () -> mSnapshot; + @Mock + PackageInstallerSession.VerifierCallback mSessionCallback; + + private VerifierController mVerifierController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mInjector.isVerifierInstalled(any(Computer.class), anyInt())).thenReturn(true); + when(mInjector.getRemoteService( + any(Computer.class), any(Context.class), anyInt(), any(Handler.class) + )).thenReturn(new Pair<>(mMockServiceConnector, TEST_VERIFIER_COMPONENT_NAME)); + when(mInjector.getVerificationRequestTimeoutMillis()).thenReturn( + TEST_TIMEOUT_DURATION_MILLIS); + when(mInjector.getMaxVerificationExtendedTimeoutMillis()).thenReturn( + TEST_MAX_TIMEOUT_DURATION_MILLIS); + // Mock time forward as the code continues to check for the current time + when(mInjector.getCurrentTimeMillis()) + .thenReturn(TEST_REQUEST_START_TIME) + .thenReturn(TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS + 1); + when(mMockServiceConnector.post(any(ServiceConnector.VoidJob.class))) + .thenAnswer( + i -> { + ((ServiceConnector.VoidJob) i.getArguments()[0]).run(mMockService); + return new AndroidFuture<>(); + }); + when(mMockServiceConnector.run(any(ServiceConnector.VoidJob.class))) + .thenAnswer( + i -> { + ((ServiceConnector.VoidJob) i.getArguments()[0]).run(mMockService); + return true; + }); + + mTestDeclaredLibraries.add(TEST_SHARED_LIBRARY_INFO1); + mTestDeclaredLibraries.add(TEST_SHARED_LIBRARY_INFO2); + mTestExtensionParams.putString(TEST_KEY, TEST_VALUE); + + mVerifierController = new VerifierController(mContext, mHandler, mInjector); + } + + @Test + public void testVerifierNotInstalled() { + when(mInjector.isVerifierInstalled(any(Computer.class), anyInt())).thenReturn(false); + when(mInjector.getRemoteService( + any(Computer.class), any(Context.class), anyInt(), any(Handler.class) + )).thenReturn(null); + assertThat(mVerifierController.isVerifierInstalled(mSnapshotSupplier, 0)).isFalse(); + assertThat(mVerifierController.bindToVerifierServiceIfNeeded(mSnapshotSupplier, 0)) + .isFalse(); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false)).isFalse(); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ true)).isFalse(); + verifyZeroInteractions(mSessionCallback); + } + + @Test + public void testRebindService() { + assertThat(mVerifierController.bindToVerifierServiceIfNeeded(mSnapshotSupplier, 0)) + .isTrue(); + } + + @Test + public void testVerifierAvailableButNotConnected() { + assertThat(mVerifierController.isVerifierInstalled(mSnapshotSupplier, 0)).isTrue(); + when(mInjector.getRemoteService( + any(Computer.class), any(Context.class), anyInt(), any(Handler.class) + )).thenReturn(null); + assertThat(mVerifierController.bindToVerifierServiceIfNeeded(mSnapshotSupplier, 0)) + .isFalse(); + // Test that nothing crashes if the verifier is available even though there's no bound + mVerifierController.notifyPackageNameAvailable(TEST_PACKAGE_NAME); + mVerifierController.notifyVerificationCancelled(TEST_PACKAGE_NAME); + mVerifierController.notifyVerificationTimeout(-1); + // Since there was no bound, no call is made to the verifier + verifyZeroInteractions(mMockService); + } + + @Test + public void testUnbindService() throws Exception { + ArgumentCaptor<ServiceConnector.ServiceLifecycleCallbacks> captor = ArgumentCaptor.forClass( + ServiceConnector.ServiceLifecycleCallbacks.class); + assertThat(mVerifierController.bindToVerifierServiceIfNeeded(mSnapshotSupplier, 0)) + .isTrue(); + verify(mMockServiceConnector).setServiceLifecycleCallbacks(captor.capture()); + ServiceConnector.ServiceLifecycleCallbacks<IVerifierService> callbacks = captor.getValue(); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false)).isTrue(); + verify(mMockService, times(1)).onVerificationRequired(any(VerificationSession.class)); + callbacks.onBinderDied(); + // Test that nothing crashes if the service connection is lost + assertThat(mVerifierController.isVerifierInstalled(mSnapshotSupplier, 0)).isTrue(); + mVerifierController.notifyPackageNameAvailable(TEST_PACKAGE_NAME); + mVerifierController.notifyVerificationCancelled(TEST_PACKAGE_NAME); + mVerifierController.notifyVerificationTimeout(TEST_ID); + verifyNoMoreInteractions(mMockService); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false)).isTrue(); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ true)).isTrue(); + mVerifierController.notifyVerificationTimeout(TEST_ID); + verify(mMockService, times(1)).onVerificationTimeout(eq(TEST_ID)); + } + + @Test + public void testNotifyPackageNameAvailable() throws Exception { + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false)).isTrue(); + mVerifierController.notifyPackageNameAvailable(TEST_PACKAGE_NAME); + verify(mMockService).onPackageNameAvailable(eq(TEST_PACKAGE_NAME)); + } + + @Test + public void testNotifyVerificationCancelled() throws Exception { + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false)).isTrue(); + mVerifierController.notifyVerificationCancelled(TEST_PACKAGE_NAME); + verify(mMockService).onVerificationCancelled(eq(TEST_PACKAGE_NAME)); + } + + @Test + public void testStartVerificationSession() throws Exception { + ArgumentCaptor<VerificationSession> captor = + ArgumentCaptor.forClass(VerificationSession.class); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false)).isTrue(); + verify(mMockService).onVerificationRequired(captor.capture()); + VerificationSession session = captor.getValue(); + assertThat(session.getId()).isEqualTo(TEST_ID); + assertThat(session.getInstallSessionId()).isEqualTo(TEST_ID); + assertThat(session.getPackageName()).isEqualTo(TEST_PACKAGE_NAME); + assertThat(session.getStagedPackageUri()).isEqualTo(TEST_PACKAGE_URI); + assertThat(session.getSigningInfo().getSigningDetails()) + .isEqualTo(TEST_SIGNING_INFO.getSigningDetails()); + List<SharedLibraryInfo> declaredLibraries = session.getDeclaredLibraries(); + // SharedLibraryInfo doesn't have a "equals" method, so we have to check it indirectly + assertThat(declaredLibraries.getFirst().toString()) + .isEqualTo(TEST_SHARED_LIBRARY_INFO1.toString()); + assertThat(declaredLibraries.get(1).toString()) + .isEqualTo(TEST_SHARED_LIBRARY_INFO2.toString()); + // We can't directly test with PersistableBundle.equals() because the parceled bundle's + // structure is different, but all the key/value pairs should be preserved as before. + assertThat(session.getExtensionParams().getString(TEST_KEY)) + .isEqualTo(mTestExtensionParams.getString(TEST_KEY)); + } + + @Test + public void testNotifyVerificationRetry() throws Exception { + ArgumentCaptor<VerificationSession> captor = + ArgumentCaptor.forClass(VerificationSession.class); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ true)).isTrue(); + verify(mMockService).onVerificationRetry(captor.capture()); + VerificationSession session = captor.getValue(); + assertThat(session.getId()).isEqualTo(TEST_ID); + assertThat(session.getInstallSessionId()).isEqualTo(TEST_ID); + assertThat(session.getPackageName()).isEqualTo(TEST_PACKAGE_NAME); + assertThat(session.getStagedPackageUri()).isEqualTo(TEST_PACKAGE_URI); + assertThat(session.getSigningInfo().getSigningDetails()) + .isEqualTo(TEST_SIGNING_INFO.getSigningDetails()); + List<SharedLibraryInfo> declaredLibraries = session.getDeclaredLibraries(); + // SharedLibraryInfo doesn't have a "equals" method, so we have to check it indirectly + assertThat(declaredLibraries.getFirst().toString()) + .isEqualTo(TEST_SHARED_LIBRARY_INFO1.toString()); + assertThat(declaredLibraries.get(1).toString()) + .isEqualTo(TEST_SHARED_LIBRARY_INFO2.toString()); + // We can't directly test with PersistableBundle.equals() because the parceled bundle's + // structure is different, but all the key/value pairs should be preserved as before. + assertThat(session.getExtensionParams().getString(TEST_KEY)) + .isEqualTo(mTestExtensionParams.getString(TEST_KEY)); + } + + @Test + public void testNotifyVerificationTimeout() throws Exception { + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ true)).isTrue(); + mVerifierController.notifyVerificationTimeout(TEST_ID); + verify(mMockService).onVerificationTimeout(eq(TEST_ID)); + } + + @Test + public void testRequestTimeout() { + // Let the mock handler set request to TIMEOUT, immediately after the request is sent. + // We can't mock postDelayed because it's final, but we can mock the method it calls. + when(mHandler.sendMessageAtTime(any(Message.class), anyLong())).thenAnswer( + i -> { + ((Message) i.getArguments()[0]).getCallback().run(); + return true; + }); + ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false)).isTrue(); + verify(mHandler, times(1)).sendMessageAtTime(any(Message.class), anyLong()); + verify(mSessionCallback, times(1)).onTimeout(); + verify(mInjector, times(2)).getCurrentTimeMillis(); + verify(mInjector, times(1)).stopTimeoutCountdown(eq(mHandler), any()); + } + + @Test + public void testRequestTimeoutWithRetryPass() throws Exception { + // Only let the first request timeout and let the second one pass + when(mHandler.sendMessageAtTime(any(Message.class), anyLong())).thenAnswer( + i -> { + ((Message) i.getArguments()[0]).getCallback().run(); + return true; + }) + .thenAnswer(i -> true); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false)).isTrue(); + verify(mHandler, times(1)).sendMessageAtTime(any(Message.class), anyLong()); + verify(mSessionCallback, times(1)).onTimeout(); + verify(mInjector, times(2)).getCurrentTimeMillis(); + verify(mInjector, times(1)).stopTimeoutCountdown(eq(mHandler), any()); + // Then retry + ArgumentCaptor<VerificationSession> captor = + ArgumentCaptor.forClass(VerificationSession.class); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ true)).isTrue(); + verify(mMockService).onVerificationRetry(captor.capture()); + VerificationSession session = captor.getValue(); + VerificationStatus status = new VerificationStatus.Builder().setVerified(true).build(); + session.reportVerificationComplete(status); + verify(mSessionCallback, times(1)).onVerificationCompleteReceived( + eq(status), eq(null)); + verify(mInjector, times(2)).stopTimeoutCountdown(eq(mHandler), any()); + } + + @Test + public void testRequestIncomplete() throws Exception { + ArgumentCaptor<VerificationSession> captor = + ArgumentCaptor.forClass(VerificationSession.class); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false)).isTrue(); + verify(mMockService).onVerificationRequired(captor.capture()); + VerificationSession session = captor.getValue(); + session.reportVerificationIncomplete(VerificationSession.VERIFICATION_INCOMPLETE_UNKNOWN); + verify(mSessionCallback, times(1)).onVerificationIncompleteReceived( + eq(VerificationSession.VERIFICATION_INCOMPLETE_UNKNOWN)); + verify(mInjector, times(1)).stopTimeoutCountdown(eq(mHandler), any()); + } + + @Test + public void testRequestCompleteWithSuccessWithExtensionResponse() throws Exception { + ArgumentCaptor<VerificationSession> captor = + ArgumentCaptor.forClass(VerificationSession.class); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false)).isTrue(); + verify(mMockService).onVerificationRequired(captor.capture()); + VerificationSession session = captor.getValue(); + VerificationStatus status = new VerificationStatus.Builder().setVerified(true).build(); + PersistableBundle bundle = new PersistableBundle(); + session.reportVerificationComplete(status, bundle); + verify(mSessionCallback, times(1)).onVerificationCompleteReceived( + eq(status), eq(bundle)); + verify(mInjector, times(1)).stopTimeoutCountdown(eq(mHandler), any()); + } + + @Test + public void testRequestCompleteWithFailure() throws Exception { + ArgumentCaptor<VerificationSession> captor = + ArgumentCaptor.forClass(VerificationSession.class); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false)).isTrue(); + verify(mMockService).onVerificationRequired(captor.capture()); + VerificationSession session = captor.getValue(); + VerificationStatus status = new VerificationStatus.Builder() + .setVerified(false) + .setFailureMessage(TEST_FAILURE_MESSAGE) + .build(); + session.reportVerificationComplete(status); + verify(mSessionCallback, times(1)).onVerificationCompleteReceived( + eq(status), eq(null)); + verify(mInjector, times(1)).stopTimeoutCountdown(eq(mHandler), any()); + } + + @Test + public void testRepeatedRequestCompleteShouldThrow() throws Exception { + ArgumentCaptor<VerificationSession> captor = + ArgumentCaptor.forClass(VerificationSession.class); + assertThat(mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false)).isTrue(); + verify(mMockService).onVerificationRequired(captor.capture()); + VerificationSession session = captor.getValue(); + VerificationStatus status = new VerificationStatus.Builder().setVerified(true).build(); + session.reportVerificationComplete(status); + // getters should throw after the report + expectThrows(IllegalStateException.class, () -> session.getTimeoutTime()); + // Report again should fail with exception + expectThrows(IllegalStateException.class, () -> session.reportVerificationComplete(status)); + } + + @Test + public void testExtendTimeRemaining() throws Exception { + ArgumentCaptor<VerificationSession> captor = + ArgumentCaptor.forClass(VerificationSession.class); + mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false); + verify(mMockService).onVerificationRequired(captor.capture()); + VerificationSession session = captor.getValue(); + final long initialTimeoutTime = TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS; + assertThat(session.getTimeoutTime()).isEqualTo(initialTimeoutTime); + final long extendTimeMillis = TEST_TIMEOUT_DURATION_MILLIS; + assertThat(session.extendTimeRemaining(extendTimeMillis)).isEqualTo(extendTimeMillis); + assertThat(session.getTimeoutTime()).isEqualTo(initialTimeoutTime + extendTimeMillis); + } + + @Test + public void testExtendTimeExceedsMax() throws Exception { + ArgumentCaptor<VerificationSession> captor = + ArgumentCaptor.forClass(VerificationSession.class); + mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false); + verify(mMockService).onVerificationRequired(captor.capture()); + VerificationSession session = captor.getValue(); + final long initialTimeoutTime = TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS; + final long maxTimeoutTime = TEST_REQUEST_START_TIME + TEST_MAX_TIMEOUT_DURATION_MILLIS; + assertThat(session.getTimeoutTime()).isEqualTo(initialTimeoutTime); + final long extendTimeMillis = TEST_MAX_TIMEOUT_DURATION_MILLIS; + assertThat(session.extendTimeRemaining(extendTimeMillis)).isEqualTo( + TEST_MAX_TIMEOUT_DURATION_MILLIS - TEST_TIMEOUT_DURATION_MILLIS); + assertThat(session.getTimeoutTime()).isEqualTo(maxTimeoutTime); + } + + @Test + public void testTimeoutChecksMultipleTimes() { + // Mock message handling + when(mHandler.sendMessageAtTime(any(Message.class), anyLong())).thenAnswer( + i -> { + ((Message) i.getArguments()[0]).getCallback().run(); + return true; + }); + // Mock time forward as the code continues to check for the current time + when(mInjector.getCurrentTimeMillis()) + // First called when the tracker is created + .thenReturn(TEST_REQUEST_START_TIME) + // Then mock the first timeout check when the timeout time isn't reached yet + .thenReturn(TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS - 1000) + // Then mock the same time used to check the remaining time + .thenReturn(TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS - 1000) + // Then mock the second timeout check when the timeout time isn't reached yet + .thenReturn(TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS - 100) + // Then mock the same time used to check the remaining time + .thenReturn(TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS - 100) + // Then mock the third timeout check when the timeout time has been reached + .thenReturn(TEST_REQUEST_START_TIME + TEST_TIMEOUT_DURATION_MILLIS + 1); + mVerifierController.startVerificationSession( + mSnapshotSupplier, 0, TEST_ID, TEST_PACKAGE_NAME, TEST_PACKAGE_URI, + TEST_SIGNING_INFO, mTestDeclaredLibraries, mTestExtensionParams, mSessionCallback, + /* retry= */ false); + verify(mHandler, times(3)).sendMessageAtTime(any(Message.class), anyLong()); + verify(mInjector, times(6)).getCurrentTimeMillis(); + verify(mSessionCallback, times(1)).onTimeout(); + } +} diff --git a/services/tests/appfunctions/Android.bp b/services/tests/appfunctions/Android.bp index 9560ec9990ad..c841643c6654 100644 --- a/services/tests/appfunctions/Android.bp +++ b/services/tests/appfunctions/Android.bp @@ -36,6 +36,7 @@ android_test { "androidx.test.core", "androidx.test.runner", "androidx.test.ext.truth", + "kotlin-test", "platform-test-annotations", "services.appfunctions", "servicestests-core-utils", diff --git a/services/tests/appfunctions/src/android/app/appfunctions/AppFunctionRuntimeMetadataTest.kt b/services/tests/appfunctions/src/android/app/appfunctions/AppFunctionRuntimeMetadataTest.kt index da3e94f64e56..d3262046cad8 100644 --- a/services/tests/appfunctions/src/android/app/appfunctions/AppFunctionRuntimeMetadataTest.kt +++ b/services/tests/appfunctions/src/android/app/appfunctions/AppFunctionRuntimeMetadataTest.kt @@ -15,8 +15,12 @@ */ package android.app.appfunctions +import android.app.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_DEFAULT +import android.app.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_DISABLED +import android.app.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_ENABLED import android.app.appsearch.AppSearchSchema import com.google.common.truth.Truth.assertThat +import kotlin.test.assertFailsWith import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -108,32 +112,43 @@ class AppFunctionRuntimeMetadataTest { assertThat(runtimeMetadata.packageName).isEqualTo("com.pkg") assertThat(runtimeMetadata.functionId).isEqualTo("funcId") - assertThat(runtimeMetadata.enabled).isNull() + assertThat(runtimeMetadata.enabled).isEqualTo(APP_FUNCTION_STATE_DEFAULT) assertThat(runtimeMetadata.appFunctionStaticMetadataQualifiedId) .isEqualTo("android\$apps-db/app_functions#com.pkg/funcId") } @Test - fun setEnabled_true() { + fun setEnabled_enabled() { val runtimeMetadata = - AppFunctionRuntimeMetadata.Builder("com.pkg", "funcId").setEnabled(true).build() + AppFunctionRuntimeMetadata.Builder("com.pkg", "funcId").setEnabled(APP_FUNCTION_STATE_ENABLED).build() - assertThat(runtimeMetadata.enabled).isTrue() + assertThat(runtimeMetadata.enabled).isEqualTo(APP_FUNCTION_STATE_ENABLED) } @Test - fun setEnabled_false() { + fun setEnabled_disabled() { val runtimeMetadata = - AppFunctionRuntimeMetadata.Builder("com.pkg", "funcId").setEnabled(false).build() + AppFunctionRuntimeMetadata.Builder("com.pkg", "funcId").setEnabled( + APP_FUNCTION_STATE_DISABLED).build() - assertThat(runtimeMetadata.enabled).isFalse() + assertThat(runtimeMetadata.enabled).isEqualTo(APP_FUNCTION_STATE_DISABLED) } @Test - fun setEnabled_null() { + fun setEnabled_default() { val runtimeMetadata = - AppFunctionRuntimeMetadata.Builder("com.pkg", "funcId").setEnabled(null).build() + AppFunctionRuntimeMetadata.Builder("com.pkg", "funcId").setEnabled( + APP_FUNCTION_STATE_DEFAULT).build() - assertThat(runtimeMetadata.enabled).isNull() + assertThat(runtimeMetadata.enabled).isEqualTo(APP_FUNCTION_STATE_DEFAULT) + } + + @Test + fun setEnabled_illegalArgument() { + val runtimeMetadataBuilder = + AppFunctionRuntimeMetadata.Builder("com.pkg", "funcId") + assertFailsWith<IllegalArgumentException>("Value of EnabledState is unsupported.") { + runtimeMetadataBuilder.setEnabled(-1) + } } } diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java index 8e1be9a777fd..3976ea4fc86e 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java @@ -157,6 +157,7 @@ public final class DisplayDeviceConfigTest { .getIdleScreenRefreshRateTimeoutLuxThresholdPoint()); assertNull(mDisplayDeviceConfig.getTempSensor().name); assertTrue(mDisplayDeviceConfig.isAutoBrightnessAvailable()); + assertEquals(0, mDisplayDeviceConfig.getIdleStylusTimeoutMillis()); } @Test @@ -253,6 +254,7 @@ public final class DisplayDeviceConfigTest { .getLux().intValue()); assertEquals(800, idleScreenRefreshRateTimeoutLuxThresholdPoints.get(1) .getTimeout().intValue()); + assertEquals(1000, mDisplayDeviceConfig.getIdleStylusTimeoutMillis()); } @Test @@ -1479,6 +1481,7 @@ public final class DisplayDeviceConfigTest { + "</point>\n" + "</map>\n" + "</luxToBrightnessMapping>\n" + + "<idleStylusTimeoutMillis>1000</idleStylusTimeoutMillis>\n" + "</autoBrightness>\n" + getPowerThrottlingConfig() + "<highBrightnessMode enabled=\"true\">\n" diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java index 342c87a6b5f6..1a1c8e50ba0a 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -50,6 +50,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeastOnce; @@ -1309,6 +1310,38 @@ public class DisplayManagerServiceTest { } /** + * Tests that it's not allowed to create an auto-mirror virtual display without + * CAPTURE_VIDEO_OUTPUT permission or a virtual device that can mirror displays + */ + @Test + public void createAutoMirrorDisplay_withoutPermissionOrAllowedVirtualDevice_throwsException() + throws Exception { + DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); + DisplayManagerInternal localService = displayManager.new LocalService(); + registerDefaultDisplays(displayManager); + when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); + IVirtualDevice virtualDevice = mock(IVirtualDevice.class); + when(virtualDevice.getDeviceId()).thenReturn(1); + when(virtualDevice.canCreateMirrorDisplays()).thenReturn(false); + when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); + when(mContext.checkCallingPermission(CAPTURE_VIDEO_OUTPUT)).thenReturn( + PackageManager.PERMISSION_DENIED); + + final VirtualDisplayConfig.Builder builder = + new VirtualDisplayConfig.Builder(VIRTUAL_DISPLAY_NAME, 600, 800, 320) + .setFlags(VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) + .setUniqueId("uniqueId --- mirror display"); + assertThrows(SecurityException.class, () -> { + localService.createVirtualDisplay( + builder.build(), + mMockAppToken /* callback */, + virtualDevice /* virtualDeviceToken */, + mock(DisplayWindowPolicyController.class), + PACKAGE_NAME); + }); + } + + /** * Tests that the virtual display is added to the default display group when created with * VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR using a virtual device. */ @@ -1320,6 +1353,7 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); + when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); // Create an auto-mirror virtual display using a virtual device. @@ -1352,6 +1386,7 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); + when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); // Create an auto-mirror virtual display using a virtual device. @@ -1418,6 +1453,7 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); + when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); when(mContext.checkCallingPermission(ADD_ALWAYS_UNLOCKED_DISPLAY)) .thenReturn(PackageManager.PERMISSION_GRANTED); @@ -1453,6 +1489,7 @@ public class DisplayManagerServiceTest { when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); IVirtualDevice virtualDevice = mock(IVirtualDevice.class); when(virtualDevice.getDeviceId()).thenReturn(1); + when(virtualDevice.canCreateMirrorDisplays()).thenReturn(true); when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true); // Create an auto-mirror virtual display using a virtual device. @@ -3409,6 +3446,31 @@ public class DisplayManagerServiceTest { verify(dpc).onDisplayChanged(/* hbmMetadata= */ null, Layout.NO_LEAD_DISPLAY); } + @Test + public void testCreateAndReleaseVirtualDisplay_CalledWithTheSameUid() { + DisplayManagerService displayManager = + new DisplayManagerService(mContext, mShortMockedInjector); + registerDefaultDisplays(displayManager); + DisplayManagerService.BinderService bs = displayManager.new BinderService(); + VirtualDisplayConfig config = mock(VirtualDisplayConfig.class); + Surface surface = mock(Surface.class); + when(config.getSurface()).thenReturn(surface); + int callingUid = Binder.getCallingUid(); + IBinder binder = mock(IBinder.class); + when(mMockAppToken.asBinder()).thenReturn(binder); + String uniqueId = "123"; + when(config.getUniqueId()).thenReturn(uniqueId); + + bs.createVirtualDisplay(config, mMockAppToken, /* projection= */ null, PACKAGE_NAME); + verify(mMockVirtualDisplayAdapter).createVirtualDisplayLocked(eq(mMockAppToken), + /* projection= */ isNull(), eq(callingUid), eq(PACKAGE_NAME), + eq("virtual:" + PACKAGE_NAME + ":" + uniqueId), eq(surface), /* flags= */ anyInt(), + eq(config)); + + bs.releaseVirtualDisplay(mMockAppToken); + verify(mMockVirtualDisplayAdapter).releaseVirtualDisplayLocked(binder, callingUid); + } + private void initDisplayPowerController(DisplayManagerInternal localService) { localService.initPowerManagement(new DisplayManagerInternal.DisplayPowerCallbacks() { @Override diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java index c70bf8abaef6..01b2d3e34bdc 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java @@ -35,6 +35,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.description; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -2278,29 +2279,44 @@ public final class DisplayPowerControllerTest { throws Exception { when(mDisplayManagerFlagsMock.isBatteryStatsEnabledForAllDisplays()).thenReturn(false); - verifyNoteScreenState(Display.DEFAULT_DISPLAY, /* expectNote= */ true); + verifyNoteScreenState( + Display.DEFAULT_DISPLAY, Display.TYPE_INTERNAL, /* expectNote= */ true); } @Test public void testBatteryStatNotes_enabledOnDefaultDisplayWhenEnabledOnOthers() throws Exception { when(mDisplayManagerFlagsMock.isBatteryStatsEnabledForAllDisplays()).thenReturn(true); - verifyNoteScreenState(Display.DEFAULT_DISPLAY, /* expectNote= */ true); + verifyNoteScreenState( + Display.DEFAULT_DISPLAY, Display.TYPE_INTERNAL, /* expectNote= */ true); } @Test - public void testBatteryStatNotes_flagGuardedOnNonDefaultDisplays() throws Exception { + public void testBatteryStatNotes_flagOff_disabledForNonDefaultDisplays() throws Exception { when(mDisplayManagerFlagsMock.isBatteryStatsEnabledForAllDisplays()).thenReturn(false); - verifyNoteScreenState(/* displayId= */ 2, /* expectNote= */ false); + verifyNoteScreenState(/* displayId= */ 2, Display.TYPE_INTERNAL, /* expectNote= */ false); + } + @Test + public void testBatteryStatNotes_enabledOnlyOnInternalOrExternalDisplays() throws Exception { when(mDisplayManagerFlagsMock.isBatteryStatsEnabledForAllDisplays()).thenReturn(true); - verifyNoteScreenState(/* displayId= */ 2, /* expectNote= */ true); + for (int displayType = 0; displayType < Display.TYPE_MAX; displayType++) { + boolean expectNote = + (displayType == Display.TYPE_INTERNAL) + || (displayType == Display.TYPE_EXTERNAL); + verifyNoteScreenState(/* displayId= */ 2, displayType, expectNote); + } } - private void verifyNoteScreenState(int displayId, boolean expectNote) throws Exception { - mHolder = createDisplayPowerController(displayId, UNIQUE_ID); + private void verifyNoteScreenState(int displayId, int displayDeviceType, boolean expectNote) + throws Exception { + clearInvocations(mMockBatteryStats); + DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo(); + deviceInfo.type = displayDeviceType; + deviceInfo.uniqueId = UNIQUE_ID; + mHolder = createDisplayPowerController(displayId, deviceInfo); DisplayPowerRequest dpr = new DisplayPowerRequest(); dpr.policy = DisplayPowerRequest.POLICY_BRIGHT; when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON); @@ -2308,14 +2324,22 @@ public final class DisplayPowerControllerTest { mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState + final String baseErrorMessage = + String.format("[display id=%d type=%d]", displayId, displayDeviceType); + final String errorMessage; if (expectNote) { - verify(mMockBatteryStats) + errorMessage = "Expected battery stats: " + baseErrorMessage; + verify(mMockBatteryStats, description(errorMessage)) .noteScreenState( displayId, Display.STATE_ON, Display.STATE_REASON_DEFAULT_POLICY); - verify(mMockBatteryStats).noteScreenBrightness(eq(displayId), anyInt()); + verify(mMockBatteryStats, description(errorMessage)) + .noteScreenBrightness(eq(displayId), anyInt()); } else { - verify(mMockBatteryStats, never()).noteScreenState(anyInt(), anyInt(), anyInt()); - verify(mMockBatteryStats, never()).noteScreenBrightness(anyInt(), anyInt()); + errorMessage = "Expected no battery stats: " + baseErrorMessage; + verify(mMockBatteryStats, never().description(errorMessage)) + .noteScreenState(anyInt(), anyInt(), anyInt()); + verify(mMockBatteryStats, never().description(errorMessage)) + .noteScreenBrightness(anyInt(), anyInt()); } } @@ -2350,17 +2374,16 @@ public final class DisplayPowerControllerTest { private void setUpDisplay(int displayId, String uniqueId, LogicalDisplay logicalDisplayMock, DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock, boolean isEnabled) { - - setUpDisplay(displayId, uniqueId, logicalDisplayMock, displayDeviceMock, + DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo(); + deviceInfo.uniqueId = uniqueId; + setUpDisplay(displayId, deviceInfo, logicalDisplayMock, displayDeviceMock, displayDeviceConfigMock, isEnabled, "display_name"); } - private void setUpDisplay(int displayId, String uniqueId, LogicalDisplay logicalDisplayMock, - DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock, - boolean isEnabled, String displayName) { + private void setUpDisplay(int displayId, DisplayDeviceInfo deviceInfo, + LogicalDisplay logicalDisplayMock, DisplayDevice displayDeviceMock, + DisplayDeviceConfig displayDeviceConfigMock, boolean isEnabled, String displayName) { DisplayInfo info = new DisplayInfo(); - DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo(); - deviceInfo.uniqueId = uniqueId; when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId); when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock); @@ -2368,7 +2391,7 @@ public final class DisplayPowerControllerTest { when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled); when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false); when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo); - when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId); + when(displayDeviceMock.getUniqueId()).thenReturn(deviceInfo.uniqueId); when(displayDeviceMock.getNameLocked()).thenReturn(displayName); when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock); when(displayDeviceConfigMock.getProximitySensor()).thenReturn( @@ -2415,6 +2438,12 @@ public final class DisplayPowerControllerTest { hysteresisLevels); } + private DisplayPowerControllerHolder createDisplayPowerController( + int displayId, DisplayDeviceInfo info) { + return createDisplayPowerController( + displayId, info, /* isEnabled= */ true, /* isAutoBrightnessAvailable= */ true); + } + private DisplayPowerControllerHolder createDisplayPowerController(int displayId, String uniqueId) { return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true); @@ -2428,6 +2457,14 @@ public final class DisplayPowerControllerTest { private DisplayPowerControllerHolder createDisplayPowerController(int displayId, String uniqueId, boolean isEnabled, boolean isAutoBrightnessAvailable) { + DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo(); + deviceInfo.uniqueId = uniqueId; + return createDisplayPowerController( + displayId, deviceInfo, isEnabled, isAutoBrightnessAvailable); + } + + private DisplayPowerControllerHolder createDisplayPowerController(int displayId, + DisplayDeviceInfo deviceInfo, boolean isEnabled, boolean isAutoBrightnessAvailable) { final DisplayPowerState displayPowerState = mock(DisplayPowerState.class); final DualRampAnimator<DisplayPowerState> animator = mock(DualRampAnimator.class); final AutomaticBrightnessController automaticBrightnessController = @@ -2469,7 +2506,7 @@ public final class DisplayPowerControllerTest { when(config.getScreenBrightnessHysteresis()).thenReturn(hysteresisLevels); when(config.getScreenBrightnessIdleHysteresis()).thenReturn(hysteresisLevels); - setUpDisplay(displayId, uniqueId, display, device, config, isEnabled); + setUpDisplay(displayId, deviceInfo, display, device, config, isEnabled, "display_name"); when(config.isAutoBrightnessAvailable()).thenReturn(isAutoBrightnessAvailable); final DisplayPowerController dpc = new DisplayPowerController( diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyTest.kt b/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyTest.kt index 1fad14b0a062..f3a8d8415c19 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyTest.kt +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyTest.kt @@ -16,6 +16,7 @@ package com.android.server.display +import android.view.Display import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -23,7 +24,7 @@ class DisplayTopologyTest { private val topology = DisplayTopology() @Test - fun oneDisplay() { + fun addOneDisplay() { val displayId = 1 val width = 800.0 val height = 600.0 @@ -40,7 +41,7 @@ class DisplayTopologyTest { } @Test - fun twoDisplays() { + fun addTwoDisplays() { val displayId1 = 1 val width1 = 800.0 val height1 = 600.0 @@ -71,7 +72,7 @@ class DisplayTopologyTest { } @Test - fun manyDisplays() { + fun addManyDisplays() { val displayId1 = 1 val width1 = 800.0 val height1 = 600.0 @@ -118,4 +119,130 @@ class DisplayTopologyTest { assertThat(display.mOffset).isEqualTo(0) } } + + @Test + fun removeDisplays() { + val displayId1 = 1 + val width1 = 800.0 + val height1 = 600.0 + + val displayId2 = 2 + val width2 = 1000.0 + val height2 = 1500.0 + + topology.addDisplay(displayId1, width1, height1) + topology.addDisplay(displayId2, width2, height2) + + val noOfDisplays = 30 + for (i in 3..noOfDisplays) { + topology.addDisplay(/* displayId= */ i, width1, height1) + } + + var removedDisplays = arrayOf(20) + topology.removeDisplay(20) + + assertThat(topology.mPrimaryDisplayId).isEqualTo(displayId1) + + var display1 = topology.mRoot!! + assertThat(display1.mDisplayId).isEqualTo(displayId1) + assertThat(display1.mWidth).isEqualTo(width1) + assertThat(display1.mHeight).isEqualTo(height1) + assertThat(display1.mChildren).hasSize(1) + + var display2 = display1.mChildren[0] + assertThat(display2.mDisplayId).isEqualTo(displayId2) + assertThat(display2.mWidth).isEqualTo(width2) + assertThat(display2.mHeight).isEqualTo(height2) + assertThat(display2.mChildren).hasSize(1) + assertThat(display2.mPosition).isEqualTo( + DisplayTopology.TreeNode.Position.POSITION_TOP) + assertThat(display2.mOffset).isEqualTo(width1 / 2 - width2 / 2) + + var display = display2 + for (i in 3..noOfDisplays) { + if (i in removedDisplays) { + continue + } + display = display.mChildren[0] + assertThat(display.mDisplayId).isEqualTo(i) + assertThat(display.mWidth).isEqualTo(width1) + assertThat(display.mHeight).isEqualTo(height1) + // The last display should have no children + assertThat(display.mChildren).hasSize(if (i < noOfDisplays) 1 else 0) + assertThat(display.mPosition).isEqualTo( + DisplayTopology.TreeNode.Position.POSITION_RIGHT) + assertThat(display.mOffset).isEqualTo(0) + } + + topology.removeDisplay(22) + removedDisplays += 22 + topology.removeDisplay(23) + removedDisplays += 23 + topology.removeDisplay(25) + removedDisplays += 25 + + assertThat(topology.mPrimaryDisplayId).isEqualTo(displayId1) + + display1 = topology.mRoot!! + assertThat(display1.mDisplayId).isEqualTo(displayId1) + assertThat(display1.mWidth).isEqualTo(width1) + assertThat(display1.mHeight).isEqualTo(height1) + assertThat(display1.mChildren).hasSize(1) + + display2 = display1.mChildren[0] + assertThat(display2.mDisplayId).isEqualTo(displayId2) + assertThat(display2.mWidth).isEqualTo(width2) + assertThat(display2.mHeight).isEqualTo(height2) + assertThat(display2.mChildren).hasSize(1) + assertThat(display2.mPosition).isEqualTo( + DisplayTopology.TreeNode.Position.POSITION_TOP) + assertThat(display2.mOffset).isEqualTo(width1 / 2 - width2 / 2) + + display = display2 + for (i in 3..noOfDisplays) { + if (i in removedDisplays) { + continue + } + display = display.mChildren[0] + assertThat(display.mDisplayId).isEqualTo(i) + assertThat(display.mWidth).isEqualTo(width1) + assertThat(display.mHeight).isEqualTo(height1) + // The last display should have no children + assertThat(display.mChildren).hasSize(if (i < noOfDisplays) 1 else 0) + assertThat(display.mPosition).isEqualTo( + DisplayTopology.TreeNode.Position.POSITION_RIGHT) + assertThat(display.mOffset).isEqualTo(0) + } + } + + @Test + fun removeAllDisplays() { + val displayId = 1 + val width = 800.0 + val height = 600.0 + + topology.addDisplay(displayId, width, height) + topology.removeDisplay(displayId) + + assertThat(topology.mPrimaryDisplayId).isEqualTo(Display.INVALID_DISPLAY) + assertThat(topology.mRoot).isNull() + } + + @Test + fun removeDisplayThatDoesNotExist() { + val displayId = 1 + val width = 800.0 + val height = 600.0 + + topology.addDisplay(displayId, width, height) + topology.removeDisplay(3) + + assertThat(topology.mPrimaryDisplayId).isEqualTo(displayId) + + val display = topology.mRoot!! + assertThat(display.mDisplayId).isEqualTo(displayId) + assertThat(display.mWidth).isEqualTo(width) + assertThat(display.mHeight).isEqualTo(height) + assertThat(display.mChildren).isEmpty() + } }
\ No newline at end of file diff --git a/services/tests/displayservicetests/src/com/android/server/display/VirtualDisplayAdapterTest.java b/services/tests/displayservicetests/src/com/android/server/display/VirtualDisplayAdapterTest.java index 81e6cc3f546b..3ac7fb0dbe53 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/VirtualDisplayAdapterTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/VirtualDisplayAdapterTest.java @@ -21,71 +21,104 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; -import android.content.Context; import android.hardware.display.IVirtualDisplayCallback; import android.hardware.display.VirtualDisplayConfig; +import android.media.projection.IMediaProjection; import android.os.IBinder; import android.os.Process; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; +import android.testing.TestableContext; +import android.view.Surface; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; +import com.android.internal.R; import com.android.server.display.feature.DisplayManagerFlags; import com.android.server.testutils.TestHandler; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.ArrayList; +import java.util.List; + @SmallTest @RunWith(AndroidJUnit4.class) public class VirtualDisplayAdapterTest { + private static final int MAX_DEVICES = 3; + private static final int MAX_DEVICES_PER_PACKAGE = 2; + + @Rule + public final TestableContext mContext = new TestableContext( + InstrumentationRegistry.getInstrumentation().getContext()); + @Mock - Context mContextMock; + private VirtualDisplayAdapter.SurfaceControlDisplayFactory mMockSufaceControlDisplayFactory; @Mock - VirtualDisplayAdapter.SurfaceControlDisplayFactory mMockSufaceControlDisplayFactory; + private DisplayAdapter.Listener mMockListener; @Mock - DisplayAdapter.Listener mMockListener; + private IVirtualDisplayCallback mMockCallback; @Mock - IVirtualDisplayCallback mMockCallback; + private IBinder mMockBinder; @Mock - IBinder mMockBinder; + private IMediaProjection mMediaProjectionMock; - private TestHandler mHandler; + @Mock + private Surface mSurfaceMock; + + @Mock + private VirtualDisplayConfig mVirtualDisplayConfigMock; - private VirtualDisplayAdapter mVirtualDisplayAdapter; + private TestHandler mHandler; @Mock private DisplayManagerFlags mFeatureFlags; + private VirtualDisplayAdapter mAdapter; + + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Before public void setUp() { MockitoAnnotations.initMocks(this); + + mContext.getOrCreateTestableResources().addOverride(R.integer.config_virtualDisplayLimit, + MAX_DEVICES); + mContext.getOrCreateTestableResources().addOverride( + R.integer.config_virtualDisplayLimitPerPackage, MAX_DEVICES_PER_PACKAGE); + mHandler = new TestHandler(null); - mVirtualDisplayAdapter = new VirtualDisplayAdapter(new DisplayManagerService.SyncRoot(), - mContextMock, mHandler, mMockListener, mMockSufaceControlDisplayFactory, - mFeatureFlags); + mAdapter = new VirtualDisplayAdapter(new DisplayManagerService.SyncRoot(), mContext, + mHandler, mMockListener, mMockSufaceControlDisplayFactory, mFeatureFlags); when(mMockCallback.asBinder()).thenReturn(mMockBinder); } @Test - public void testCreatesVirtualDisplay() { + public void testCreateAndReleaseVirtualDisplay() { VirtualDisplayConfig config = new VirtualDisplayConfig.Builder("test", /* width= */ 1, /* height= */ 1, /* densityDpi= */ 1).build(); + int ownerUid = 10; - DisplayDevice result = mVirtualDisplayAdapter.createVirtualDisplayLocked(mMockCallback, - /* projection= */ null, /* ownerUid= */ 10, /* packageName= */ "testpackage", + DisplayDevice result = mAdapter.createVirtualDisplayLocked(mMockCallback, + /* projection= */ null, ownerUid, /* packageName= */ "testpackage", /* uniqueId= */ "uniqueId", /* surface= */ null, /* flags= */ 0, config); + assertNotNull(result); + result = mAdapter.releaseVirtualDisplayLocked(mMockBinder, ownerUid); assertNotNull(result); } @@ -98,7 +131,7 @@ public class VirtualDisplayAdapterTest { final String displayUniqueId = VirtualDisplayAdapter.generateDisplayUniqueId( packageName, Process.myUid(), config); - DisplayDevice result = mVirtualDisplayAdapter.createVirtualDisplayLocked( + DisplayDevice result = mAdapter.createVirtualDisplayLocked( mMockCallback, /* projection= */ null, /* ownerUid= */ 10, packageName, displayUniqueId, /* surface= */ null, /* flags= */ 0, config); @@ -114,14 +147,194 @@ public class VirtualDisplayAdapterTest { /* height= */ 1, /* densityDpi= */ 1).build(); VirtualDisplayConfig config2 = new VirtualDisplayConfig.Builder("test2", /* width= */ 1, /* height= */ 1, /* densityDpi= */ 1).build(); - mVirtualDisplayAdapter.createVirtualDisplayLocked(mMockCallback, /* projection= */ null, - /* ownerUid= */ 10, /* packageName= */ "testpackage", /* uniqueId= */ "uniqueId1", - /* surface= */ null, /* flags= */ 0, config1); - DisplayDevice result = mVirtualDisplayAdapter.createVirtualDisplayLocked(mMockCallback, + DisplayDevice result = mAdapter.createVirtualDisplayLocked(mMockCallback, /* projection= */ null, /* ownerUid= */ 10, /* packageName= */ "testpackage", - /* uniqueId= */ "uniqueId2", /* surface= */ null, /* flags= */ 0, config2); + /* uniqueId= */ "uniqueId1", /* surface= */ null, /* flags= */ 0, config1); + assertNotNull(result); + result = mAdapter.createVirtualDisplayLocked(mMockCallback, + /* projection= */ null, /* ownerUid= */ 10, /* packageName= */ "testpackage", + /* uniqueId= */ "uniqueId2", /* surface= */ null, /* flags= */ 0, config2); assertNull(result); } + + @Test + public void testCreateManyVirtualDisplays_LimitFlagDisabled() { + when(mFeatureFlags.isVirtualDisplayLimitEnabled()).thenReturn(false); + + // Displays for the same package + for (int i = 0; i < MAX_DEVICES_PER_PACKAGE * 2; i++) { + // Same owner UID + IVirtualDisplayCallback callback = createCallback(); + DisplayDevice device = mAdapter.createVirtualDisplayLocked(callback, + mMediaProjectionMock, 1234, "test.package", "123", + mSurfaceMock, /* flags= */ 0, mVirtualDisplayConfigMock); + assertNotNull(device); + } + + // Displays for different packages + for (int i = 0; i < MAX_DEVICES * 2; i++) { + // Same owner UID + IVirtualDisplayCallback callback = createCallback(); + DisplayDevice device = mAdapter.createVirtualDisplayLocked(callback, + mMediaProjectionMock, 1234 + i, "test.package", "123", + mSurfaceMock, /* flags= */ 0, mVirtualDisplayConfigMock); + assertNotNull(device); + } + } + + @Test + public void testCreateVirtualDisplay_MaxDisplaysPerPackage() { + when(mFeatureFlags.isVirtualDisplayLimitEnabled()).thenReturn(true); + List<IVirtualDisplayCallback> callbacks = new ArrayList<>(); + int ownerUid = 1234; + + for (int i = 0; i < MAX_DEVICES_PER_PACKAGE * 2; i++) { + // Same owner UID + IVirtualDisplayCallback callback = createCallback(); + DisplayDevice device = mAdapter.createVirtualDisplayLocked(callback, + mMediaProjectionMock, ownerUid, "test.package", "123", + mSurfaceMock, /* flags= */ 0, mVirtualDisplayConfigMock); + if (i < MAX_DEVICES_PER_PACKAGE) { + assertNotNull(device); + callbacks.add(callback); + } else { + assertNull(device); + } + } + + // Release one display + DisplayDevice device = mAdapter.releaseVirtualDisplayLocked(callbacks.get(0).asBinder(), + ownerUid); + assertNotNull(device); + callbacks.remove(0); + + // We should be able to create another display + IVirtualDisplayCallback callback = createCallback(); + device = mAdapter.createVirtualDisplayLocked(callback, mMediaProjectionMock, ownerUid, + "test.package", "123", mSurfaceMock, /* flags= */ 0, + mVirtualDisplayConfigMock); + assertNotNull(device); + callbacks.add(callback); + + // But only one + callback = createCallback(); + device = mAdapter.createVirtualDisplayLocked(callback, mMediaProjectionMock, ownerUid, + "test.package", "123", mSurfaceMock, /* flags= */ 0, + mVirtualDisplayConfigMock); + assertNull(device); + + // Release all the displays + for (IVirtualDisplayCallback cb : callbacks) { + device = mAdapter.releaseVirtualDisplayLocked(cb.asBinder(), ownerUid); + assertNotNull(device); + } + callbacks.clear(); + + // We should be able to create the max number of displays again + for (int i = 0; i < MAX_DEVICES_PER_PACKAGE * 2; i++) { + // Same owner UID + callback = createCallback(); + device = mAdapter.createVirtualDisplayLocked(callback, mMediaProjectionMock, ownerUid, + "test.package", "123", mSurfaceMock, /* flags= */ 0, + mVirtualDisplayConfigMock); + if (i < MAX_DEVICES_PER_PACKAGE) { + assertNotNull(device); + callbacks.add(callback); + } else { + assertNull(device); + } + } + + // We should be able to create a display for a different package + callback = createCallback(); + device = mAdapter.createVirtualDisplayLocked(callback, mMediaProjectionMock, ownerUid + 1, + "test.package", "123", mSurfaceMock, /* flags= */ 0, + mVirtualDisplayConfigMock); + assertNotNull(device); + callbacks.add(callback); + } + + @Test + public void testCreateVirtualDisplay_MaxDisplays() { + when(mFeatureFlags.isVirtualDisplayLimitEnabled()).thenReturn(true); + List<IVirtualDisplayCallback> callbacks = new ArrayList<>(); + int firstOwnerUid = 1000; + + for (int i = 0; i < MAX_DEVICES * 2; i++) { + // Different owner UID + IVirtualDisplayCallback callback = createCallback(); + DisplayDevice device = mAdapter.createVirtualDisplayLocked(callback, + mMediaProjectionMock, firstOwnerUid + i, "test.package", + "123", mSurfaceMock, /* flags= */ 0, mVirtualDisplayConfigMock); + if (i < MAX_DEVICES) { + assertNotNull(device); + callbacks.add(callback); + } else { + assertNull(device); + } + } + + // Release one display + DisplayDevice device = mAdapter.releaseVirtualDisplayLocked(callbacks.get(0).asBinder(), + firstOwnerUid); + assertNotNull(device); + callbacks.remove(0); + + // We should be able to create another display + IVirtualDisplayCallback callback = createCallback(); + device = mAdapter.createVirtualDisplayLocked(callback, mMediaProjectionMock, + firstOwnerUid, "test.package", "123", mSurfaceMock, /* flags= */ 0, + mVirtualDisplayConfigMock); + assertNotNull(device); + callbacks.add(callback); + + // But only one + callback = createCallback(); + device = mAdapter.createVirtualDisplayLocked(callback, mMediaProjectionMock, + firstOwnerUid, "test.package", "123", mSurfaceMock, /* flags= */ 0, + mVirtualDisplayConfigMock); + assertNull(device); + + // Release all the displays + for (int i = 0; i < callbacks.size(); i++) { + device = mAdapter.releaseVirtualDisplayLocked(callbacks.get(i).asBinder(), + firstOwnerUid + i); + assertNotNull(device); + } + callbacks.clear(); + + // We should be able to create the max number of displays again + for (int i = 0; i < MAX_DEVICES * 2; i++) { + // Different owner UID + callback = createCallback(); + device = mAdapter.createVirtualDisplayLocked(callback, mMediaProjectionMock, + firstOwnerUid + i, "test.package", "123", mSurfaceMock, + /* flags= */ 0, mVirtualDisplayConfigMock); + if (i < MAX_DEVICES) { + assertNotNull(device); + callbacks.add(callback); + } else { + assertNull(device); + } + } + } + + private IVirtualDisplayCallback createCallback() { + return new IVirtualDisplayCallback.Stub() { + + @Override + public void onPaused() { + } + + @Override + public void onResumed() { + } + + @Override + public void onStopped() { + } + }; + } } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java index 809e13c65225..6ccc03709b4f 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java @@ -29,6 +29,7 @@ import static android.app.ActivityManager.PROCESS_STATE_TOP; import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN; import static android.content.ContentResolver.SCHEME_CONTENT; +import static android.content.Intent.FILL_IN_ACTION; import static android.os.PowerExemptionManager.REASON_DENIED; import static android.os.UserHandle.USER_ALL; import static android.util.DebugUtils.valueToString; @@ -1300,6 +1301,45 @@ public class ActivityManagerServiceTest { .containsExactly(new Pair<>(USER_ID, 42)); } + @Test + @RequiresFlagsEnabled(android.security.Flags.FLAG_PREVENT_INTENT_REDIRECT) + public void testAddCreatorToken() { + Intent intent = new Intent(); + Intent extraIntent = new Intent("EXTRA_INTENT_ACTION"); + intent.putExtra("EXTRA_INTENT0", extraIntent); + + intent.collectExtraIntentKeys(); + mAms.addCreatorToken(intent); + + ActivityManagerService.IntentCreatorToken token = + (ActivityManagerService.IntentCreatorToken) extraIntent.getCreatorToken(); + assertThat(token).isNotNull(); + assertThat(token.getCreatorUid()).isEqualTo(mInjector.getCallingUid()); + } + + @Test + @RequiresFlagsEnabled(android.security.Flags.FLAG_PREVENT_INTENT_REDIRECT) + public void testAddCreatorTokenForFillingIntent() { + Intent intent = new Intent(); + Intent extraIntent = new Intent("EXTRA_INTENT_ACTION"); + intent.putExtra("EXTRA_INTENT0", extraIntent); + Intent fillinIntent = new Intent(); + Intent fillinExtraIntent = new Intent("FILLIN_EXTRA_INTENT_ACTION"); + fillinIntent.putExtra("FILLIN_EXTRA_INTENT0", fillinExtraIntent); + + fillinIntent.collectExtraIntentKeys(); + intent.fillIn(fillinIntent, FILL_IN_ACTION); + + mAms.addCreatorToken(fillinIntent); + + fillinExtraIntent = intent.getParcelableExtra("FILLIN_EXTRA_INTENT0", Intent.class); + + ActivityManagerService.IntentCreatorToken token = + (ActivityManagerService.IntentCreatorToken) fillinExtraIntent.getCreatorToken(); + assertThat(token).isNotNull(); + assertThat(token.getCreatorUid()).isEqualTo(mInjector.getCallingUid()); + } + private void verifyWaitingForNetworkStateUpdate(long curProcStateSeq, long lastNetworkUpdatedProcStateSeq, final long procStateSeqToWait, boolean expectWait) throws Exception { diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationStartInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationStartInfoTest.java index e863f1574932..e678acc092e9 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationStartInfoTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationStartInfoTest.java @@ -39,6 +39,7 @@ import android.content.pm.PackageManagerInternal; import android.os.FileUtils; import android.os.Handler; import android.os.HandlerThread; +import android.os.Parcel; import android.os.Process; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; @@ -580,6 +581,50 @@ public class ApplicationStartInfoTest { assertTrue(mAppStartInfoTracker.mMonotonicClock.monotonicTime() >= originalMonotonicTime); } + /** + * Test to confirm that parcel read and write implementations match, correctly loading records + * with the same values and leaving no data unread. + */ + @Test + public void testParcelReadWriteMatch() throws Exception { + // Create a start info records with all fields set. + ApplicationStartInfo startInfo = new ApplicationStartInfo(1234L); + startInfo.setPid(123); + startInfo.setRealUid(987); + startInfo.setPackageUid(654); + startInfo.setDefiningUid(321); + startInfo.setReason(ApplicationStartInfo.START_REASON_LAUNCHER); + startInfo.setStartupState(ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN); + startInfo.setStartType(ApplicationStartInfo.START_TYPE_WARM); + startInfo.setLaunchMode(ApplicationStartInfo.LAUNCH_MODE_SINGLE_TOP); + startInfo.setPackageName(APP_1_PACKAGE_NAME); + startInfo.setProcessName(APP_1_PROCESS_NAME); + startInfo.addStartupTimestamp(ApplicationStartInfo.START_TIMESTAMP_LAUNCH, 999L); + startInfo.addStartupTimestamp(ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME, 888L); + startInfo.setForceStopped(true); + startInfo.setStartComponent(ApplicationStartInfo.START_COMPONENT_OTHER); + startInfo.setIntent(buildIntent(COMPONENT)); + + // Write the start info to a parcel. + Parcel parcel = Parcel.obtain(); + startInfo.writeToParcel(parcel, 0 /* flags */); + + // Set the data position back to 0 so it's ready to be read. + parcel.setDataPosition(0); + + // Now load the record from the parcel. + ApplicationStartInfo startInfoFromParcel = new ApplicationStartInfo(parcel); + + // Make sure there is no unread data remaining in the parcel, and confirm that the loaded + // start info object is equal to the one it was written from. Check dataAvail first as if + // that check fails then the next check will fail too, but knowing the status of this check + // will tell us that we're missing a read or write. Check the objects are equals second as + // if the avail check passes and equals fails, then we know we're reading all the data just + // not to the correct fields. + assertEquals(0, parcel.dataAvail()); + assertTrue(startInfo.equals(startInfoFromParcel)); + } + private static <T> void setFieldValue(Class clazz, Object obj, String fieldName, T val) { try { Field field = clazz.getDeclaredField(fieldName); diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java index d08cdc718a82..769f071e3ddc 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java @@ -265,19 +265,19 @@ public class ApexManagerTest { } @Test - public void testSubmitStagedSession_throwRunTimeException() throws RemoteException { + public void testSubmitStagedSession_throwPackageManagerExceptionOnRemoteException() + throws RemoteException { doThrow(RemoteException.class).when(mApexService).submitStagedSession(any(), any()); - assertThrows(RuntimeException.class, + assertThrows(PackageManagerException.class, () -> mApexManager.submitStagedSession(testParamsWithChildren())); } @Test - public void testGetStagedApexInfos_throwRunTimeException() throws RemoteException { + public void testGetStagedApexInfos_returnsEmptyOnRemoteException() throws RemoteException { doThrow(RemoteException.class).when(mApexService).getStagedApexInfos(any()); - assertThrows(RuntimeException.class, - () -> mApexManager.getStagedApexInfos(testParamsWithChildren())); + assertThat(mApexManager.getStagedApexInfos(testParamsWithChildren())).hasLength(0); } @Test @@ -298,10 +298,11 @@ public class ApexManagerTest { } @Test - public void testMarkStagedSessionReady_throwRunTimeException() throws RemoteException { + public void testMarkStagedSessionReady_throwPackageManagerExceptionOnRemoteException() + throws RemoteException { doThrow(RemoteException.class).when(mApexService).markStagedSessionReady(anyInt()); - assertThrows(RuntimeException.class, + assertThrows(PackageManagerException.class, () -> mApexManager.markStagedSessionReady(TEST_SESSION_ID)); } diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS index 5181af14ff65..aa22790022c5 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS +++ b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS @@ -2,3 +2,4 @@ include /services/core/java/com/android/server/pm/OWNERS per-file BackgroundDexOptServiceUnitTest.java = file:/services/core/java/com/android/server/pm/dex/OWNERS per-file StagingManagerTest.java = dariofreni@google.com, ioffe@google.com, olilan@google.com +per-file ApexManagerTest.java = dariofreni@google.com, ioffe@google.com, olilan@google.com diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java index 24e7242792fb..54ee2a3ae0d5 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java @@ -33,6 +33,7 @@ import android.os.Handler; import android.os.IRemoteCallback; import android.os.Looper; import android.os.Process; +import android.os.UserHandle; import android.util.SparseArray; import org.junit.After; @@ -340,6 +341,24 @@ public class PackageMonitorCallbackHelperTest { verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(any()); } + @Test + public void registerPackageMonitor_callbackNotInAllowListSystemUidSecondUser_callbackIsCalled() + throws Exception { + IRemoteCallback callback = createMockPackageMonitorCallback(); + int userId = 10; + int fakeAppId = 12345; + SparseArray<int[]> broadcastAllowList = new SparseArray<>(); + broadcastAllowList.put(userId, new int[]{UserHandle.getUid(userId, fakeAppId)}); + + mPackageMonitorCallbackHelper.registerPackageMonitorCallback(callback, userId, + UserHandle.getUid(userId, Process.SYSTEM_UID)); + mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED, + FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{userId}, + null /* instantUserIds */, broadcastAllowList, mHandler, null /* filterExtras */); + + verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).times(1)).sendResult(any()); + } + private IRemoteCallback createMockPackageMonitorCallback() { return spy(new IRemoteCallback.Stub() { @Override diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java index 6f9b8dfc023d..39acd8dd816a 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java @@ -756,7 +756,8 @@ public class StagingManagerTest { /* isApplied */false, /* stagedSessionErrorCode */ PackageManager.INSTALL_UNKNOWN, /* stagedSessionErrorMessage */ "no error", - /* preVerifiedDomains */ null); + /* preVerifiedDomains */ null, + /* verifierController */ null); StagingManager.StagedSession stagedSession = spy(session.mStagedSession); doReturn(packageName).when(stagedSession).getPackageName(); diff --git a/services/tests/powerservicetests/src/com/android/server/power/LowPowerStandbyControllerTest.java b/services/tests/powerservicetests/src/com/android/server/power/LowPowerStandbyControllerTest.java index 0e815d0eab95..3e731a322d4e 100644 --- a/services/tests/powerservicetests/src/com/android/server/power/LowPowerStandbyControllerTest.java +++ b/services/tests/powerservicetests/src/com/android/server/power/LowPowerStandbyControllerTest.java @@ -163,6 +163,7 @@ public class LowPowerStandbyControllerTest { addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock); when(mIPowerManagerMock.isInteractive()).thenReturn(true); + when(mIPowerManagerMock.isDisplayInteractive(anyInt())).thenReturn(true); when(mDeviceConfigWrapperMock.enableCustomPolicy()).thenReturn(true); when(mDeviceConfigWrapperMock.enableStandbyPorts()).thenReturn(true); @@ -899,11 +900,13 @@ public class LowPowerStandbyControllerTest { private void setInteractive() throws Exception { when(mIPowerManagerMock.isInteractive()).thenReturn(true); + when(mIPowerManagerMock.isDisplayInteractive(anyInt())).thenReturn(true); mContextSpy.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON)); } private void setNonInteractive() throws Exception { when(mIPowerManagerMock.isInteractive()).thenReturn(false); + when(mIPowerManagerMock.isDisplayInteractive(anyInt())).thenReturn(false); mContextSpy.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF)); } 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 54a02cf3cda3..e9e21dee16a8 100644 --- a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java @@ -1659,6 +1659,64 @@ public class PowerManagerServiceTest { } @Test + public void testIsWakeLockLevelSupported_returnsCorrectValue() { + createService(); + startSystem(); + PowerManagerService.BinderService service = mService.getBinderServiceInstance(); + assertThat(service.isWakeLockLevelSupported(PowerManager.PARTIAL_WAKE_LOCK)).isTrue(); + assertThat(service.isWakeLockLevelSupported(PowerManager.SCREEN_BRIGHT_WAKE_LOCK)).isTrue(); + assertThat(service.isWakeLockLevelSupported(PowerManager.FULL_WAKE_LOCK)).isTrue(); + assertThat(service.isWakeLockLevelSupported(PowerManager.DOZE_WAKE_LOCK)).isTrue(); + assertThat(service.isWakeLockLevelSupported(PowerManager.DRAW_WAKE_LOCK)).isTrue(); + + when(mDisplayManagerInternalMock.isProximitySensorAvailable(eq(Display.DEFAULT_DISPLAY))) + .thenReturn(true); + assertThat(service.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) + .isTrue(); + + when(mDisplayManagerInternalMock.isProximitySensorAvailable(eq(Display.DEFAULT_DISPLAY))) + .thenReturn(false); + assertThat(service.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) + .isFalse(); + } + + @Test + public void testIsWakeLockLevelSupportedWithDisplayId_nonDefaultDisplay_returnsCorrectValue() { + createService(); + startSystem(); + int displayId = Display.DEFAULT_DISPLAY + 1; + PowerManagerService.BinderService service = mService.getBinderServiceInstance(); + assertThat(service.isWakeLockLevelSupportedWithDisplayId( + PowerManager.PARTIAL_WAKE_LOCK, displayId)) + .isTrue(); + assertThat(service.isWakeLockLevelSupportedWithDisplayId( + PowerManager.SCREEN_BRIGHT_WAKE_LOCK, displayId)) + .isTrue(); + assertThat(service.isWakeLockLevelSupportedWithDisplayId( + PowerManager.FULL_WAKE_LOCK, displayId)) + .isTrue(); + assertThat(service.isWakeLockLevelSupportedWithDisplayId( + PowerManager.DOZE_WAKE_LOCK, displayId)) + .isTrue(); + assertThat(service.isWakeLockLevelSupportedWithDisplayId( + PowerManager.DRAW_WAKE_LOCK, displayId)) + .isTrue(); + + when(mDisplayManagerInternalMock.isProximitySensorAvailable(eq(displayId))) + .thenReturn(true); + assertThat(service.isWakeLockLevelSupportedWithDisplayId( + PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, displayId)) + .isTrue(); + + when(mDisplayManagerInternalMock.isProximitySensorAvailable(eq(displayId))) + .thenReturn(false); + assertThat(service.isWakeLockLevelSupportedWithDisplayId( + PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, displayId)) + .isFalse(); + } + + + @Test public void testWakeLock_affectsProperDisplayGroup() { final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener = @@ -1699,6 +1757,47 @@ public class PowerManagerServiceTest { } @Test + public void testWakeLock_nonDefaultDisplay_affectsProperDisplayGroup() { + final int nonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1; + final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; + final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener = + new AtomicReference<>(); + doAnswer((Answer<Void>) invocation -> { + listener.set(invocation.getArgument(0)); + return null; + }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any()); + final DisplayInfo info = new DisplayInfo(); + info.displayGroupId = nonDefaultDisplayGroupId; + when(mDisplayManagerInternalMock.getDisplayInfo(nonDefaultDisplayId)).thenReturn(info); + + final String pkg = mContextSpy.getOpPackageName(); + final Binder token = new Binder(); + final String tag = "testWakeLock_nonDefaultDisplay_affectsProperDisplayGroup"; + + setMinimumScreenOffTimeoutConfig(5); + createService(); + startSystem(); + listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); + + mService.getBinderServiceInstance().acquireWakeLock(token, + PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg, + null /* workSource */, null /* historyTag */, nonDefaultDisplayId, null); + + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( + WAKEFULNESS_AWAKE); + assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( + WAKEFULNESS_AWAKE); + + advanceTime(15000); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( + WAKEFULNESS_ASLEEP); + assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( + WAKEFULNESS_AWAKE); + } + + @Test public void testInvalidDisplayGroupWakeLock_affectsAllDisplayGroups() { final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener = @@ -2590,14 +2689,15 @@ public class PowerManagerServiceTest { when(mDisplayManagerInternalMock.getDisplayInfo(nonDefaultDisplay)).thenReturn(info); createService(); startSystem(); - listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); - verify(mInvalidateInteractiveCachesMock).call(); + listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); + verify(mInvalidateInteractiveCachesMock, times(2)).call(); + mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, mClock.now(), 0, PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, null, null); - verify(mInvalidateInteractiveCachesMock, times(2)).call(); + verify(mInvalidateInteractiveCachesMock, times(3)).call(); } @Test @@ -2616,14 +2716,15 @@ public class PowerManagerServiceTest { when(mDisplayManagerInternalMock.getDisplayInfo(nonDefaultDisplay)).thenReturn(info); createService(); startSystem(); - listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); - verify(mInvalidateInteractiveCachesMock).call(); + listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); + verify(mInvalidateInteractiveCachesMock, times(2)).call(); + mService.setWakefulnessLocked(nonDefaultDisplayGroupId, WAKEFULNESS_ASLEEP, mClock.now(), 0, PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, null, null); - verify(mInvalidateInteractiveCachesMock, times(2)).call(); + verify(mInvalidateInteractiveCachesMock, times(3)).call(); } @Test diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java index 1426d5d20419..c4b4afd13a60 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java @@ -69,6 +69,7 @@ import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.android.internal.R; +import com.android.internal.os.BackgroundThread; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.test.FakeSettingsProvider; import com.android.server.LocalServices; @@ -92,6 +93,8 @@ import org.mockito.stubbing.Answer; import org.testng.Assert; import java.util.Locale; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; @RunWith(AndroidJUnit4.class) public class FullScreenMagnificationControllerTest { @@ -1440,19 +1443,42 @@ public class FullScreenMagnificationControllerTest { @Test public void persistScale_setValueWhenScaleIsOne_nothingChanged() { + register(TEST_DISPLAY); final float persistedScale = mFullScreenMagnificationController.getPersistedScale(TEST_DISPLAY); PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER; - mFullScreenMagnificationController.setScale(DISPLAY_0, 1.0f, pivotPoint.x, pivotPoint.y, + mFullScreenMagnificationController.setScale(TEST_DISPLAY, 1.0f, pivotPoint.x, pivotPoint.y, false, SERVICE_ID_1); mFullScreenMagnificationController.persistScale(TEST_DISPLAY); + // persistScale may post a task to a background thread. Let's wait for it completes. + waitForBackgroundThread(); Assert.assertEquals(mFullScreenMagnificationController.getPersistedScale(TEST_DISPLAY), persistedScale); } @Test + public void persistScale_setValuesOnMultipleDisplays() { + register(DISPLAY_0); + register(DISPLAY_1); + final PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER; + mFullScreenMagnificationController.setScale(DISPLAY_0, 3.0f, pivotPoint.x, pivotPoint.y, + false, SERVICE_ID_1); + mFullScreenMagnificationController.persistScale(DISPLAY_0); + mFullScreenMagnificationController.setScale(DISPLAY_1, 4.0f, pivotPoint.x, pivotPoint.y, + false, SERVICE_ID_1); + mFullScreenMagnificationController.persistScale(DISPLAY_1); + + // persistScale may post a task to a background thread. Let's wait for it completes. + waitForBackgroundThread(); + Assert.assertEquals(mFullScreenMagnificationController.getPersistedScale(DISPLAY_0), + 3.0f); + Assert.assertEquals(mFullScreenMagnificationController.getPersistedScale(DISPLAY_1), + 4.0f); + } + + @Test public void testOnContextChanged_alwaysOnFeatureDisabled_resetMagnification() { setScaleToMagnifying(); @@ -1494,6 +1520,15 @@ public class FullScreenMagnificationControllerTest { ); } + private static void waitForBackgroundThread() { + final CompletableFuture<Void> future = new CompletableFuture<>(); + BackgroundThread.getHandler().post(() -> future.complete(null)); + try { + future.get(); + } catch (InterruptedException | ExecutionException ignore) { + } + } + private void setScaleToMagnifying() { register(DISPLAY_0); float scale = 2.0f; diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java index 87fe6cf8f283..6aa8a32dd7db 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java @@ -300,7 +300,8 @@ public class MagnificationConnectionManagerTest { mMagnificationConnectionManager.setConnection(mMockConnection.getConnection()); mMagnificationConnectionManager.enableWindowMagnification(TEST_DISPLAY, 2.5f, NaN, NaN); - mMagnificationConnectionManager.setScale(TEST_DISPLAY, 10.0f); + mMagnificationConnectionManager.setScale(TEST_DISPLAY, + MagnificationScaleProvider.MAX_SCALE * 2.f); assertEquals(mMagnificationConnectionManager.getScale(TEST_DISPLAY), MagnificationScaleProvider.MAX_SCALE); diff --git a/services/tests/servicestests/src/com/android/server/audio/VolumeHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/VolumeHelperTest.java index c305fd92cfbb..dc8c1b9c8a10 100644 --- a/services/tests/servicestests/src/com/android/server/audio/VolumeHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/audio/VolumeHelperTest.java @@ -290,6 +290,9 @@ public class VolumeHelperTest { // --------------- Volume Stream APIs --------------- @Test public void setStreamVolume_callsASSetStreamVolumeIndex() throws Exception { + assumeFalse("Skipping setStreamVolume_callsASSetStreamVolumeIndex on automotive", + mIsAutomotive); + int newIndex = circularNoMinMaxIncrementVolume(STREAM_MUSIC); mAudioService.setDeviceForStream(STREAM_MUSIC, DEVICE_OUT_USB_DEVICE); @@ -313,6 +316,9 @@ public class VolumeHelperTest { @Test public void adjustStreamVolume_callsASSetStreamVolumeIndex() throws Exception { + assumeFalse("Skipping adjustStreamVolume_callsASSetStreamVolumeIndex on automotive", + mIsAutomotive); + mAudioService.setDeviceForStream(STREAM_MUSIC, DEVICE_OUT_USB_DEVICE); mAudioService.adjustStreamVolume(STREAM_MUSIC, ADJUST_LOWER, /*flags=*/0, mContext.getOpPackageName()); @@ -324,6 +330,9 @@ public class VolumeHelperTest { @Test public void handleVolumeKey_callsASSetStreamVolumeIndex() throws Exception { + assumeFalse("Skipping handleVolumeKey_callsASSetStreamVolumeIndex on automotive", + mIsAutomotive); + final KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_UP); mAudioService.setDeviceForStream(STREAM_MUSIC, DEVICE_OUT_USB_DEVICE); @@ -339,6 +348,9 @@ public class VolumeHelperTest { @Test public void setVolumeGroupVolumeIndex_callsASSetVolumeIndexForAttributes() throws Exception { + assumeFalse( + "Skipping setVolumeGroupVolumeIndex_callsASSetVolumeIndexForAttributes on " + + "automotive", mIsAutomotive); assumeNotNull(mAudioMusicVolumeGroup); mAudioService.setDeviceForStream(STREAM_MUSIC, DEVICE_OUT_USB_DEVICE); @@ -347,8 +359,8 @@ public class VolumeHelperTest { mContext.getOpPackageName(), /*attributionTag*/null); mTestLooper.dispatchAll(); - verify(mSpyAudioSystem).setVolumeIndexForAttributes( - any(), anyInt(), eq(DEVICE_OUT_USB_DEVICE)); + verify(mSpyAudioSystem).setVolumeIndexForAttributes(any(), anyInt(), + eq(DEVICE_OUT_USB_DEVICE)); } @Test @@ -366,6 +378,7 @@ public class VolumeHelperTest { @Test public void check_getVolumeGroupVolumeIndex() throws Exception { + assumeFalse("Skipping check_getVolumeGroupVolumeIndex on automotive", mIsAutomotive); assumeNotNull(mAudioMusicVolumeGroup); int newIndex = circularNoMinMaxIncrementVolume(STREAM_MUSIC); @@ -374,10 +387,9 @@ public class VolumeHelperTest { newIndex, /*flags=*/0, mContext.getOpPackageName(), /*attributionTag*/null); mTestLooper.dispatchAll(); - assertEquals(mAudioService.getVolumeGroupVolumeIndex(mAudioMusicVolumeGroup.getId()), - newIndex); - assertEquals(mAudioService.getStreamVolume(STREAM_MUSIC), - newIndex); + assertEquals(newIndex, + mAudioService.getVolumeGroupVolumeIndex(mAudioMusicVolumeGroup.getId())); + assertEquals(newIndex, mAudioService.getStreamVolume(STREAM_MUSIC)); } @Test @@ -432,6 +444,7 @@ public class VolumeHelperTest { @Test public void flagAbsVolume_onBtDevice_changesVolume() throws Exception { + assumeFalse("Skipping flagAbsVolume_onBtDevice_changesVolume on automotive", mIsAutomotive); mAudioService.setDeviceForStream(STREAM_NOTIFICATION, DEVICE_OUT_BLE_SPEAKER); int newIndex = circularNoMinMaxIncrementVolume(STREAM_NOTIFICATION); @@ -494,7 +507,7 @@ public class VolumeHelperTest { mContext.getOpPackageName()); mTestLooper.dispatchAll(); - assertEquals(mAudioService.getRingerModeInternal(), RINGER_MODE_VIBRATE); + assertEquals(RINGER_MODE_VIBRATE, mAudioService.getRingerModeInternal()); } // --------------------- Permission tests --------------------- @@ -538,6 +551,7 @@ public class VolumeHelperTest { // ----------------- AudioDeviceVolumeManager ----------------- @Test public void setDeviceVolume_checkIndex() { + assumeFalse("Skipping setDeviceVolume_checkIndex on automotive", mIsAutomotive); final int minIndex = mAm.getStreamMinVolume(STREAM_MUSIC); final int maxIndex = mAm.getStreamMaxVolume(STREAM_MUSIC); final int midIndex = (minIndex + maxIndex) / 2; @@ -553,21 +567,17 @@ public class VolumeHelperTest { mAudioService.setDeviceVolume(volMin, usbDevice, mContext.getOpPackageName()); mTestLooper.dispatchAll(); - if (!mIsAutomotive) { - // there is a min/max index mismatch in automotive - assertEquals(mAudioService.getDeviceVolume(volMin, usbDevice, - mContext.getOpPackageName()), volMin); - } + // there is a min/max index mismatch in automotive + assertEquals(volMin, mAudioService.getDeviceVolume(volMin, usbDevice, + mContext.getOpPackageName())); verify(mSpyAudioSystem, atLeast(1)).setStreamVolumeIndexAS( eq(STREAM_MUSIC), anyInt(), eq(AudioSystem.DEVICE_OUT_USB_DEVICE)); mAudioService.setDeviceVolume(volMid, usbDevice, mContext.getOpPackageName()); mTestLooper.dispatchAll(); - if (!mIsAutomotive) { - // there is a min/max index mismatch in automotive - assertEquals(mAudioService.getDeviceVolume(volMid, usbDevice, - mContext.getOpPackageName()), volMid); - } + // there is a min/max index mismatch in automotive + assertEquals(volMid, mAudioService.getDeviceVolume(volMid, usbDevice, + mContext.getOpPackageName())); verify(mSpyAudioSystem, atLeast(1)).setStreamVolumeIndexAS( eq(STREAM_MUSIC), anyInt(), eq(AudioSystem.DEVICE_OUT_USB_DEVICE)); } @@ -603,9 +613,8 @@ public class VolumeHelperTest { mAudioService.setDeviceVolume(volCur, bleDevice, mContext.getOpPackageName()); mTestLooper.dispatchAll(); - assertEquals( - mAudioService.getDeviceVolume(volCur, bleDevice, mContext.getOpPackageName()), - volCur); + assertEquals(volCur, + mAudioService.getDeviceVolume(volCur, bleDevice, mContext.getOpPackageName())); // Stream volume changes verify(mSpyAudioSystem, atLeast(1)).setStreamVolumeIndexAS( STREAM_MUSIC, targetIndex, @@ -618,9 +627,8 @@ public class VolumeHelperTest { mAudioService.setDeviceVolume(volIndex4, bleDevice, mContext.getOpPackageName()); mTestLooper.dispatchAll(); - assertEquals( - mAudioService.getDeviceVolume(volIndex4, bleDevice, mContext.getOpPackageName()), - volIndex4); + assertEquals(volIndex4, + mAudioService.getDeviceVolume(volIndex4, bleDevice, mContext.getOpPackageName())); verify(mSpyAudioSystem, atLeast(1)).setStreamVolumeIndexAS( STREAM_MUSIC, maxIndex, AudioSystem.DEVICE_OUT_BLE_HEADSET); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java b/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java index efc2d974a7cc..1bea371c5786 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/UtilsTest.java @@ -217,7 +217,13 @@ public class UtilsTest { doNothing().when(mContext).enforceCallingOrSelfPermission( eq(SET_BIOMETRIC_DIALOG_ADVANCED), any()); - assertTrue(Utils.isValidAuthenticatorConfig(mContext, Authenticators.MANDATORY_BIOMETRICS)); + if (Flags.mandatoryBiometrics()) { + assertTrue(Utils.isValidAuthenticatorConfig(mContext, + Authenticators.MANDATORY_BIOMETRICS)); + } else { + assertFalse(Utils.isValidAuthenticatorConfig(mContext, + Authenticators.MANDATORY_BIOMETRICS)); + } // The rest of the bits are not allowed to integrate with the public APIs for (int i = 8; i < 32; i++) { diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java index 4d067f6bfc62..e6c34ca68c75 100644 --- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java @@ -150,6 +150,7 @@ public class VirtualDeviceManagerServiceTest { private static final String NONBLOCKED_APP_PACKAGE_NAME = "com.someapp"; private static final String PERMISSION_CONTROLLER_PACKAGE_NAME = "com.android.permissioncontroller"; + private static final String VIRTUAL_DEVICE_OWNER_PACKAGE = "com.android.virtualdevice.test"; private static final String SETTINGS_PACKAGE_NAME = "com.android.settings"; private static final String VENDING_PACKAGE_NAME = "com.android.vending"; private static final String GOOGLE_DIALER_PACKAGE_NAME = "com.google.android.dialer"; @@ -296,11 +297,10 @@ public class VirtualDeviceManagerServiceTest { private Intent createRestrictedActivityBlockedIntent(Set<String> displayCategories, String targetDisplayCategory) { when(mDisplayManagerInternalMock.createVirtualDisplay(any(), any(), any(), any(), - eq(NONBLOCKED_APP_PACKAGE_NAME))).thenReturn(DISPLAY_ID_1); + eq(VIRTUAL_DEVICE_OWNER_PACKAGE))).thenReturn(DISPLAY_ID_1); VirtualDisplayConfig config = new VirtualDisplayConfig.Builder("display", 640, 480, 420).setDisplayCategories(displayCategories).build(); - mDeviceImpl.createVirtualDisplay(config, mVirtualDisplayCallback, - NONBLOCKED_APP_PACKAGE_NAME); + mDeviceImpl.createVirtualDisplay(config, mVirtualDisplayCallback); GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( DISPLAY_ID_1); doNothing().when(mContext).startActivityAsUser(any(), any(), any()); @@ -1950,7 +1950,7 @@ public class VirtualDeviceManagerServiceTest { mVirtualDeviceLog, new Binder(), new AttributionSource( - ownerUid, "com.android.virtualdevice.test", "virtualdevice"), + ownerUid, VIRTUAL_DEVICE_OWNER_PACKAGE, "virtualdevice"), virtualDeviceId, mInputController, mCameraAccessController, @@ -1971,8 +1971,7 @@ public class VirtualDeviceManagerServiceTest { private void addVirtualDisplay(VirtualDeviceImpl virtualDevice, int displayId) { when(mDisplayManagerInternalMock.createVirtualDisplay(any(), eq(mVirtualDisplayCallback), eq(virtualDevice), any(), any())).thenReturn(displayId); - virtualDevice.createVirtualDisplay(VIRTUAL_DISPLAY_CONFIG, mVirtualDisplayCallback, - NONBLOCKED_APP_PACKAGE_NAME); + virtualDevice.createVirtualDisplay(VIRTUAL_DISPLAY_CONFIG, mVirtualDisplayCallback); final String uniqueId = UNIQUE_ID + displayId; doAnswer(inv -> { final DisplayInfo displayInfo = new DisplayInfo(); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakePowerManagerWrapper.java b/services/tests/servicestests/src/com/android/server/hdmi/FakePowerManagerWrapper.java index 04f921f495a2..629f9683a547 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/FakePowerManagerWrapper.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/FakePowerManagerWrapper.java @@ -26,6 +26,7 @@ final class FakePowerManagerWrapper extends PowerManagerWrapper { private boolean mInteractive; private WakeLockWrapper mWakeLock; private boolean mWasWakeLockInstanceCreated = false; + private boolean mIsLowPowerStandbyEnabled = false; FakePowerManagerWrapper(@NonNull Context context) { @@ -60,6 +61,15 @@ final class FakePowerManagerWrapper extends PowerManagerWrapper { } @Override + boolean isLowPowerStandbyEnabled() { + return mIsLowPowerStandbyEnabled; + } + + void setIsLowPowerStandbyEnabled(boolean isLowPowerStandbyEnabled) { + mIsLowPowerStandbyEnabled = isLowPowerStandbyEnabled; + } + + @Override WakeLockWrapper newWakeLock(int levelAndFlags, String tag) { if (mWakeLock == null) { mWakeLock = new FakeWakeLockWrapper(); 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 2d957401e6bd..935c8b8720fb 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java @@ -70,6 +70,7 @@ import org.junit.runners.JUnit4; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.concurrent.TimeUnit; @SmallTest @@ -113,6 +114,10 @@ public class HdmiCecLocalDeviceTvTest { private boolean mWokenUp; private boolean mEarcBlocksArc; private List<DeviceEventListener> mDeviceEventListeners = new ArrayList<>(); + private List<VendorCommandListener> mVendorCommandListeners = new ArrayList<>(); + private boolean mDisableCecOnStandbyByLowEnergyMode; + private boolean mWasCecDisabledOnStandbyByLowEnergyMode; + private boolean mUseHdmiCecPowerStatusController; private class DeviceEventListener { private HdmiDeviceInfo mDevice; @@ -132,6 +137,30 @@ public class HdmiCecLocalDeviceTvTest { } } + private class VendorCommandListener { + private boolean mEnabled; + private int mReason; + + VendorCommandListener(boolean enabled, int reason) { + this.mEnabled = enabled; + this.mReason = reason; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof VendorCommandListener)) { + return false; + } + VendorCommandListener other = (VendorCommandListener) obj; + return other.mReason == mReason && other.mEnabled == mEnabled; + } + + @Override + public int hashCode() { + return Objects.hash(mEnabled, mReason); + } + } + private FakeAudioFramework mAudioFramework; private AudioManagerWrapper mAudioManager; @@ -169,6 +198,9 @@ public class HdmiCecLocalDeviceTvTest { @Override boolean isPowerStandby() { + if (mUseHdmiCecPowerStatusController) { + return mPowerStatusController.isPowerStatusStandby(); + } return false; } @@ -188,6 +220,13 @@ public class HdmiCecLocalDeviceTvTest { } @Override + boolean invokeVendorCommandListenersOnControlStateChanged( + boolean enabled, int reason) { + mVendorCommandListeners.add(new VendorCommandListener(enabled, reason)); + return true; + } + + @Override protected boolean earcBlocksArcConnection() { return mEarcBlocksArc; } @@ -196,6 +235,21 @@ public class HdmiCecLocalDeviceTvTest { protected void sendBroadcastAsUser(@RequiresPermission Intent intent) { // do nothing } + + @Override + protected boolean getDisableCecOnStandbyByLowEnergyMode() { + return mDisableCecOnStandbyByLowEnergyMode; + } + + @Override + protected boolean getWasCecDisabledOnStandbyByLowEnergyMode() { + return mWasCecDisabledOnStandbyByLowEnergyMode; + } + + @Override + protected void setWasCecDisabledOnStandbyByLowEnergyMode(boolean value) { + mWasCecDisabledOnStandbyByLowEnergyMode = value; + } }; mHdmiControlService.setIoLooper(mMyLooper); @@ -241,6 +295,9 @@ public class HdmiCecLocalDeviceTvTest { mHdmiControlService.getHdmiCecConfig().setIntValue( sad, HdmiControlManager.QUERY_SAD_DISABLED); } + mWasCecDisabledOnStandbyByLowEnergyMode = false; + mDisableCecOnStandbyByLowEnergyMode = false; + mUseHdmiCecPowerStatusController = false; mNativeWrapper.clearResultMessages(); } @@ -2238,6 +2295,92 @@ public class HdmiCecLocalDeviceTvTest { assertThat(mHdmiCecLocalDeviceTv.getActions(SystemAudioActionFromTv.class)).hasSize(1); } + @Test + public void lowEnergyMode_disableCecOnStandby_reEnableOnWakeup() { + mDisableCecOnStandbyByLowEnergyMode = true; + mUseHdmiCecPowerStatusController = true; + mPowerManager.setIsLowPowerStandbyEnabled(true); + + assertEquals(mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED), + HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); + mHdmiControlService.onStandby(STANDBY_SCREEN_OFF); + mTestLooper.dispatchAll(); + + assertEquals(mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED), + HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); + assertTrue(mWasCecDisabledOnStandbyByLowEnergyMode); + mHdmiControlService.onWakeUp(WAKE_UP_SCREEN_ON); + mTestLooper.dispatchAll(); + + assertEquals(mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED), + HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); + assertFalse(mWasCecDisabledOnStandbyByLowEnergyMode); + } + + @Test + public void lowEnergyMode_disableCecBeforeStandby_cecStaysDisabledOnWakeup() { + mDisableCecOnStandbyByLowEnergyMode = true; + mUseHdmiCecPowerStatusController = true; + mPowerManager.setIsLowPowerStandbyEnabled(true); + + assertEquals(mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED), + HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); + mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().setIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, + HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); + mTestLooper.dispatchAll(); + + mHdmiControlService.onStandby(STANDBY_SCREEN_OFF); + mTestLooper.dispatchAll(); + + assertEquals(mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED), + HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); + assertFalse(mWasCecDisabledOnStandbyByLowEnergyMode); + mHdmiControlService.onWakeUp(WAKE_UP_SCREEN_ON); + mTestLooper.dispatchAll(); + + assertEquals(mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED), + HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); + } + + @Test + public void lowEnergyMode_onWakeUp_reEnableCec_invokeVendorCommandListeners() { + mDisableCecOnStandbyByLowEnergyMode = true; + mUseHdmiCecPowerStatusController = true; + mPowerManager.setIsLowPowerStandbyEnabled(true); + VendorCommandListener vendorCommandListenerInvocationWakeup = new VendorCommandListener( + true, HdmiControlManager.CONTROL_STATE_CHANGED_REASON_WAKEUP); + VendorCommandListener vendorCommandListenerInvocationSettingChange = + new VendorCommandListener(true, + HdmiControlManager.CONTROL_STATE_CHANGED_REASON_WAKEUP); + + assertEquals(mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED), + HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); + mHdmiControlService.onStandby(STANDBY_SCREEN_OFF); + mTestLooper.dispatchAll(); + + assertEquals(mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().getIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED), + HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); + assertTrue(mWasCecDisabledOnStandbyByLowEnergyMode); + mVendorCommandListeners.clear(); + mTestLooper.dispatchAll(); + + mHdmiControlService.onWakeUp(WAKE_UP_SCREEN_ON); + mTestLooper.dispatchAll(); + + assertThat(mVendorCommandListeners.size()).isEqualTo(2); + assertTrue(mVendorCommandListeners.contains(vendorCommandListenerInvocationWakeup)); + assertTrue(mVendorCommandListeners.contains(vendorCommandListenerInvocationSettingChange)); + } + protected static class MockTvDevice extends HdmiCecLocalDeviceTv { MockTvDevice(HdmiControlService service) { super(service); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java index 50f3a88cc3a2..5bcddc41eb87 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java @@ -1,6 +1,10 @@ package com.android.server.locksettings; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; import android.platform.test.annotations.Presubmit; @@ -56,4 +60,44 @@ public class WeaverBasedSyntheticPasswordTests extends SyntheticPasswordTests { mService.initializeSyntheticPassword(userId); // This should allocate a Weaver slot. assertEquals(Sets.newHashSet(0), mPasswordSlotManager.getUsedSlots()); } + + private int getNumUsedWeaverSlots() { + return mPasswordSlotManager.getUsedSlots().size(); + } + + @Test + public void testDisableWeaverOnUnsecuredUsers_false() { + final int userId = PRIMARY_USER_ID; + when(mResources.getBoolean(eq( + com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers))) + .thenReturn(false); + assertEquals(0, getNumUsedWeaverSlots()); + mService.initializeSyntheticPassword(userId); + assertEquals(1, getNumUsedWeaverSlots()); + assertTrue(mService.setLockCredential(newPassword("password"), nonePassword(), userId)); + assertEquals(1, getNumUsedWeaverSlots()); + assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"), userId)); + assertEquals(1, getNumUsedWeaverSlots()); + } + + @Test + public void testDisableWeaverOnUnsecuredUsers_true() { + final int userId = PRIMARY_USER_ID; + when(mResources.getBoolean(eq( + com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers))) + .thenReturn(true); + assertEquals(0, getNumUsedWeaverSlots()); + mService.initializeSyntheticPassword(userId); + assertEquals(0, getNumUsedWeaverSlots()); + assertTrue(mService.setLockCredential(newPassword("password"), nonePassword(), userId)); + assertEquals(1, getNumUsedWeaverSlots()); + assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"), userId)); + assertEquals(0, getNumUsedWeaverSlots()); + } + + @Test + public void testDisableWeaverOnUnsecuredUsers_defaultsToFalse() { + assertFalse(mResources.getBoolean( + com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers)); + } } diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java index ee63d5d32ff1..425bb158f997 100644 --- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java @@ -33,6 +33,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -51,11 +52,15 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.testng.Assert.assertThrows; +import android.Manifest; import android.annotation.SuppressLint; import android.app.ActivityManagerInternal; import android.app.ActivityOptions.LaunchCookie; import android.app.AppOpsManager; +import android.app.Instrumentation; import android.app.KeyguardManager; +import android.app.role.RoleManager; +import android.companion.AssociationRequest; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -68,6 +73,7 @@ import android.media.projection.ReviewGrantedConsentResult; import android.os.Binder; import android.os.IBinder; import android.os.Looper; +import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.os.test.TestLooper; @@ -88,6 +94,7 @@ import com.android.server.testutils.OffsettableClock; import com.android.server.wm.WindowManagerInternal; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -98,6 +105,7 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -312,7 +320,6 @@ public class MediaProjectionManagerServiceTest { assertThat(mService.getActiveProjectionInfo()).isNotNull(); } - @SuppressLint("MissingPermission") @EnableFlags(android.companion.virtualdevice.flags .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) @Test @@ -335,6 +342,36 @@ public class MediaProjectionManagerServiceTest { assertThat(mService.getActiveProjectionInfo()).isNotNull(); } + @EnableFlags(android.companion.virtualdevice.flags + .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) + @Test + public void testCreateProjection_keyguardLocked_RoleHeld() { + runWithRole(AssociationRequest.DEVICE_PROFILE_APP_STREAMING, () -> { + try { + mAppInfo.privateFlags |= PRIVATE_FLAG_PRIVILEGED; + doReturn(mAppInfo).when(mPackageManager).getApplicationInfoAsUser(anyString(), + any(ApplicationInfoFlags.class), any(UserHandle.class)); + MediaProjectionManagerService.MediaProjection projection = + mService.createProjectionInternal(Process.myUid(), + mContext.getPackageName(), + TYPE_MIRRORING, /* isPermanentGrant= */ false, UserHandle.CURRENT); + doReturn(true).when(mKeyguardManager).isKeyguardLocked(); + doReturn(PackageManager.PERMISSION_DENIED).when( + mPackageManager).checkPermission( + RECORD_SENSITIVE_CONTENT, projection.packageName); + + projection.start(mIMediaProjectionCallback); + projection.notifyVirtualDisplayCreated(10); + + // The projection was started because it was allowed to capture the keyguard. + assertWithMessage("Failed to run projection") + .that(mService.getActiveProjectionInfo()).isNotNull(); + } catch (NameNotFoundException e) { + throw new RuntimeException(e); + } + }); + } + @Test public void testCreateProjection_attemptReuse_noPriorProjectionGrant() throws NameNotFoundException { @@ -1202,6 +1239,47 @@ public class MediaProjectionManagerServiceTest { return mService.getProjectionInternal(UID, PACKAGE_NAME); } + /** + * Run the provided block giving the current context's package the provided role. + */ + @SuppressWarnings("SameParameterValue") + private void runWithRole(String role, Runnable block) { + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + String packageName = mContext.getPackageName(); + UserHandle user = instrumentation.getTargetContext().getUser(); + RoleManager roleManager = Objects.requireNonNull( + mContext.getSystemService(RoleManager.class)); + try { + CountDownLatch latch = new CountDownLatch(1); + instrumentation.getUiAutomation().adoptShellPermissionIdentity( + Manifest.permission.MANAGE_ROLE_HOLDERS, + Manifest.permission.BYPASS_ROLE_QUALIFICATION); + + roleManager.setBypassingRoleQualification(true); + roleManager.addRoleHolderAsUser(role, packageName, /* flags = */ 0, user, + mContext.getMainExecutor(), success -> { + if (success) { + latch.countDown(); + } else { + Assert.fail("Couldn't set role for test (failure) " + role); + } + }); + assertWithMessage("Couldn't set role for test (timeout) : " + role) + .that(latch.await(1, TimeUnit.SECONDS)).isTrue(); + block.run(); + + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + roleManager.removeRoleHolderAsUser(role, packageName, 0, user, + mContext.getMainExecutor(), (aBool) -> { + }); + roleManager.setBypassingRoleQualification(false); + instrumentation.getUiAutomation() + .dropShellPermissionIdentity(); + } + } + private static class FakeIMediaProjectionCallback extends IMediaProjectionCallback.Stub { CountDownLatch mLatch = new CountDownLatch(1); @Override 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 48bc9d7c51a1..3bbc6b21cce2 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java @@ -63,11 +63,13 @@ import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.IInterface; +import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.platform.test.annotations.EnableFlags; import android.provider.Settings; +import android.testing.TestableLooper; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -82,6 +84,7 @@ import com.android.server.UiServiceTestCase; import com.google.android.collect.Lists; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -103,6 +106,7 @@ import java.util.List; import java.util.Set; import java.util.concurrent.CountDownLatch; + public class ManagedServicesTest extends UiServiceTestCase { @Mock @@ -115,6 +119,7 @@ public class ManagedServicesTest extends UiServiceTestCase { private ManagedServices.UserProfiles mUserProfiles; @Mock private DevicePolicyManager mDpm; Object mLock = new Object(); + private TestableLooper mTestableLooper; UserInfo mZero = new UserInfo(0, "zero", 0); UserInfo mTen = new UserInfo(10, "ten", 0); @@ -142,6 +147,7 @@ public class ManagedServicesTest extends UiServiceTestCase { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + mTestableLooper = new TestableLooper(Looper.getMainLooper()); mContext.setMockPackageManager(mPm); mContext.addMockSystemService(Context.USER_SERVICE, mUm); @@ -199,6 +205,11 @@ public class ManagedServicesTest extends UiServiceTestCase { mIpm, APPROVAL_BY_COMPONENT); } + @After + public void tearDown() throws Exception { + mTestableLooper.destroy(); + } + @Test public void testBackupAndRestore_migration() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { @@ -888,7 +899,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 +930,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 +961,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 +992,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); @@ -1053,6 +1064,77 @@ public class ManagedServicesTest extends UiServiceTestCase { } @Test + public void registerService_bindingDied_rebindIsClearedOnUserSwitch() throws Exception { + Context context = mock(Context.class); + PackageManager pm = mock(PackageManager.class); + ApplicationInfo ai = new ApplicationInfo(); + ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; + + when(context.getPackageName()).thenReturn(mPkg); + when(context.getUserId()).thenReturn(mUser.getIdentifier()); + when(context.getPackageManager()).thenReturn(pm); + when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai); + + ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm, + APPROVAL_BY_PACKAGE); + service = spy(service); + ComponentName cn = ComponentName.unflattenFromString("a/a"); + + // Trigger onBindingDied for component when registering + // => will schedule a rebind in 10 seconds + when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> { + Object[] args = invocation.getArguments(); + ServiceConnection sc = (ServiceConnection) args[1]; + sc.onBindingDied(cn); + return true; + }); + service.registerService(cn, 0); + assertThat(service.isBound(cn, 0)).isFalse(); + + // Switch to user 10 + service.onUserSwitched(10); + + // Check that the scheduled rebind for user 0 was cleared + mTestableLooper.moveTimeForward(ManagedServices.ON_BINDING_DIED_REBIND_DELAY_MS); + mTestableLooper.processAllMessages(); + verify(service, never()).reregisterService(any(), anyInt()); + } + + @Test + public void registerService_bindingDied_rebindIsExecutedAfterTimeout() throws Exception { + Context context = mock(Context.class); + PackageManager pm = mock(PackageManager.class); + ApplicationInfo ai = new ApplicationInfo(); + ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; + + when(context.getPackageName()).thenReturn(mPkg); + when(context.getUserId()).thenReturn(mUser.getIdentifier()); + when(context.getPackageManager()).thenReturn(pm); + when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai); + + ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm, + APPROVAL_BY_PACKAGE); + service = spy(service); + ComponentName cn = ComponentName.unflattenFromString("a/a"); + + // Trigger onBindingDied for component when registering + // => will schedule a rebind in 10 seconds + when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> { + Object[] args = invocation.getArguments(); + ServiceConnection sc = (ServiceConnection) args[1]; + sc.onBindingDied(cn); + return true; + }); + service.registerService(cn, 0); + assertThat(service.isBound(cn, 0)).isFalse(); + + // Check that the scheduled rebind is run + mTestableLooper.moveTimeForward(ManagedServices.ON_BINDING_DIED_REBIND_DELAY_MS); + mTestableLooper.processAllMessages(); + verify(service, times(1)).reregisterService(eq(cn), eq(0)); + } + + @Test public void testPackageUninstall_packageNoLongerInApprovedList() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, @@ -1211,6 +1293,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, @@ -1223,6 +1363,21 @@ public class ManagedServicesTest extends UiServiceTestCase { "user10package1/K", "user10.3/Component", "user10package2/L", "user10.4/Component"})); + // mock permissions for services + PackageManager pm = mock(PackageManager.class); + when(getContext().getPackageManager()).thenReturn(pm); + List<ComponentName> enabledComponents = List.of( + ComponentName.unflattenFromString("package/Comp"), + ComponentName.unflattenFromString("package/C2"), + ComponentName.unflattenFromString("again/M4"), + ComponentName.unflattenFromString("user10package/B"), + ComponentName.unflattenFromString("user10/Component"), + ComponentName.unflattenFromString("user10package1/K"), + ComponentName.unflattenFromString("user10.3/Component"), + ComponentName.unflattenFromString("user10package2/L"), + ComponentName.unflattenFromString("user10.4/Component")); + mockServiceInfoWithMetaData(enabledComponents, service, pm, new ArrayMap<>()); + for (int userId : expectedEnabled.keySet()) { ArrayList<String> expectedForUser = expectedEnabled.get(userId); for (int i = 0; i < expectedForUser.size(); i++) { @@ -1944,7 +2099,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); @@ -1989,7 +2144,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); @@ -2028,7 +2183,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); @@ -2099,8 +2254,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); @@ -2115,6 +2270,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/NotificationAdjustmentExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java index 18ca09be235c..bf0586ceb32d 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java @@ -18,11 +18,21 @@ package com.android.server.notification; import static android.app.NotificationManager.IMPORTANCE_LOW; +import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT; +import static android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION; +import static android.service.notification.Flags.FLAG_NOTIFICATION_FORCE_GROUPING; + +import static com.google.common.truth.Truth.assertThat; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + import android.app.Notification; import android.app.NotificationChannel; import android.app.PendingIntent; @@ -30,12 +40,16 @@ import android.content.Intent; import android.graphics.drawable.Icon; import android.os.Bundle; import android.os.UserHandle; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import android.service.notification.Adjustment; import android.service.notification.SnoozeCriterion; import android.service.notification.StatusBarNotification; import com.android.server.UiServiceTestCase; +import org.junit.Rule; import org.junit.Test; import java.util.ArrayList; @@ -43,6 +57,9 @@ import java.util.Objects; public class NotificationAdjustmentExtractorTest extends UiServiceTestCase { + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT); + @Test public void testExtractsAdjustment() { NotificationAdjustmentExtractor extractor = new NotificationAdjustmentExtractor(); @@ -111,6 +128,44 @@ public class NotificationAdjustmentExtractorTest extends UiServiceTestCase { assertEquals(snoozeCriteria, r.getSnoozeCriteria()); } + @Test + @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION, FLAG_NOTIFICATION_FORCE_GROUPING}) + public void testClassificationAdjustments_triggerRegrouping() { + GroupHelper groupHelper = mock(GroupHelper.class); + NotificationAdjustmentExtractor extractor = new NotificationAdjustmentExtractor(); + extractor.setGroupHelper(groupHelper); + + NotificationRecord r = generateRecord(); + + Bundle classificationAdj = new Bundle(); + classificationAdj.putParcelable(Adjustment.KEY_TYPE, mock(NotificationChannel.class)); + Adjustment adjustment = new Adjustment("pkg", r.getKey(), classificationAdj, "", 0); + r.addAdjustment(adjustment); + + RankingReconsideration regroupingTask = extractor.process(r); + assertThat(regroupingTask).isNotNull(); + regroupingTask.applyChangesLocked(r); + verify(groupHelper, times(1)).onChannelUpdated(r); + } + + @Test + @DisableFlags({FLAG_NOTIFICATION_CLASSIFICATION, FLAG_NOTIFICATION_FORCE_GROUPING}) + public void testClassificationAdjustments_notTriggerRegrouping_flagsDisabled() { + GroupHelper groupHelper = mock(GroupHelper.class); + NotificationAdjustmentExtractor extractor = new NotificationAdjustmentExtractor(); + extractor.setGroupHelper(groupHelper); + + NotificationRecord r = generateRecord(); + + Bundle classificationAdj = new Bundle(); + classificationAdj.putParcelable(Adjustment.KEY_TYPE, mock(NotificationChannel.class)); + Adjustment adjustment = new Adjustment("pkg", r.getKey(), classificationAdj, "", 0); + r.addAdjustment(adjustment); + + RankingReconsideration regroupingTask = extractor.process(r); + assertThat(regroupingTask).isNull(); + } + private NotificationRecord generateRecord() { NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW); final Notification.Builder builder = new Notification.Builder(getContext()) diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java index 797b95b5dbe9..7e4ae679a22f 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java @@ -25,6 +25,7 @@ import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertNull; + import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Matchers.any; @@ -193,6 +194,8 @@ public class NotificationAssistantsTest extends UiServiceTestCase { public void testWriteXml_userTurnedOffNAS() throws Exception { int userId = ActivityManager.getCurrentUser(); + doReturn(true).when(mAssistants).isValidService(eq(mCn), eq(userId)); + mAssistants.loadDefaultsFromConfig(true); mAssistants.setPackageOrComponentEnabled(mCn.flattenToString(), userId, true, @@ -398,6 +401,10 @@ public class NotificationAssistantsTest extends UiServiceTestCase { public void testSetPackageOrComponentEnabled_onlyOnePackage() throws Exception { ComponentName component1 = ComponentName.unflattenFromString("package/Component1"); ComponentName component2 = ComponentName.unflattenFromString("package/Component2"); + + doReturn(true).when(mAssistants).isValidService(eq(component1), eq(mZero.id)); + doReturn(true).when(mAssistants).isValidService(eq(component2), eq(mZero.id)); + mAssistants.setPackageOrComponentEnabled(component1.flattenToString(), mZero.id, true, true, true); verify(mNm, never()).setNotificationAssistantAccessGrantedForUserInternal( @@ -543,6 +550,7 @@ public class NotificationAssistantsTest extends UiServiceTestCase { public void testSetAdjustmentTypeSupportedState() throws Exception { int userId = ActivityManager.getCurrentUser(); + doReturn(true).when(mAssistants).isValidService(eq(mCn), eq(userId)); mAssistants.loadDefaultsFromConfig(true); mAssistants.setPackageOrComponentEnabled(mCn.flattenToString(), userId, true, true, true); @@ -566,6 +574,7 @@ public class NotificationAssistantsTest extends UiServiceTestCase { public void testSetAdjustmentTypeSupportedState_readWriteXml_entries() throws Exception { int userId = ActivityManager.getCurrentUser(); + doReturn(true).when(mAssistants).isValidService(eq(mCn), eq(userId)); mAssistants.loadDefaultsFromConfig(true); mAssistants.setPackageOrComponentEnabled(mCn.flattenToString(), userId, true, true, true); @@ -589,6 +598,7 @@ public class NotificationAssistantsTest extends UiServiceTestCase { public void testSetAdjustmentTypeSupportedState_readWriteXml_empty() throws Exception { int userId = ActivityManager.getCurrentUser(); + doReturn(true).when(mAssistants).isValidService(eq(mCn), eq(userId)); mAssistants.loadDefaultsFromConfig(true); mAssistants.setPackageOrComponentEnabled(mCn.flattenToString(), userId, true, true, true); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java index 45cd5719cd86..592eec539ae6 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java @@ -2291,10 +2291,7 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME2, 0); initAttentionHelper(flagResolver); - // Trigger avalanche trigger intent - final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); - intent.putExtra("state", false); - mAvalancheBroadcastReceiver.onReceive(getContext(), intent); + triggerAvalancheEvent(); NotificationRecord r = getBeepyNotification(); @@ -2338,10 +2335,7 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME2, 0); initAttentionHelper(flagResolver); - // Trigger avalanche trigger intent - final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); - intent.putExtra("state", false); - mAvalancheBroadcastReceiver.onReceive(getContext(), intent); + triggerAvalancheEvent(); NotificationRecord r = getBeepyNotification(); @@ -2379,10 +2373,7 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME2, 0); initAttentionHelper(flagResolver); - // Trigger avalanche trigger intent - final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); - intent.putExtra("state", false); - mAvalancheBroadcastReceiver.onReceive(getContext(), intent); + triggerAvalancheEvent(); NotificationRecord r = getBeepyNotification(); @@ -2428,10 +2419,7 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME2, 0); initAttentionHelper(flagResolver); - // Trigger avalanche trigger intent - final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); - intent.putExtra("state", false); - mAvalancheBroadcastReceiver.onReceive(getContext(), intent); + triggerAvalancheEvent(); NotificationRecord r = getBeepyNotification(); r.getNotification().category = Notification.CATEGORY_EVENT; @@ -2504,10 +2492,7 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME2, 0); initAttentionHelper(flagResolver); - // Trigger avalanche trigger intent - final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); - intent.putExtra("state", false); - mAvalancheBroadcastReceiver.onReceive(getContext(), intent); + triggerAvalancheEvent(); // Regular notification: should beep at 0% volume NotificationRecord r = getBeepyNotification(); @@ -2574,10 +2559,7 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME2, 0); initAttentionHelper(flagResolver); - // Trigger avalanche trigger intent - final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); - intent.putExtra("state", false); - mAvalancheBroadcastReceiver.onReceive(getContext(), intent); + triggerAvalancheEvent(); NotificationRecord r = getBeepyNotification(); @@ -2602,10 +2584,7 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME2, 0); initAttentionHelper(flagResolver); - // Trigger avalanche trigger intent - final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); - intent.putExtra("state", false); - mAvalancheBroadcastReceiver.onReceive(getContext(), intent); + triggerAvalancheEvent(); // CATEGORY_ALARM is exempted NotificationRecord r = getBeepyNotification(); @@ -2637,6 +2616,70 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase { } @Test + public void testBeepVolume_politeNotif_AvalancheStrategy_exempt_msgCategory() throws Exception { + mSetFlagsRule.enableFlags(Flags.FLAG_POLITE_NOTIFICATIONS); + mSetFlagsRule.enableFlags(Flags.FLAG_CROSS_APP_POLITE_NOTIFICATIONS); + mSetFlagsRule.enableFlags(Flags.FLAG_POLITE_NOTIFICATIONS_ATTN_UPDATE); + TestableFlagResolver flagResolver = new TestableFlagResolver(); + flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME1, 50); + flagResolver.setFlagOverride(NotificationFlags.NOTIF_VOLUME2, 0); + initAttentionHelper(flagResolver); + + triggerAvalancheEvent(); + + // Create a conversation group with GROUP_ALERT_SUMMARY behavior + // Where the summary is not MessagingStyle + final String groupKey = "grup_name"; + final String shortcutId = "shortcut"; + NotificationRecord summary = getBeepyNotificationRecord(groupKey, GROUP_ALERT_SUMMARY); + summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY; + summary.getNotification().category = Notification.CATEGORY_MESSAGE; + ShortcutInfo.Builder sb = new ShortcutInfo.Builder(getContext()); + summary.setShortcutInfo(sb.setId(shortcutId).build()); + + // Should beep at 100% volume + mAttentionHelper.buzzBeepBlinkLocked(summary, DEFAULT_SIGNALS); + verifyBeepVolume(1.0f); + assertNotEquals(-1, summary.getLastAudiblyAlertedMs()); + Mockito.reset(mRingtonePlayer); + + // Post child notifications with GROUP_ALERT_SUMMARY + NotificationRecord child = getConversationNotificationRecord(mId, false /* insistent */, + false /* once */, true /* noisy */, false /* buzzy*/, false /* lights */, true, + true, false, groupKey, Notification.GROUP_ALERT_SUMMARY, false, mUser, mPkg, + shortcutId); + + // Should not beep + mAttentionHelper.buzzBeepBlinkLocked(child, DEFAULT_SIGNALS); + verifyNeverBeep(); + assertFalse(child.isInterruptive()); + assertEquals(-1, child.getLastAudiblyAlertedMs()); + Mockito.reset(mRingtonePlayer); + + // 2nd update for summary should beep at 50% volume + mAttentionHelper.buzzBeepBlinkLocked(summary, DEFAULT_SIGNALS); + verifyBeepVolume(0.5f); + assertNotEquals(-1, summary.getLastAudiblyAlertedMs()); + Mockito.reset(mRingtonePlayer); + + // 3rd update for summary should not beep + mAttentionHelper.buzzBeepBlinkLocked(summary, DEFAULT_SIGNALS); + verifyNeverBeep(); + assertFalse(summary.isInterruptive()); + assertEquals(-1, summary.getLastAudiblyAlertedMs()); + } + + private void triggerAvalancheEvent() throws Exception { + // Trigger avalanche trigger intent + final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); + intent.putExtra("state", false); + mAvalancheBroadcastReceiver.onReceive(getContext(), intent); + // Wait after avalanche trigger before posting notifications + // so that notification#getWhen() is not the same value + Thread.sleep(100); + } + + @Test public void testBeepVolume_politeNotif_exemptEmergency() throws Exception { mSetFlagsRule.enableFlags(Flags.FLAG_POLITE_NOTIFICATIONS); mSetFlagsRule.disableFlags(Flags.FLAG_CROSS_APP_POLITE_NOTIFICATIONS); 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 3c120e1ada2a..1349ee04696d 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -3206,7 +3206,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Send two cancelations. mBinderService.cancelNotificationWithTag(mPkg, mPkg, sbn.getTag(), sbn.getId(), sbn.getUserId()); - waitForIdle(); mBinderService.cancelNotificationWithTag(mPkg, mPkg, sbn.getTag(), sbn.getId(), sbn.getUserId()); waitForIdle(); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java index 9a6e81865947..5d4382a6331c 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java @@ -92,6 +92,7 @@ public class RankingHelperTest extends UiServiceTestCase { @Mock ZenModeHelper mMockZenModeHelper; @Mock RankingConfig mConfig; @Mock Vibrator mVibrator; + @Mock GroupHelper mGroupHelper; private NotificationManager.Policy mTestNotificationPolicy; private Notification mNotiGroupGSortA; @@ -157,7 +158,7 @@ public class RankingHelperTest extends UiServiceTestCase { when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); mHelper = new RankingHelper(getContext(), mHandler, mConfig, mMockZenModeHelper, mUsageStats, new String[] {ImportanceExtractor.class.getName()}, - mock(IPlatformCompat.class)); + mock(IPlatformCompat.class), mGroupHelper); mNotiGroupGSortA = new Notification.Builder(mContext, TEST_CHANNEL_ID) .setContentTitle("A") diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java index b997f5d9a2a0..a49f5a89b11b 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java @@ -26,8 +26,6 @@ import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSAT import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES; import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS; import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY; -import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; -import static android.provider.Settings.Global.ZEN_MODE_ALARMS; import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS; import static android.provider.Settings.Global.ZEN_MODE_OFF; @@ -57,7 +55,6 @@ import android.util.ArraySet; import androidx.test.filters.SmallTest; -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.util.NotificationMessagingUtil; import com.android.server.UiServiceTestCase; @@ -188,49 +185,6 @@ public class ZenModeFilteringTest extends UiServiceTestCase { } @Test - public void testSuppressDNDInfo_yes_VisEffectsAllowed() { - NotificationRecord r = getNotificationRecord(); - when(r.getSbn().getPackageName()).thenReturn("android"); - when(r.getSbn().getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE); - Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects() - - SUPPRESSED_EFFECT_STATUS_BAR, 0); - - assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r)); - } - - @Test - public void testSuppressDNDInfo_yes_WrongId() { - NotificationRecord r = getNotificationRecord(); - when(r.getSbn().getPackageName()).thenReturn("android"); - when(r.getSbn().getId()).thenReturn(SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION); - Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects(), 0); - - assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r)); - } - - @Test - public void testSuppressDNDInfo_yes_WrongPackage() { - NotificationRecord r = getNotificationRecord(); - when(r.getSbn().getPackageName()).thenReturn("android2"); - when(r.getSbn().getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE); - Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects(), 0); - - assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r)); - } - - @Test - public void testSuppressDNDInfo_no() { - NotificationRecord r = getNotificationRecord(); - when(r.getSbn().getPackageName()).thenReturn("android"); - when(r.getSbn().getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE); - Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects(), 0); - - assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r)); - assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_ALARMS, policy, r)); - assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, policy, r)); - } - - @Test public void testSuppressAnything_yes_ZenModeOff() { NotificationRecord r = getNotificationRecord(); when(r.getSbn().getPackageName()).thenReturn("bananas"); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java index d4cba8d726fb..294027b10b26 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -169,7 +169,6 @@ import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.internal.config.sysui.TestableFlagResolver; -import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.os.AtomsProto; @@ -747,54 +746,6 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test - public void testZenUpgradeNotification() { - /** - * Commit a485ec65b5ba947d69158ad90905abf3310655cf disabled DND status change - * notification on watches. So, assume that the device is not watch. - */ - when(mContext.getPackageManager()).thenReturn(mPackageManager); - when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(false); - - // shows zen upgrade notification if stored settings says to shows, - // zen has not been updated, boot is completed - // and we're setting zen mode on - Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1); - Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 0); - mZenModeHelper.mIsSystemServicesReady = true; - mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0); - mZenModeHelper.setZenModeSetting(ZEN_MODE_IMPORTANT_INTERRUPTIONS); - - verify(mNotificationManager, times(1)).notify(eq(ZenModeHelper.TAG), - eq(SystemMessage.NOTE_ZEN_UPGRADE), any()); - assertEquals(0, Settings.Secure.getInt(mContentResolver, - Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, -1)); - } - - @Test - public void testNoZenUpgradeNotification() { - // doesn't show upgrade notification if stored settings says don't show - Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); - Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 0); - mZenModeHelper.mIsSystemServicesReady = true; - mZenModeHelper.setZenModeSetting(ZEN_MODE_IMPORTANT_INTERRUPTIONS); - - verify(mNotificationManager, never()).notify(eq(ZenModeHelper.TAG), - eq(SystemMessage.NOTE_ZEN_UPGRADE), any()); - } - - @Test - public void testNoZenUpgradeNotificationZenUpdated() { - // doesn't show upgrade notification since zen was already updated - Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); - Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 1); - mZenModeHelper.mIsSystemServicesReady = true; - mZenModeHelper.setZenModeSetting(ZEN_MODE_IMPORTANT_INTERRUPTIONS); - - verify(mNotificationManager, never()).notify(eq(ZenModeHelper.TAG), - eq(SystemMessage.NOTE_ZEN_UPGRADE), any()); - } - - @Test public void testZenSetInternalRinger_AllPriorityNotificationSoundsMuted() { AudioManagerInternal mAudioManager = mock(AudioManagerInternal.class); mZenModeHelper.mAudioManager = mAudioManager; @@ -3032,6 +2983,33 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test + @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI}) + public void updateAutomaticZenRule_withTypeBedtime_replacesDisabledSleeping() { + ZenRule sleepingRule = createCustomAutomaticRule(ZEN_MODE_IMPORTANT_INTERRUPTIONS, + ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID); + sleepingRule.enabled = false; + sleepingRule.userModifiedFields = 0; + sleepingRule.name = "ZZZZZZZ..."; + mZenModeHelper.mConfig.automaticRules.clear(); + mZenModeHelper.mConfig.automaticRules.put(sleepingRule.id, sleepingRule); + + AutomaticZenRule futureBedtime = new AutomaticZenRule.Builder("Bedtime (?)", CONDITION_ID) + .build(); + String bedtimeRuleId = mZenModeHelper.addAutomaticZenRule(mPkg, futureBedtime, + ORIGIN_APP, "reason", CUSTOM_PKG_UID); + assertThat(mZenModeHelper.mConfig.automaticRules.keySet()) + .containsExactly(sleepingRule.id, bedtimeRuleId); + + AutomaticZenRule bedtime = new AutomaticZenRule.Builder("Bedtime (!)", CONDITION_ID) + .setType(TYPE_BEDTIME) + .build(); + mZenModeHelper.updateAutomaticZenRule(bedtimeRuleId, bedtime, ORIGIN_APP, "reason", + CUSTOM_PKG_UID); + + assertThat(mZenModeHelper.mConfig.automaticRules.keySet()).containsExactly(bedtimeRuleId); + } + + @Test @EnableFlags(FLAG_MODES_API) public void testSetManualZenMode() { setupZenConfig(); diff --git a/services/tests/vibrator/src/com/android/server/vibrator/RampToStepAdapterTest.java b/services/tests/vibrator/src/com/android/server/vibrator/RampToStepAdapterTest.java index 867c061151b4..81036824f92b 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/RampToStepAdapterTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/RampToStepAdapterTest.java @@ -39,8 +39,8 @@ public class RampToStepAdapterTest { private static final int TEST_STEP_DURATION = 5; private static final float[] TEST_AMPLITUDE_MAP = new float[]{ /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f}; - private static final VibratorInfo.FrequencyProfile TEST_FREQUENCY_PROFILE = - new VibratorInfo.FrequencyProfile( + private static final VibratorInfo.FrequencyProfileLegacy TEST_FREQUENCY_PROFILE = + new VibratorInfo.FrequencyProfileLegacy( /* resonantFrequencyHz= */ 150f, /* minFrequencyHz= */ 50f, /* frequencyResolutionHz= */ 25f, TEST_AMPLITUDE_MAP); private static final VibratorInfo EMPTY_VIBRATOR_INFO = createVibratorInfo(); @@ -121,7 +121,7 @@ public class RampToStepAdapterTest { private static VibratorInfo createVibratorInfo(int... capabilities) { return new VibratorInfo.Builder(0) .setCapabilities(IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0)) - .setFrequencyProfile(TEST_FREQUENCY_PROFILE) + .setFrequencyProfileLegacy(TEST_FREQUENCY_PROFILE) .build(); } } diff --git a/services/tests/vibrator/src/com/android/server/vibrator/SplitSegmentsAdapterTest.java b/services/tests/vibrator/src/com/android/server/vibrator/SplitSegmentsAdapterTest.java index 6630ccad6189..f2c3726375e6 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/SplitSegmentsAdapterTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/SplitSegmentsAdapterTest.java @@ -41,8 +41,8 @@ public class SplitSegmentsAdapterTest { private static final float[] TEST_AMPLITUDE_MAP = new float[]{ /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f}; - private static final VibratorInfo.FrequencyProfile TEST_FREQUENCY_PROFILE = - new VibratorInfo.FrequencyProfile( + private static final VibratorInfo.FrequencyProfileLegacy TEST_FREQUENCY_PROFILE = + new VibratorInfo.FrequencyProfileLegacy( /* resonantFrequencyHz= */ 150f, /* minFrequencyHz= */ 50f, /* frequencyResolutionHz= */ 25f, TEST_AMPLITUDE_MAP); @@ -125,7 +125,7 @@ public class SplitSegmentsAdapterTest { VibratorInfo vibratorInfo = new VibratorInfo.Builder(0) .setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS) .setPwlePrimitiveDurationMax(10) - .setFrequencyProfile(TEST_FREQUENCY_PROFILE) + .setFrequencyProfileLegacy(TEST_FREQUENCY_PROFILE) .build(); // Update repeat index to skip the ramp splits. @@ -137,7 +137,7 @@ public class SplitSegmentsAdapterTest { private static VibratorInfo createVibratorInfo(int... capabilities) { return new VibratorInfo.Builder(0) .setCapabilities(IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0)) - .setFrequencyProfile(TEST_FREQUENCY_PROFILE) + .setFrequencyProfileLegacy(TEST_FREQUENCY_PROFILE) .setPwlePrimitiveDurationMax(PWLE_COMPOSITION_PRIMITIVE_DURATION_MAX) .build(); } diff --git a/services/tests/vibrator/src/com/android/server/vibrator/StepToRampAdapterTest.java b/services/tests/vibrator/src/com/android/server/vibrator/StepToRampAdapterTest.java index 82deff011e82..d501dba13ac3 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/StepToRampAdapterTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/StepToRampAdapterTest.java @@ -38,8 +38,8 @@ import java.util.stream.IntStream; public class StepToRampAdapterTest { private static final float[] TEST_AMPLITUDE_MAP = new float[]{ /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f}; - private static final VibratorInfo.FrequencyProfile TEST_FREQUENCY_PROFILE = - new VibratorInfo.FrequencyProfile( + private static final VibratorInfo.FrequencyProfileLegacy TEST_FREQUENCY_PROFILE = + new VibratorInfo.FrequencyProfileLegacy( /* resonantFrequencyHz= */ 150f, /* minFrequencyHz= */ 50f, /* frequencyResolutionHz= */ 25f, TEST_AMPLITUDE_MAP); private static final VibratorInfo EMPTY_VIBRATOR_INFO = createVibratorInfo(); @@ -153,7 +153,7 @@ public class StepToRampAdapterTest { private static VibratorInfo createVibratorInfo(int... capabilities) { return new VibratorInfo.Builder(0) .setCapabilities(IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0)) - .setFrequencyProfile(TEST_FREQUENCY_PROFILE) + .setFrequencyProfileLegacy(TEST_FREQUENCY_PROFILE) .build(); } } diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java index e83a4b22d9bf..7536f5f54ba2 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java @@ -47,7 +47,6 @@ import android.hardware.vibrator.IVibrator; import android.hardware.vibrator.IVibratorManager; import android.os.CombinedVibration; import android.os.Handler; -import android.os.IBinder; import android.os.PersistableBundle; import android.os.PowerManager; import android.os.Process; @@ -119,7 +118,6 @@ public class VibrationThreadTest { @Mock private PackageManagerInternal mPackageManagerInternalMock; @Mock private VibrationThread.VibratorManagerHooks mManagerHooks; @Mock private VibratorController.OnVibrationCompleteListener mControllerCallbacks; - @Mock private IBinder mVibrationToken; @Mock private VibrationConfig mVibrationConfigMock; @Mock private VibratorFrameworkStatsLogger mStatsLoggerMock; @@ -668,7 +666,7 @@ public class VibrationThreadTest { VibrationEffect fallback = VibrationEffect.createOneShot(10, 100); HalVibration vibration = createVibration(CombinedVibration.createParallel( VibrationEffect.get(VibrationEffect.EFFECT_CLICK))); - vibration.addFallback(VibrationEffect.EFFECT_CLICK, fallback); + vibration.fillFallbacks(unused -> fallback); startThreadAndDispatcher(vibration); waitForCompletion(); @@ -848,7 +846,7 @@ public class VibrationThreadTest { .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f) .compose(); HalVibration vibration = createVibration(CombinedVibration.createParallel(effect)); - vibration.addFallback(VibrationEffect.EFFECT_TICK, fallback); + vibration.fillFallbacks(unused -> fallback); startThreadAndDispatcher(vibration); waitForCompletion(); @@ -954,7 +952,8 @@ public class VibrationThreadTest { assertTrue(mThread.isRunningVibrationId(vibration.id)); assertTrue(mControllers.get(VIBRATOR_ID).isVibrating()); - mVibrationConductor.binderDied(); + mVibrationConductor.notifyCancelled( + new Vibration.EndInfo(Status.CANCELLED_BINDER_DIED), /* immediate= */ false); waitForCompletion(); assertFalse(mControllers.get(VIBRATOR_ID).isVibrating()); @@ -1575,7 +1574,8 @@ public class VibrationThreadTest { TEST_TIMEOUT_MILLIS)); assertTrue(mThread.isRunningVibrationId(vibration.id)); - mVibrationConductor.binderDied(); + mVibrationConductor.notifyCancelled( + new Vibration.EndInfo(Status.CANCELLED_BINDER_DIED), /* immediate= */ false); waitForCompletion(); verifyCallbacksTriggered(vibration, Status.CANCELLED_BINDER_DIED); @@ -1865,9 +1865,9 @@ public class VibrationThreadTest { VibrationAttributes attrs = new VibrationAttributes.Builder() .setUsage(usage) .build(); - HalVibration vib = new HalVibration(mVibrationToken, - CombinedVibration.createParallel(effect), - new CallerInfo(attrs, UID, DEVICE_ID, PACKAGE_NAME, "reason")); + HalVibration vib = new HalVibration( + new CallerInfo(attrs, UID, DEVICE_ID, PACKAGE_NAME, "reason"), + CombinedVibration.createParallel(effect)); return startThreadAndDispatcher(vib, requestVibrationParamsFuture); } @@ -1903,8 +1903,8 @@ public class VibrationThreadTest { } private HalVibration createVibration(CombinedVibration effect) { - return new HalVibration(mVibrationToken, effect, - new CallerInfo(ATTRS, UID, DEVICE_ID, PACKAGE_NAME, "reason")); + return new HalVibration(new CallerInfo(ATTRS, UID, DEVICE_ID, PACKAGE_NAME, "reason"), + effect); } private SparseArray<VibratorController> createVibratorControllers() { diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerTest.java index e8ca8bf8ec63..81793694a110 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControllerTest.java @@ -334,13 +334,14 @@ public class VibratorControllerTest { } private void mockVibratorCapabilities(int capabilities) { - VibratorInfo.FrequencyProfile frequencyProfile = new VibratorInfo.FrequencyProfile( + VibratorInfo.FrequencyProfileLegacy + frequencyProfile = new VibratorInfo.FrequencyProfileLegacy( Float.NaN, Float.NaN, Float.NaN, null); when(mNativeWrapperMock.getInfo(any(VibratorInfo.Builder.class))) .then(invocation -> { ((VibratorInfo.Builder) invocation.getArgument(0)) .setCapabilities(capabilities) - .setFrequencyProfile(frequencyProfile); + .setFrequencyProfileLegacy(frequencyProfile); return true; }); } diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorFrameworkStatsLoggerTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorFrameworkStatsLoggerTest.java index cd057b619000..1d1b4e271e19 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorFrameworkStatsLoggerTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorFrameworkStatsLoggerTest.java @@ -115,6 +115,6 @@ public class VibratorFrameworkStatsLoggerTest { } private static VibrationStats.StatsInfo newEmptyStatsInfo() { - return new VibrationStats.StatsInfo(0, 0, 0, Status.FINISHED, new VibrationStats(), 0L); + return new VibrationStats.StatsInfo(0, 0, 0, Status.FINISHED, new VibrationStats()); } } 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 538c3fc2ddae..b7821623855c 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java @@ -1791,28 +1791,6 @@ public class VibratorManagerServiceTest { } @Test - public void performHapticFeedback_usesServiceAsToken() throws Exception { - VibratorManagerService service = createSystemReadyService(); - - HalVibration vibration = - performHapticFeedbackAndWaitUntilFinished( - service, HapticFeedbackConstants.SCROLL_TICK, /* always= */ true); - - assertTrue(vibration.callerToken == service); - } - - @Test - public void performHapticFeedbackForInputDevice_usesServiceAsToken() throws Exception { - VibratorManagerService service = createSystemReadyService(); - - HalVibration vibration = performHapticFeedbackForInputDeviceAndWaitUntilFinished( - service, HapticFeedbackConstants.SCROLL_TICK, /* inputDeviceId= */ 0, - InputDevice.SOURCE_ROTARY_ENCODER, /* always= */ true); - - assertTrue(vibration.callerToken == service); - } - - @Test @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS) public void vibrate_vendorEffectsWithoutPermission_doesNotVibrate() throws Exception { // Deny permission to vibrate with vendor effects @@ -2147,6 +2125,27 @@ public class VibratorManagerServiceTest { } @Test + public void cancelVibrate_externalVibration_cancelWithDifferentToken() { + mockVibrators(1); + mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL); + createSystemReadyService(); + + IBinder vibrationBinderToken = mock(IBinder.class); + ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, + AUDIO_ALARM_ATTRS, + mock(IExternalVibrationController.class), vibrationBinderToken); + ExternalVibrationScale scale = mExternalVibratorService.onExternalVibrationStart( + externalVibration); + + IBinder cancelBinderToken = mock(IBinder.class); + mService.cancelVibrate(VibrationAttributes.USAGE_FILTER_MATCH_ALL, cancelBinderToken); + + assertNotEquals(ExternalVibrationScale.ScaleLevel.SCALE_MUTE, scale.scaleLevel); + assertEquals(Arrays.asList(false, true, false), + mVibratorProviders.get(1).getExternalControlStates()); + } + + @Test public void onExternalVibration_ignoreVibrationFromVirtualDevices() { mockVibrators(1); mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL); diff --git a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java index 946e1eaa5666..f96177d98052 100644 --- a/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java +++ b/services/tests/vibrator/utils/com/android/server/vibrator/FakeVibratorControllerProvider.java @@ -218,7 +218,7 @@ public final class FakeVibratorControllerProvider { } infoBuilder.setCompositionSizeMax(mCompositionSizeMax); infoBuilder.setQFactor(mQFactor); - infoBuilder.setFrequencyProfile(new VibratorInfo.FrequencyProfile( + infoBuilder.setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy( mResonantFrequency, mMinFrequency, mFrequencyResolution, mMaxAmplitudes)); infoBuilder.setMaxEnvelopeEffectSize(mMaxEnvelopeEffectSize); infoBuilder.setMinEnvelopeEffectControlPointDurationMillis( diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java index 65736cbc519f..c8a35598479f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java @@ -179,17 +179,25 @@ class AppCompatActivityRobot { .getAppCompatAspectRatioPolicy()).isLetterboxedForFixedOrientationAndAspectRatio(); } - void enableTreatmentForTopActivity(boolean enabled) { - doReturn(enabled).when(mDisplayContent.mAppCompatCameraPolicy) - .isTreatmentEnabledForActivity(eq(mActivityStack.top())); + void enableFullscreenCameraCompatTreatmentForTopActivity(boolean enabled) { + if (mDisplayContent.mAppCompatCameraPolicy.hasDisplayRotationCompatPolicy()) { + doReturn(enabled).when( + mDisplayContent.mAppCompatCameraPolicy.mDisplayRotationCompatPolicy) + .isTreatmentEnabledForActivity(eq(mActivityStack.top())); + } } - void setTopActivityCameraActive(boolean enabled) { + void setIsCameraRunningAndWindowingModeEligibleFullscreen(boolean enabled) { doReturn(enabled).when(getTopDisplayRotationCompatPolicy()) .isCameraRunningAndWindowingModeEligible(eq(mActivityStack.top()), /* mustBeFullscreen= */ eq(true)); } + void setIsCameraRunningAndWindowingModeEligibleFreeform(boolean enabled) { + doReturn(enabled).when(getTopCameraCompatFreeformPolicy()) + .isCameraRunningAndWindowingModeEligible(eq(mActivityStack.top())); + } + void setTopActivityEligibleForOrientationOverride(boolean enabled) { doReturn(enabled).when(getTopDisplayRotationCompatPolicy()) .isActivityEligibleForOrientationOverride(eq(mActivityStack.top())); @@ -508,8 +516,13 @@ class AppCompatActivityRobot { } private DisplayRotationCompatPolicy getTopDisplayRotationCompatPolicy() { - return mActivityStack.top().mDisplayContent - .mAppCompatCameraPolicy.mDisplayRotationCompatPolicy; + return mActivityStack.top().mDisplayContent.mAppCompatCameraPolicy + .mDisplayRotationCompatPolicy; + } + + private CameraCompatFreeformPolicy getTopCameraCompatFreeformPolicy() { + return mActivityStack.top().mDisplayContent.mAppCompatCameraPolicy + .mCameraCompatFreeformPolicy; } // We add the activity to the stack and spyOn() on its properties. 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 1e40aa0c8da8..b83911337c5c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatAspectRatioOverridesTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatAspectRatioOverridesTest.java @@ -282,7 +282,8 @@ public class AppCompatAspectRatioOverridesTest extends WindowTestsBase { robot.activity().createActivityWithComponentInNewTaskAndDisplay(); robot.checkFixedOrientationLetterboxAspectRatioForTopParent(/* expected */ 1.5f); - robot.activity().enableTreatmentForTopActivity(/* enabled */ true); + robot.activity().enableFullscreenCameraCompatTreatmentForTopActivity( + /* enabled */ true); robot.checkAspectRatioForTopParentIsSplitScreenRatio(/* expected */ true); }); } @@ -308,6 +309,12 @@ public class AppCompatAspectRatioOverridesTest extends WindowTestsBase { void onPostDisplayContentCreation(@NonNull DisplayContent displayContent) { super.onPostDisplayContentCreation(displayContent); spyOn(displayContent.mAppCompatCameraPolicy); + if (displayContent.mAppCompatCameraPolicy.hasDisplayRotationCompatPolicy()) { + spyOn(displayContent.mAppCompatCameraPolicy.mDisplayRotationCompatPolicy); + } + if (displayContent.mAppCompatCameraPolicy.hasCameraCompatFreeformPolicy()) { + spyOn(displayContent.mAppCompatCameraPolicy.mCameraCompatFreeformPolicy); + } } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java index 41102d6922da..cb5afd830619 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java @@ -18,13 +18,13 @@ package com.android.server.wm; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.server.wm.AppCompatCameraPolicy.isTreatmentEnabledForActivity; +import static com.android.server.wm.AppCompatCameraPolicy.shouldOverrideMinAspectRatioForCamera; import static com.android.window.flags.Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; import android.compat.testing.PlatformCompatChangeRule; import android.platform.test.annotations.DisableFlags; @@ -88,7 +88,7 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testCameraCompatFreeformPolicy_presentWhenEnabledAndDW() { runTestScenario((robot) -> { - robot.allowEnterDesktopMode(/* isAllowed= */ true); + robot.dw().allowEnterDesktopMode(/* isAllowed= */ true); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ true); }); @@ -98,7 +98,7 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testCameraCompatFreeformPolicy_notPresentWhenNoDW() { runTestScenario((robot) -> { - robot.allowEnterDesktopMode(/* isAllowed= */ false); + robot.dw().allowEnterDesktopMode(/* isAllowed= */ false); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ false); }); @@ -108,7 +108,7 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @DisableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testCameraCompatFreeformPolicy_notPresentWhenNoFlag() { runTestScenario((robot) -> { - robot.allowEnterDesktopMode(/* isAllowed= */ true); + robot.dw().allowEnterDesktopMode(/* isAllowed= */ true); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ false); }); @@ -118,7 +118,7 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testCameraCompatFreeformPolicy_notPresentWhenNoFlagAndNoDW() { runTestScenario((robot) -> { - robot.allowEnterDesktopMode(/* isAllowed= */ false); + robot.dw().allowEnterDesktopMode(/* isAllowed= */ false); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ false); }); @@ -128,7 +128,7 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testCameraCompatFreeformPolicy_startedWhenEnabledAndDW() { runTestScenario((robot) -> { - robot.allowEnterDesktopMode(/* isAllowed= */ true); + robot.dw().allowEnterDesktopMode(/* isAllowed= */ true); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ true); robot.checkTopActivityCameraCompatFreeformPolicyIsRunning(); @@ -139,7 +139,7 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testCameraStateManager_existsWhenCameraCompatFreeformExists() { runTestScenario((robot) -> { - robot.allowEnterDesktopMode(true); + robot.dw().allowEnterDesktopMode(true); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ true); robot.checkTopActivityHasCameraStateMonitor(/* exists= */ true); @@ -150,7 +150,7 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testCameraStateManager_startedWhenCameraCompatFreeformExists() { runTestScenario((robot) -> { - robot.allowEnterDesktopMode(true); + robot.dw().allowEnterDesktopMode(true); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); robot.checkTopActivityHasCameraCompatFreeformPolicy(/* exists= */ true); robot.checkTopActivityHasCameraStateMonitor(/* exists= */ true); @@ -194,9 +194,10 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @Test public void testIsCameraCompatTreatmentActive_whenTreatmentForTopActivityIsEnabled() { runTestScenario((robot) -> { + robot.conf().enableCameraCompatTreatmentAtBuildTime(/* enabled= */ true); robot.applyOnActivity((a)-> { - a.createActivityWithComponent(); - a.enableTreatmentForTopActivity(/* enabled */ true); + a.createActivityWithComponentInNewTaskAndDisplay(); + a.enableFullscreenCameraCompatTreatmentForTopActivity(/* enabled */ true); }); robot.checkIsCameraCompatTreatmentActiveForTopActivity(/* active */ true); @@ -206,9 +207,10 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @Test public void testIsCameraCompatTreatmentNotActive_whenTreatmentForTopActivityIsDisabled() { runTestScenario((robot) -> { + robot.conf().enableCameraCompatTreatmentAtBuildTime(/* enabled= */ true); robot.applyOnActivity((a)-> { a.createActivityWithComponent(); - a.enableTreatmentForTopActivity(/* enabled */ false); + a.enableFullscreenCameraCompatTreatmentForTopActivity(/* enabled */ false); }); robot.checkIsCameraCompatTreatmentActiveForTopActivity(/* active */ false); @@ -220,9 +222,10 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { public void testShouldOverrideMinAspectRatioForCamera_whenCameraIsNotRunning() { runTestScenario((robot) -> { robot.applyOnActivity((a)-> { + robot.dw().allowEnterDesktopMode(true); robot.conf().enableCameraCompatTreatmentAtBuildTime(/* enabled= */ true); a.createActivityWithComponentInNewTaskAndDisplay(); - a.setTopActivityCameraActive(/* active */ false); + a.setIsCameraRunningAndWindowingModeEligibleFullscreen(/* enabled */ false); }); robot.checkShouldOverrideMinAspectRatioForCamera(/* active */ false); @@ -234,9 +237,10 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { public void testShouldOverrideMinAspectRatioForCamera_whenCameraIsRunning_overrideDisabled() { runTestScenario((robot) -> { robot.applyOnActivity((a)-> { + robot.dw().allowEnterDesktopMode(true); robot.conf().enableCameraCompatTreatmentAtBuildTime(/* enabled= */ true); a.createActivityWithComponentInNewTaskAndDisplay(); - a.setTopActivityCameraActive(/* active */ true); + a.setIsCameraRunningAndWindowingModeEligibleFullscreen(/* active */ true); }); robot.checkShouldOverrideMinAspectRatioForCamera(/* active */ false); @@ -245,12 +249,28 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { @Test @EnableCompatChanges(OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA) - public void testShouldOverrideMinAspectRatioForCamera_whenCameraIsRunning_overrideEnabled() { + public void testShouldOverrideMinAspectRatioForCameraFullscr_cameraIsRunning_overrideEnabled() { runTestScenario((robot) -> { robot.applyOnActivity((a)-> { robot.conf().enableCameraCompatTreatmentAtBuildTime(/* enabled= */ true); a.createActivityWithComponentInNewTaskAndDisplay(); - a.setTopActivityCameraActive(/* active */ true); + a.setIsCameraRunningAndWindowingModeEligibleFullscreen(/* active */ true); + }); + + robot.checkShouldOverrideMinAspectRatioForCamera(/* active */ true); + }); + } + + + @Test + @EnableCompatChanges(OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA) + @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) + public void testShouldOverrideMinAspectRatioForCameraFreeform_cameraRunning_overrideEnabled() { + runTestScenario((robot) -> { + robot.applyOnActivity((a)-> { + robot.dw().allowEnterDesktopMode(true); + a.createActivityWithComponentInNewTaskAndDisplay(); + a.setIsCameraRunningAndWindowingModeEligibleFreeform(/* active */ true); }); robot.checkShouldOverrideMinAspectRatioForCamera(/* active */ true); @@ -318,23 +338,11 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { } void checkIsCameraCompatTreatmentActiveForTopActivity(boolean active) { - assertEquals(getTopAppCompatCameraPolicy() - .isTreatmentEnabledForActivity(activity().top()), active); + assertEquals(active, isTreatmentEnabledForActivity(activity().top())); } void checkShouldOverrideMinAspectRatioForCamera(boolean expected) { - assertEquals(getTopAppCompatCameraPolicy() - .shouldOverrideMinAspectRatioForCamera(activity().top()), expected); - } - - // TODO(b/350460645): Create Desktop Windowing Robot to reuse common functionalities. - void allowEnterDesktopMode(boolean isAllowed) { - doReturn(isAllowed).when(() -> - DesktopModeHelper.canEnterDesktopMode(any())); - } - - private AppCompatCameraPolicy getTopAppCompatCameraPolicy() { - return activity().top().mDisplayContent.mAppCompatCameraPolicy; + assertEquals(expected, shouldOverrideMinAspectRatioForCamera(activity().top())); } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationOverridesTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationOverridesTest.java index d9b5f37be86c..8747cfae93f8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationOverridesTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationOverridesTest.java @@ -17,11 +17,13 @@ package com.android.server.wm; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; import static android.content.pm.ActivityInfo.OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.AppCompatOrientationOverrides.OrientationOverridesState.MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; import static com.android.server.wm.AppCompatOrientationOverrides.OrientationOverridesState.SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS; @@ -31,6 +33,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import android.compat.testing.PlatformCompatChangeRule; +import android.content.pm.ActivityInfo.ScreenOrientation; import android.platform.test.annotations.Presubmit; import androidx.annotation.NonNull; @@ -228,6 +231,25 @@ public class AppCompatOrientationOverridesTest extends WindowTestsBase { }); } + @Test + public void testOverrideRespectRequestedOrientationIsEnabled_bottomOrientationIsRespected() { + runTestScenario((robot) -> { + robot.applyOnActivity((a) -> { + a.setIgnoreOrientationRequest(true); + a.createActivityWithComponentInNewTask(); + robot.setOverrideRespectRequestedOrientationEnabled(true); + a.configureUnresizableTopActivity(SCREEN_ORIENTATION_LANDSCAPE); + robot.checkDisplayShouldIgnoreOrientationRequest(SCREEN_ORIENTATION_LANDSCAPE, + /* expected */ false); + + a.createActivityWithComponentInNewTask(); + a.setTopActivityInFreeformWindowingMode(true); + }); + robot.checkDisplayShouldIgnoreOrientationRequest(SCREEN_ORIENTATION_LANDSCAPE, + /* expected */ false); + }); + } + /** * Runs a test scenario providing a Robot. */ @@ -291,6 +313,22 @@ public class AppCompatOrientationOverridesTest extends WindowTestsBase { } } + void setOverrideRespectRequestedOrientationEnabled(boolean override) { + spyOn(getTopOrientationOverrides()); + doReturn(override).when(getTopOrientationOverrides()) + .isOverrideRespectRequestedOrientationEnabled(); + } + + void checkDisplayShouldIgnoreOrientationRequest(@ScreenOrientation int candidate, + boolean expected) { + assertEquals(expected, activity().displayContent() + .shouldIgnoreOrientationRequest(candidate)); + } + + void checkExpectedDisplayOrientation(@ScreenOrientation int expected) { + assertEquals(expected, activity().displayContent().getOrientation()); + } + void checkShouldUseDisplayLandscapeNaturalOrientation(boolean expected) { assertEquals(expected, getTopOrientationOverrides().shouldUseDisplayLandscapeNaturalOrientation()); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationPolicyTest.java index 9057b6cb99ea..09ed9baba096 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationPolicyTest.java @@ -38,6 +38,7 @@ import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.window.flags.Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.verify; @@ -45,6 +46,7 @@ import static org.mockito.Mockito.verify; import android.compat.testing.PlatformCompatChangeRule; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import androidx.annotation.NonNull; @@ -321,7 +323,22 @@ public class AppCompatOrientationPolicyTest extends WindowTestsBase { }); robot.applyOnActivity((a) -> { a.createActivityWithComponentInNewTaskAndDisplay(); - a.setTopActivityCameraActive(false); + a.setIsCameraRunningAndWindowingModeEligibleFullscreen(false); + }); + + robot.checkOverrideOrientation(/* candidate */ SCREEN_ORIENTATION_PORTRAIT, + /* expected */ SCREEN_ORIENTATION_PORTRAIT); + }); + } + + @Test + @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) + public void testOverrideOrientationIfNeeded_fullscrOverrideFreeform_cameraActivity_unchanged() { + runTestScenario((robot) -> { + robot.applyOnActivity((a) -> { + robot.dw().allowEnterDesktopMode(true); + a.createActivityWithComponentInNewTaskAndDisplay(); + a.setIsCameraRunningAndWindowingModeEligibleFreeform(false); }); robot.checkOverrideOrientation(/* candidate */ SCREEN_ORIENTATION_PORTRAIT, @@ -426,8 +443,8 @@ public class AppCompatOrientationPolicyTest extends WindowTestsBase { c.enablePolicyForIgnoringRequestedOrientation(true); }); robot.applyOnActivity((a) -> { - a.createActivityWithComponentInNewTask(); - a.enableTreatmentForTopActivity(true); + a.createActivityWithComponentInNewTaskAndDisplay(); + a.enableFullscreenCameraCompatTreatmentForTopActivity(true); }); robot.prepareRelaunchingAfterRequestedOrientationChanged(false); 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 5f2a63aa9eab..0d929abeb34a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatRobotBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatRobotBase.java @@ -39,6 +39,8 @@ abstract class AppCompatRobotBase { private final AppCompatComponentPropRobot mOptPropRobot; @NonNull private final AppCompatResourcesRobot mResourcesRobot; + @NonNull + private final DesktopWindowingRobot mDesktopWindowingRobot; AppCompatRobotBase(@NonNull WindowManagerService wm, @NonNull ActivityTaskManagerService atm, @@ -51,6 +53,7 @@ abstract class AppCompatRobotBase { new AppCompatConfigurationRobot(wm.mAppCompatConfiguration); mOptPropRobot = new AppCompatComponentPropRobot(wm); mResourcesRobot = new AppCompatResourcesRobot(wm.mContext.getResources()); + mDesktopWindowingRobot = new DesktopWindowingRobot(); } AppCompatRobotBase(@NonNull WindowManagerService wm, @@ -111,6 +114,11 @@ abstract class AppCompatRobotBase { return mResourcesRobot; } + @NonNull + DesktopWindowingRobot dw() { + return mDesktopWindowingRobot; + } + void applyOnResources(@NonNull Consumer<AppCompatResourcesRobot> consumer) { consumer.accept(mResourcesRobot); } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatUtilsTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatUtilsTest.java index d8373c5dc3d6..50c2c2fd926c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppCompatUtilsTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatUtilsTest.java @@ -18,16 +18,26 @@ package com.android.server.wm; import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_PORTRAIT_DEVICE_IN_LANDSCAPE; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import android.app.CameraCompatTaskInfo.FreeformCameraCompatMode; import android.app.TaskInfo; +import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; +import android.view.DisplayInfo; +import android.view.Surface; import androidx.annotation.NonNull; +import com.android.window.flags.Flags; + import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -174,9 +184,13 @@ public class AppCompatUtilsTest extends WindowTestsBase { } @Test + @EnableFlags(Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void getTaskInfoPropagatesCameraCompatMode() { runTestScenario((robot) -> { - robot.applyOnActivity(AppCompatActivityRobot::createActivityWithComponentInNewTask); + robot.dw().allowEnterDesktopMode(/* isAllowed= */ true); + robot.applyOnActivity( + AppCompatActivityRobot::createActivityWithComponentInNewTaskAndDisplay); + robot.setCameraCompatTreatmentEnabledForActivity(/* enabled= */ true); robot.setFreeformCameraCompatMode(CAMERA_COMPAT_FREEFORM_PORTRAIT_DEVICE_IN_LANDSCAPE); robot.checkTaskInfoFreeformCameraCompatMode( @@ -212,6 +226,15 @@ public class AppCompatUtilsTest extends WindowTestsBase { spyOn(activity.mAppCompatController.getAppCompatAspectRatioPolicy()); } + @Override + void onPostDisplayContentCreation(@NonNull DisplayContent displayContent) { + super.onPostDisplayContentCreation(displayContent); + mockPortraitDisplay(displayContent); + if (displayContent.mAppCompatCameraPolicy.hasCameraCompatFreeformPolicy()) { + spyOn(displayContent.mAppCompatCameraPolicy.mCameraCompatFreeformPolicy); + } + } + void transparentActivity(@NonNull Consumer<AppCompatTransparentActivityRobot> consumer) { // We always create at least an opaque activity in a Task. activity().createNewTaskWithBaseActivity(); @@ -235,8 +258,8 @@ public class AppCompatUtilsTest extends WindowTestsBase { } void setFreeformCameraCompatMode(@FreeformCameraCompatMode int mode) { - activity().top().mAppCompatController.getAppCompatCameraOverrides() - .setFreeformCameraCompatMode(mode); + doReturn(mode).when(activity().top().mDisplayContent.mAppCompatCameraPolicy + .mCameraCompatFreeformPolicy).getCameraCompatMode(activity().top()); } void checkTopActivityLetterboxReason(@NonNull String expected) { @@ -258,6 +281,24 @@ public class AppCompatUtilsTest extends WindowTestsBase { Assert.assertEquals(mode, getTopTaskInfo().appCompatTaskInfo .cameraCompatTaskInfo.freeformCameraCompatMode); } - } + void setCameraCompatTreatmentEnabledForActivity(boolean enabled) { + doReturn(enabled).when(activity().displayContent().mAppCompatCameraPolicy + .mCameraCompatFreeformPolicy).isTreatmentEnabledForActivity( + eq(activity().top()), anyBoolean()); + } + + private void mockPortraitDisplay(DisplayContent displayContent) { + doAnswer(invocation -> { + DisplayInfo displayInfo = new DisplayInfo(); + displayContent.getDisplay().getDisplayInfo(displayInfo); + displayInfo.rotation = Surface.ROTATION_90; + // Set height and width so that the natural orientation (when rotation is 0) is + // portrait. + displayInfo.logicalHeight = 600; + displayInfo.logicalWidth = 800; + return displayInfo; + }).when(displayContent.mWmService.mDisplayManagerInternal).getDisplayInfo(anyInt()); + } + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java index a8ccf95e1bb5..a07fd235d14f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java @@ -223,10 +223,13 @@ public class CameraCompatFreeformPolicyTests extends WindowTestsBase { setDisplayRotation(Surface.ROTATION_270); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); - callOnActivityConfigurationChanging(mActivity); + callOnActivityConfigurationChanging(mActivity, /* letterboxNew= */ true, + /* lastLetterbox= */ false); mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); - callOnActivityConfigurationChanging(mActivity); + // Activity is letterboxed from the previous configuration change. + callOnActivityConfigurationChanging(mActivity, /* letterboxNew= */ true, + /* lastLetterbox= */ true); assertInCameraCompatMode(CAMERA_COMPAT_FREEFORM_PORTRAIT_DEVICE_IN_LANDSCAPE); assertActivityRefreshRequested(/* refreshRequested */ true); @@ -264,6 +267,48 @@ public class CameraCompatFreeformPolicyTests extends WindowTestsBase { @Test @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) + public void testShouldRefreshActivity_appBoundsChanged_returnsTrue() { + configureActivity(SCREEN_ORIENTATION_PORTRAIT); + Configuration oldConfiguration = createConfiguration(/* letterbox= */ false); + Configuration newConfiguration = createConfiguration(/* letterbox= */ true); + mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); + + assertTrue(mCameraCompatFreeformPolicy.shouldRefreshActivity(mActivity, newConfiguration, + oldConfiguration)); + } + + @Test + @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) + public void testShouldRefreshActivity_displayRotationChanged_returnsTrue() { + configureActivity(SCREEN_ORIENTATION_PORTRAIT); + Configuration oldConfiguration = createConfiguration(/* letterbox= */ true); + Configuration newConfiguration = createConfiguration(/* letterbox= */ true); + + oldConfiguration.windowConfiguration.setDisplayRotation(0); + newConfiguration.windowConfiguration.setDisplayRotation(90); + mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); + + assertTrue(mCameraCompatFreeformPolicy.shouldRefreshActivity(mActivity, newConfiguration, + oldConfiguration)); + } + + @Test + @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) + public void testShouldRefreshActivity_appBoundsNorDisplayChanged_returnsFalse() { + configureActivity(SCREEN_ORIENTATION_PORTRAIT); + Configuration oldConfiguration = createConfiguration(/* letterbox= */ true); + Configuration newConfiguration = createConfiguration(/* letterbox= */ true); + + oldConfiguration.windowConfiguration.setDisplayRotation(0); + newConfiguration.windowConfiguration.setDisplayRotation(0); + mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); + + assertFalse(mCameraCompatFreeformPolicy.shouldRefreshActivity(mActivity, newConfiguration, + oldConfiguration)); + } + + @Test + @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testOnActivityConfigurationChanging_refreshDisabledViaFlag_noRefresh() throws Exception { configureActivity(SCREEN_ORIENTATION_PORTRAIT); @@ -306,6 +351,7 @@ public class CameraCompatFreeformPolicyTests extends WindowTestsBase { } @Test + @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testGetCameraCompatAspectRatio_activityNotInCameraCompat_returnsDefaultAspRatio() { configureActivity(SCREEN_ORIENTATION_FULL_USER); @@ -318,6 +364,7 @@ public class CameraCompatFreeformPolicyTests extends WindowTestsBase { } @Test + @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testGetCameraCompatAspectRatio_activityInCameraCompat_returnsConfigAspectRatio() { configureActivity(SCREEN_ORIENTATION_PORTRAIT); final float configAspectRatio = 1.5f; @@ -331,8 +378,8 @@ public class CameraCompatFreeformPolicyTests extends WindowTestsBase { /* delta= */ 0.001); } - @Test + @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testGetCameraCompatAspectRatio_inCameraCompatPerAppOverride_returnDefAspectRatio() { configureActivity(SCREEN_ORIENTATION_PORTRAIT); final float configAspectRatio = 1.5f; @@ -411,9 +458,15 @@ public class CameraCompatFreeformPolicyTests extends WindowTestsBase { } private void callOnActivityConfigurationChanging(ActivityRecord activity) { + callOnActivityConfigurationChanging(activity, /* letterboxNew= */ true, + /* lastLetterbox= */false); + } + + private void callOnActivityConfigurationChanging(ActivityRecord activity, boolean letterboxNew, + boolean lastLetterbox) { mActivityRefresher.onActivityConfigurationChanging(activity, - /* newConfig */ createConfiguration(/*letterbox=*/ true), - /* lastReportedConfig */ createConfiguration(/*letterbox=*/ false)); + /* newConfig */ createConfiguration(letterboxNew), + /* lastReportedConfig */ createConfiguration(lastLetterbox)); } private Configuration createConfiguration(boolean letterbox) { diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopWindowingRobot.java b/services/tests/wmtests/src/com/android/server/wm/DesktopWindowingRobot.java new file mode 100644 index 000000000000..285a5e246e0c --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/DesktopWindowingRobot.java @@ -0,0 +1,28 @@ +/* + * 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.wm; + +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; + +import static org.mockito.ArgumentMatchers.any; + +/** Robot for changing desktop windowing properties. */ +class DesktopWindowingRobot { + void allowEnterDesktopMode(boolean isAllowed) { + doReturn(isAllowed).when(() -> DesktopModeHelper.canEnterDesktopMode(any())); + } +} diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java index b26c267768a7..d2cf03dd4b9a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java @@ -41,7 +41,10 @@ import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.verify; import android.app.StatusBarManager; +import android.graphics.Rect; import android.os.Binder; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.view.InsetsFrameProvider; import android.view.InsetsSource; @@ -52,6 +55,7 @@ import android.view.WindowInsets; import androidx.test.filters.SmallTest; import com.android.server.statusbar.StatusBarManagerInternal; +import com.android.window.flags.Flags; import org.junit.Before; import org.junit.Test; @@ -95,6 +99,7 @@ public class InsetsPolicyTest extends WindowTestsBase { } @Test + @DisableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) public void testControlsForDispatch_freeformTaskVisible() { addStatusBar(); addNavigationBar(); @@ -108,6 +113,37 @@ public class InsetsPolicyTest extends WindowTestsBase { } @Test + @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) + public void testControlsForDispatch_fullscreenFreeformTaskVisible() { + addStatusBar(); + addNavigationBar(); + + final WindowState win = createWindow(null, WINDOWING_MODE_FREEFORM, + ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app"); + win.setBounds(new Rect()); + final InsetsSourceControl[] controls = addWindowAndGetControlsForDispatch(win); + + // The freeform (w/fullscreen bounds) app window can control both system bars. + assertNotNull(controls); + assertEquals(2, controls.length); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) + public void testControlsForDispatch_nonFullscreenFreeformTaskVisible() { + addStatusBar(); + addNavigationBar(); + + final WindowState win = createWindow(null, WINDOWING_MODE_FREEFORM, + ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app"); + win.getTask().setBounds(new Rect(1, 1, 10, 10)); + final InsetsSourceControl[] controls = addWindowAndGetControlsForDispatch(win); + + // The freeform (but not fullscreen bounds) app window must not control any system bars. + assertNull(controls); + } + + @Test public void testControlsForDispatch_forceStatusBarVisible() { addStatusBar().mAttrs.forciblyShownTypes |= statusBars(); addNavigationBar(); diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxAttachInputTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxAttachInputTest.java new file mode 100644 index 000000000000..7e1de4762681 --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxAttachInputTest.java @@ -0,0 +1,178 @@ +/* + * 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.wm; + +import static com.android.server.testutils.MockitoUtilsKt.eq; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +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.spy; +import static org.mockito.Mockito.verify; + +import android.graphics.Color; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.InputConfig; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.annotations.Presubmit; +import android.view.InputWindowHandle; +import android.view.SurfaceControl; +import android.view.WindowManager; + +import com.android.server.testutils.StubTransaction; +import com.android.window.flags.Flags; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; + +/** + * Test class for {@link Letterbox}. + * <p> + * Build/Install/Run: + * atest WmTests:LetterboxAttachInputTest + */ +@Presubmit +@RunWith(WindowTestRunner.class) +public class LetterboxAttachInputTest extends WindowTestsBase { + + private Letterbox mLetterbox; + private LetterboxTest.SurfaceControlMocker mSurfaces; + + @Before + public void setUp() throws Exception { + mSurfaces = new LetterboxTest.SurfaceControlMocker(); + AppCompatLetterboxOverrides letterboxOverrides = mock(AppCompatLetterboxOverrides.class); + doReturn(false).when(letterboxOverrides).shouldLetterboxHaveRoundedCorners(); + doReturn(Color.valueOf(Color.BLACK)).when(letterboxOverrides) + .getLetterboxBackgroundColor(); + doReturn(false).when(letterboxOverrides).hasWallpaperBackgroundForLetterbox(); + doReturn(0).when(letterboxOverrides).getLetterboxWallpaperBlurRadiusPx(); + doReturn(0.5f).when(letterboxOverrides).getLetterboxWallpaperDarkScrimAlpha(); + mLetterbox = new Letterbox(mSurfaces, StubTransaction::new, + mock(AppCompatReachabilityPolicy.class), letterboxOverrides, + () -> mock(SurfaceControl.class)); + mTransaction = spy(StubTransaction.class); + } + + @DisableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX) + @Test + public void testSurface_createdHasSlipperyInput_scrollingFromLetterboxDisabled() { + mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); + + attachInput(); + applySurfaceChanges(); + + assertNotNull(mSurfaces.top); + ArgumentCaptor<InputWindowHandle> handleCaptor = + ArgumentCaptor.forClass(InputWindowHandle.class); + verify(mTransaction).setInputWindowInfo(eq(mSurfaces.top), handleCaptor.capture()); + InputWindowHandle capturedHandle = handleCaptor.getValue(); + assertTrue((capturedHandle.inputConfig & InputConfig.SLIPPERY) != 0); + assertFalse((capturedHandle.inputConfig & InputConfig.SPY) != 0); + } + + @DisableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX) + @Test + public void testInputSurface_notCreated_scrollingFromLetterboxDisabled() { + mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); + + attachInput(); + applySurfaceChanges(); + + assertNull(mSurfaces.topInput); + } + + @EnableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX) + @Test + public void testSurface_createdHasNoInput_scrollingFromLetterboxEnabled() { + mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); + + attachInput(); + applySurfaceChanges(); + + assertNotNull(mSurfaces.top); + verify(mTransaction, never()).setInputWindowInfo(eq(mSurfaces.top), any()); + + } + + @EnableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX) + @Test + public void testInputSurface_createdHasSpyInput_scrollingFromLetterboxEnabled() { + mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); + + attachInput(); + applySurfaceChanges(); + + assertNotNull(mSurfaces.topInput); + ArgumentCaptor<InputWindowHandle> handleCaptor = + ArgumentCaptor.forClass(InputWindowHandle.class); + verify(mTransaction).setInputWindowInfo(eq(mSurfaces.topInput), handleCaptor.capture()); + InputWindowHandle capturedHandle = handleCaptor.getValue(); + assertTrue((capturedHandle.inputConfig & InputConfig.SPY) != 0); + assertFalse((capturedHandle.inputConfig & InputConfig.SLIPPERY) != 0); + } + + @EnableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX) + @Test + public void testInputSurfaceOrigin_applied_scrollingFromLetterboxEnabled() { + mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); + + attachInput(); + applySurfaceChanges(); + + verify(mTransaction).setPosition(mSurfaces.topInput, -1000, -2000); + } + + @EnableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX) + @Test + public void testInputSurfaceOrigin_changeCausesReapply_scrollingFromLetterboxEnabled() { + mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); + + attachInput(); + applySurfaceChanges(); + clearInvocations(mTransaction); + mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(0, 0)); + + assertTrue(mLetterbox.needsApplySurfaceChanges()); + + applySurfaceChanges(); + + verify(mTransaction).setPosition(mSurfaces.topInput, 0, 0); + } + + private void applySurfaceChanges() { + mLetterbox.applySurfaceChanges(/* syncTransaction */ mTransaction, + /* pendingTransaction */ mTransaction); + } + + private void attachInput() { + final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(); + final WindowToken windowToken = createTestWindowToken(0, mDisplayContent); + WindowState windowState = createWindowState(attrs, windowToken); + mLetterbox.attachInput(windowState); + } +} diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java index 400fe8b05526..0baa5171a541 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java @@ -33,14 +33,19 @@ import static org.mockito.Mockito.when; import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; +import android.platform.test.flag.junit.SetFlagsRule; import android.view.SurfaceControl; import androidx.test.filters.SmallTest; import com.android.server.testutils.StubTransaction; +import com.android.window.flags.Flags; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; @@ -56,9 +61,12 @@ import java.util.function.Supplier; @Presubmit public class LetterboxTest { - Letterbox mLetterbox; - SurfaceControlMocker mSurfaces; - SurfaceControl.Transaction mTransaction; + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + + private Letterbox mLetterbox; + private SurfaceControlMocker mSurfaces; + private SurfaceControl.Transaction mTransaction; private SurfaceControl mParentSurface = mock(SurfaceControl.class); private AppCompatLetterboxOverrides mLetterboxOverrides; @@ -183,6 +191,38 @@ public class LetterboxTest { verify(mTransaction).setPosition(mSurfaces.top, -1000, -2000); } + @DisableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX) + @Test + public void testSurface_created_scrollingFromLetterboxDisabled() { + mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); + applySurfaceChanges(); + assertNotNull(mSurfaces.top); + } + + @DisableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX) + @Test + public void testInputSurface_notCreated_scrollingFromLetterboxDisabled() { + mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); + applySurfaceChanges(); + assertNull(mSurfaces.topInput); + } + + @EnableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX) + @Test + public void testSurface_created_scrollingFromLetterboxEnabled() { + mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); + applySurfaceChanges(); + assertNotNull(mSurfaces.top); + } + + @EnableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX) + @Test + public void testInputSurface_notCreated_notAttachedInputAndScrollingFromLetterboxEnabled() { + mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); + applySurfaceChanges(); + assertNull(mSurfaces.topInput); + } + @Test public void testApplySurfaceChanges_setColor() { mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000)); @@ -283,15 +323,11 @@ public class LetterboxTest { /* pendingTransaction */ mTransaction); } - class SurfaceControlMocker implements Supplier<SurfaceControl.Builder> { - private SurfaceControl.Builder mLeftBuilder; - public SurfaceControl left; + static class SurfaceControlMocker implements Supplier<SurfaceControl.Builder> { private SurfaceControl.Builder mTopBuilder; public SurfaceControl top; - private SurfaceControl.Builder mRightBuilder; - public SurfaceControl right; - private SurfaceControl.Builder mBottomBuilder; - public SurfaceControl bottom; + private SurfaceControl.Builder mTopInputBuilder; + public SurfaceControl topInput; private SurfaceControl.Builder mFullWindowSurfaceBuilder; public SurfaceControl fullWindowSurface; @@ -300,32 +336,24 @@ public class LetterboxTest { final SurfaceControl.Builder builder = mock(SurfaceControl.Builder.class, InvocationOnMock::getMock); when(builder.setName(anyString())).then((i) -> { - if (((String) i.getArgument(0)).contains("left")) { - mLeftBuilder = (SurfaceControl.Builder) i.getMock(); - } else if (((String) i.getArgument(0)).contains("top")) { + if (((String) i.getArgument(0)).contains("Letterbox - top")) { mTopBuilder = (SurfaceControl.Builder) i.getMock(); - } else if (((String) i.getArgument(0)).contains("right")) { - mRightBuilder = (SurfaceControl.Builder) i.getMock(); - } else if (((String) i.getArgument(0)).contains("bottom")) { - mBottomBuilder = (SurfaceControl.Builder) i.getMock(); - } else if (((String) i.getArgument(0)).contains("fullWindow")) { + } else if (((String) i.getArgument(0)).contains("Letterbox - fullWindow")) { mFullWindowSurfaceBuilder = (SurfaceControl.Builder) i.getMock(); + } else if (((String) i.getArgument(0)).contains("LetterboxInput - top")) { + mTopInputBuilder = (SurfaceControl.Builder) i.getMock(); } return i.getMock(); }); doAnswer((i) -> { final SurfaceControl control = mock(SurfaceControl.class); - if (i.getMock() == mLeftBuilder) { - left = control; - } else if (i.getMock() == mTopBuilder) { + if (i.getMock() == mTopBuilder) { top = control; - } else if (i.getMock() == mRightBuilder) { - right = control; - } else if (i.getMock() == mBottomBuilder) { - bottom = control; } else if (i.getMock() == mFullWindowSurfaceBuilder) { fullWindowSurface = control; + } else if (i.getMock() == mTopInputBuilder) { + topInput = control; } return control; }).when(builder).build(); diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index adc969c40e35..72f4fa9158fb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -4881,6 +4881,25 @@ public class SizeCompatTests extends WindowTestsBase { assertNotEquals(SCREEN_ORIENTATION_UNSPECIFIED, mActivity.getOverrideOrientation()); } + + @Test + @EnableCompatChanges({ActivityRecord.UNIVERSAL_RESIZABLE_BY_DEFAULT}) + public void testUniversalResizeableByDefault() { + mSetFlagsRule.enableFlags(Flags.FLAG_UNIVERSAL_RESIZABLE_BY_DEFAULT); + mDisplayContent.setIgnoreOrientationRequest(false); + setUpApp(mDisplayContent); + assertFalse(mActivity.isUniversalResizeable()); + + mDisplayContent.setIgnoreOrientationRequest(true); + final int swDp = mDisplayContent.getConfiguration().smallestScreenWidthDp; + if (swDp < WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP) { + final int height = 100 + (int) (mDisplayContent.getDisplayMetrics().density + * WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP); + resizeDisplay(mDisplayContent, 100 + height, height); + } + assertTrue(mActivity.isUniversalResizeable()); + } + @Test public void testClearSizeCompat_resetOverrideConfig() { final int origDensity = 480; diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java index 401964c2f597..1fa657822189 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java @@ -23,6 +23,10 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.view.InsetsSource.FLAG_FORCE_CONSUMING; +import static android.view.WindowInsets.Type.captionBar; +import static android.view.WindowInsets.Type.ime; +import static android.view.WindowInsets.Type.navigationBars; +import static android.view.WindowInsets.Type.statusBars; import static android.view.WindowInsets.Type.systemOverlays; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; @@ -36,6 +40,7 @@ import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyFloat; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; 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; @@ -80,6 +85,8 @@ import android.os.ResultReceiver; import android.os.ShellCallback; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.util.ArraySet; import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner; import android.view.InsetsFrameProvider; @@ -103,6 +110,7 @@ import org.mockito.Mockito; import java.io.FileDescriptor; import java.util.ArrayList; import java.util.Comparator; +import java.util.List; import java.util.NoSuchElementException; @@ -967,7 +975,7 @@ public class WindowContainerTests extends WindowTestsBase { Rect insetsRect = new Rect(0, 200, 1080, 700); final int flags = FLAG_FORCE_CONSUMING; final InsetsFrameProvider provider = - new InsetsFrameProvider(owner, 1, WindowInsets.Type.captionBar()) + new InsetsFrameProvider(owner, 1, captionBar()) .setArbitraryRectangle(insetsRect) .setFlags(flags); task.addLocalInsetsFrameProvider(provider, owner); @@ -1678,6 +1686,178 @@ public class WindowContainerTests extends WindowTestsBase { assertFalse("The source must be removed.", hasLocalSource(task, provider.getId())); } + @Test + public void testSetExcludeInsetsTypes_appliedOnNodeAndChildren() { + final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm); + final TestWindowContainer root = builder.setLayer(0).build(); + + final TestWindowContainer child1 = root.addChildWindow(); + final TestWindowContainer child2 = root.addChildWindow(); + final TestWindowContainer child11 = child1.addChildWindow(); + final TestWindowContainer child12 = child1.addChildWindow(); + final TestWindowContainer child21 = child2.addChildWindow(); + + assertEquals(0, root.mMergedExcludeInsetsTypes); + assertEquals(0, child1.mMergedExcludeInsetsTypes); + assertEquals(0, child11.mMergedExcludeInsetsTypes); + assertEquals(0, child12.mMergedExcludeInsetsTypes); + assertEquals(0, child2.mMergedExcludeInsetsTypes); + assertEquals(0, child21.mMergedExcludeInsetsTypes); + + child1.setExcludeInsetsTypes(ime()); + assertEquals(0, root.mMergedExcludeInsetsTypes); + assertEquals(ime(), child1.mMergedExcludeInsetsTypes); + assertEquals(ime(), child11.mMergedExcludeInsetsTypes); + assertEquals(ime(), child12.mMergedExcludeInsetsTypes); + assertEquals(0, child2.mMergedExcludeInsetsTypes); + assertEquals(0, child21.mMergedExcludeInsetsTypes); + + child11.setExcludeInsetsTypes(navigationBars()); + assertEquals(0, root.mMergedExcludeInsetsTypes); + assertEquals(ime(), child1.mMergedExcludeInsetsTypes); + assertEquals(ime() | navigationBars(), child11.mMergedExcludeInsetsTypes); + assertEquals(ime(), child12.mMergedExcludeInsetsTypes); + assertEquals(0, child2.mMergedExcludeInsetsTypes); + assertEquals(0, child21.mMergedExcludeInsetsTypes); + + // overwriting the same value has no change + for (int i = 0; i < 2; i++) { + root.setExcludeInsetsTypes(statusBars()); + assertEquals(statusBars(), root.mMergedExcludeInsetsTypes); + assertEquals(statusBars() | ime(), child1.mMergedExcludeInsetsTypes); + assertEquals(statusBars() | ime() | navigationBars(), + child11.mMergedExcludeInsetsTypes); + assertEquals(statusBars() | ime(), child12.mMergedExcludeInsetsTypes); + assertEquals(statusBars(), child2.mMergedExcludeInsetsTypes); + assertEquals(statusBars(), child21.mMergedExcludeInsetsTypes); + } + + // set and reset type statusBars on child. Should have no effect because of parent + child2.setExcludeInsetsTypes(statusBars()); + assertEquals(statusBars(), root.mMergedExcludeInsetsTypes); + assertEquals(statusBars() | ime(), child1.mMergedExcludeInsetsTypes); + assertEquals(statusBars() | ime() | navigationBars(), child11.mMergedExcludeInsetsTypes); + assertEquals(statusBars() | ime(), child12.mMergedExcludeInsetsTypes); + assertEquals(statusBars(), child2.mMergedExcludeInsetsTypes); + assertEquals(statusBars(), child21.mMergedExcludeInsetsTypes); + + // reset + child2.setExcludeInsetsTypes(0); + assertEquals(statusBars(), root.mMergedExcludeInsetsTypes); + assertEquals(statusBars() | ime(), child1.mMergedExcludeInsetsTypes); + assertEquals(statusBars() | ime() | navigationBars(), child11.mMergedExcludeInsetsTypes); + assertEquals(statusBars() | ime(), child12.mMergedExcludeInsetsTypes); + assertEquals(statusBars(), child2.mMergedExcludeInsetsTypes); + assertEquals(statusBars(), child21.mMergedExcludeInsetsTypes); + + // when parent has statusBars also removed, it should be cleared from all children in the + // hierarchy + root.setExcludeInsetsTypes(0); + assertEquals(0, root.mMergedExcludeInsetsTypes); + assertEquals(ime(), child1.mMergedExcludeInsetsTypes); + assertEquals(ime() | navigationBars(), child11.mMergedExcludeInsetsTypes); + assertEquals(ime(), child12.mMergedExcludeInsetsTypes); + assertEquals(0, child2.mMergedExcludeInsetsTypes); + assertEquals(0, child21.mMergedExcludeInsetsTypes); + + // change on node should have no effect on siblings + child12.setExcludeInsetsTypes(captionBar()); + assertEquals(0, root.mMergedExcludeInsetsTypes); + assertEquals(ime(), child1.mMergedExcludeInsetsTypes); + assertEquals(ime() | navigationBars(), child11.mMergedExcludeInsetsTypes); + assertEquals(captionBar() | ime(), child12.mMergedExcludeInsetsTypes); + assertEquals(0, child2.mMergedExcludeInsetsTypes); + assertEquals(0, child21.mMergedExcludeInsetsTypes); + } + + @Test + @RequiresFlagsEnabled(android.view.inputmethod.Flags.FLAG_REFACTOR_INSETS_CONTROLLER) + public void testSetExcludeInsetsTypes_appliedAfterReparenting() { + final SurfaceControl mockSurfaceControl = mock(SurfaceControl.class); + final DisplayContent mockDisplayContent = mock(DisplayContent.class); + final var mockInsetsStateController = mock(InsetsStateController.class); + doReturn(mockInsetsStateController).when(mockDisplayContent).getInsetsStateController(); + + final WindowContainer root1 = createWindowContainerSpy(mockSurfaceControl, + mockDisplayContent); + final WindowContainer root2 = createWindowContainerSpy(mockSurfaceControl, + mockDisplayContent); + final WindowContainer child = createWindowContainerSpy(mockSurfaceControl, + mockDisplayContent); + doNothing().when(child).onConfigurationChanged(any()); + + root1.setExcludeInsetsTypes(ime()); + root2.setExcludeInsetsTypes(captionBar()); + assertEquals(ime(), root1.mMergedExcludeInsetsTypes); + assertEquals(captionBar(), root2.mMergedExcludeInsetsTypes); + assertEquals(0, child.mMergedExcludeInsetsTypes); + clearInvocations(mockInsetsStateController); + + root1.addChild(child, 0); + assertEquals(ime(), child.mMergedExcludeInsetsTypes); + verify(mockInsetsStateController).notifyInsetsChanged( + new ArraySet<>(List.of(child.asWindowState()))); + clearInvocations(mockInsetsStateController); + + // Make sure that reparenting does not call notifyInsetsChanged twice + child.reparent(root2, 0); + assertEquals(captionBar(), child.mMergedExcludeInsetsTypes); + verify(mockInsetsStateController).notifyInsetsChanged( + new ArraySet<>(List.of(child.asWindowState()))); + } + + @Test + @RequiresFlagsEnabled(android.view.inputmethod.Flags.FLAG_REFACTOR_INSETS_CONTROLLER) + public void testSetExcludeInsetsTypes_notifyInsetsAfterChange() { + final var mockDisplayContent = mock(DisplayContent.class); + final var mockInsetsStateController = mock(InsetsStateController.class); + doReturn(mockInsetsStateController).when(mockDisplayContent).getInsetsStateController(); + + final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm); + final WindowState mockRootWs = mock(WindowState.class); + final TestWindowContainer root = builder.setLayer(0).setAsWindowState(mockRootWs).build(); + root.mDisplayContent = mockDisplayContent; + verify(mockInsetsStateController, never()).notifyInsetsChanged(any()); + + root.setExcludeInsetsTypes(ime()); + assertEquals(ime(), root.mMergedExcludeInsetsTypes); + verify(mockInsetsStateController).notifyInsetsChanged( + new ArraySet<>(List.of(root.asWindowState()))); + clearInvocations(mockInsetsStateController); + + // adding a child (while parent has set excludedInsetsTypes) should trigger + // notifyInsetsChanged + final WindowState mockChildWs = mock(WindowState.class); + final TestWindowContainer child1 = builder.setLayer(0).setAsWindowState( + mockChildWs).build(); + child1.mDisplayContent = mockDisplayContent; + root.addChildWindow(child1); + // TestWindowContainer overrides onParentChanged and therefore doesn't call into + // mergeExcludeInsetsTypesAndNotifyInsetsChanged. This is checked in another test + assertTrue(child1.mOnParentChangedCalled); + child1.setExcludeInsetsTypes(ime()); + assertEquals(ime(), child1.mMergedExcludeInsetsTypes); + verify(mockInsetsStateController).notifyInsetsChanged( + new ArraySet<>(List.of(child1.asWindowState()))); + clearInvocations(mockInsetsStateController); + + // not changing excludedInsetsTypes should not trigger notifyInsetsChanged again + root.setExcludeInsetsTypes(ime()); + assertEquals(ime(), root.mMergedExcludeInsetsTypes); + assertEquals(ime(), child1.mMergedExcludeInsetsTypes); + verify(mockInsetsStateController, never()).notifyInsetsChanged(any()); + } + + private WindowContainer<?> createWindowContainerSpy(SurfaceControl mockSurfaceControl, + DisplayContent mockDisplayContent) { + final WindowContainer<?> wc = spy(new WindowContainer<>(mWm)); + final WindowState mocWs = mock(WindowState.class); + doReturn(mocWs).when(wc).asWindowState(); + wc.mSurfaceControl = mockSurfaceControl; + wc.mDisplayContent = mockDisplayContent; + return wc; + } + private static boolean hasLocalSource(WindowContainer container, int sourceId) { if (container.mLocalInsetsSources == null) { return false; @@ -1693,6 +1873,7 @@ public class WindowContainerTests extends WindowTestsBase { private boolean mFillsParent; private boolean mWaitForTransitStart; private Integer mOrientation; + private WindowState mWindowState; private boolean mOnParentChangedCalled; private boolean mOnDescendantOverrideCalled; @@ -1714,7 +1895,7 @@ public class WindowContainerTests extends WindowTestsBase { }; TestWindowContainer(WindowManagerService wm, int layer, boolean isAnimating, - boolean isVisible, boolean waitTransitStart, Integer orientation) { + boolean isVisible, boolean waitTransitStart, Integer orientation, WindowState ws) { super(wm); mLayer = layer; @@ -1723,6 +1904,7 @@ public class WindowContainerTests extends WindowTestsBase { mFillsParent = true; mOrientation = orientation; mWaitForTransitStart = waitTransitStart; + mWindowState = ws; spyOn(mSurfaceAnimator); doReturn(mIsAnimating).when(mSurfaceAnimator).isAnimating(); doReturn(ANIMATION_TYPE_APP_TRANSITION).when(mSurfaceAnimator).getAnimationType(); @@ -1790,6 +1972,11 @@ public class WindowContainerTests extends WindowTestsBase { boolean isWaitingForTransitionStart() { return mWaitForTransitStart; } + + @Override + WindowState asWindowState() { + return mWindowState; + } } private static class TestWindowContainerBuilder { @@ -1799,6 +1986,7 @@ public class WindowContainerTests extends WindowTestsBase { private boolean mIsVisible; private boolean mIsWaitTransitStart; private Integer mOrientation; + private WindowState mWindowState; TestWindowContainerBuilder(WindowManagerService wm) { mWm = wm; @@ -1806,6 +1994,7 @@ public class WindowContainerTests extends WindowTestsBase { mIsAnimating = false; mIsVisible = false; mOrientation = null; + mWindowState = null; } TestWindowContainerBuilder setLayer(int layer) { @@ -1828,6 +2017,11 @@ public class WindowContainerTests extends WindowTestsBase { return this; } + TestWindowContainerBuilder setAsWindowState(WindowState ws) { + mWindowState = ws; + return this; + } + TestWindowContainerBuilder setWaitForTransitionStart(boolean waitTransitStart) { mIsWaitTransitStart = waitTransitStart; return this; @@ -1835,7 +2029,7 @@ public class WindowContainerTests extends WindowTestsBase { TestWindowContainer build() { return new TestWindowContainer(mWm, mLayer, mIsAnimating, mIsVisible, - mIsWaitTransitStart, mOrientation); + mIsWaitTransitStart, mOrientation, mWindowState); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java index 714eb4b3c093..35328a0e1dc0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java @@ -23,6 +23,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT; @@ -157,7 +158,16 @@ public class WindowTokenTests extends WindowTestsBase { // Verify that the other token window is still around. assertEquals(1, token.getWindowsCount()); + final TransitionController transitionController = token.mTransitionController; + spyOn(transitionController); + doReturn(true).when(transitionController).isPlayingTarget(token); window2.removeImmediately(); + assertTrue(token.mIsExiting); + assertNotNull("Defer removal for playing transition", token.getParent()); + + doReturn(false).when(transitionController).isPlayingTarget(token); + token.handleCompleteDeferredRemoval(); + assertFalse(token.mIsExiting); // Verify that the token is no-longer attached to its parent assertNull(token.getParent()); // Verify that the token windows are no longer attached to it. diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/NewVolumeDialog.kt b/services/usb/java/com/UsbDataSignalDisableRequesters.java index 869b3c65d70e..d4d6492ab984 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/NewVolumeDialog.kt +++ b/services/usb/java/com/UsbDataSignalDisableRequesters.java @@ -14,21 +14,23 @@ * limitations under the License. */ -package com.android.systemui.volume.dialog +package com.android.server.usb; -import android.app.Dialog -import android.content.Context -import android.os.Bundle -import android.view.ContextThemeWrapper -import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.res.R -import javax.inject.Inject +import android.util.ArraySet; -class NewVolumeDialog @Inject constructor(@Application context: Context) : - Dialog(ContextThemeWrapper(context, R.style.volume_dialog_theme)) { +/** + * A helper class to store and manage the request for disabling USB port data signaling. + * + * External requesters are identified by UIDs. + * Internal requesters are identified by a reason code enumerated in UsbManagerInternal. + * + * @hide + */ +public final class UsbDataSignalDisableRequesters { + final ArraySet<Integer> mExternalUids = new ArraySet<>(); + final ArraySet<Integer> mInternalReasons = new ArraySet<>(); - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.volume_dialog) + public boolean isEmpty() { + return mExternalUids.isEmpty() && mInternalReasons.isEmpty(); } -} +}
\ No newline at end of file diff --git a/services/usb/java/com/android/server/usb/UsbManagerInternal.java b/services/usb/java/com/android/server/usb/UsbManagerInternal.java new file mode 100644 index 000000000000..c97df6b4f63a --- /dev/null +++ b/services/usb/java/com/android/server/usb/UsbManagerInternal.java @@ -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.server.usb; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.hardware.usb.IUsbOperationInternal; +import android.hardware.usb.UsbPort; +import android.util.ArraySet; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * UsbManagerInternal provides internal APIs for the UsbService to + * reduce IPC overhead costs and support internal USB data signal stakers. + * + * @hide Only for use within the system server. + */ +public abstract class UsbManagerInternal { + + public static final int OS_USB_DISABLE_REASON_AAPM = 0; + + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {OS_USB_DISABLE_REASON_AAPM}) + public @interface OsUsbDisableReason { + } + + public abstract boolean enableUsbData(String portId, boolean enable, + int operationId, IUsbOperationInternal callback, @OsUsbDisableReason int disableReason); + + public abstract UsbPort[] getPorts(); + +}
\ No newline at end of file diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index 9470c0a944c2..ba9dff656f0a 100644 --- a/services/usb/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -46,6 +46,7 @@ import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbManager; import android.hardware.usb.UsbPort; import android.hardware.usb.UsbPortStatus; + import android.os.Binder; import android.os.Bundle; import android.os.Looper; @@ -69,6 +70,7 @@ import com.android.internal.util.Preconditions; import com.android.internal.util.dump.DualDumpOutputStream; import com.android.internal.widget.LockPatternUtils; import com.android.server.FgThread; +import com.android.server.LocalServices; import com.android.server.SystemServerInitThreadPool; import com.android.server.SystemService; @@ -165,8 +167,10 @@ public class UsbService extends IUsbManager.Stub { private final Object mLock = new Object(); // Key: USB port id - // Value: A set of UIDs of requesters who request disabling usb data - private final ArrayMap<String, ArraySet<Integer>> mUsbDisableRequesters = new ArrayMap<>(); + // Value: UsbDataSignalDisableRequesters: UIDs of requesters who request + // disabling usb data and disable request reasons by local service callers + private final ArrayMap<String, UsbDataSignalDisableRequesters> + mUsbDisableRequesters = new ArrayMap<>(); /** * @return the {@link UsbUserSettingsManager} for the given userId @@ -221,6 +225,9 @@ public class UsbService extends IUsbManager.Stub { filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); mContext.registerReceiverAsUser(receiver, UserHandle.ALL, filter, null, null); + if(android.hardware.usb.flags.Flags.enableUsbDataSignalStakingInternal()) { + LocalServices.addService(UsbManagerInternal.class, new UsbManagerInternalImpl()); + } } // Ideally we should use the injector pattern so we wouldn't need this constructor for test @@ -236,6 +243,10 @@ public class UsbService extends IUsbManager.Stub { mUserManager = userManager; mSettingsManager = usbSettingsManager; mPermissionManager = new UsbPermissionManager(context, this); + + if(android.hardware.usb.flags.Flags.enableUsbDataSignalStakingInternal()) { + LocalServices.addService(UsbManagerInternal.class, new UsbManagerInternalImpl()); + } } /** @@ -903,15 +914,21 @@ public class UsbService extends IUsbManager.Stub { @Override public boolean enableUsbData(String portId, boolean enable, int operationId, IUsbOperationInternal callback) { - return enableUsbDataInternal(portId, enable, operationId, callback, Binder.getCallingUid()); + return enableUsbDataInternal(portId, enable, operationId, callback, + Binder.getCallingUid(), false); } /** - * Internal function abstracted for testing with callerUid + * Manages the enablement of USB data. Requester field could mean two things: + * 1. UID of the app that requested USB data to be disabled if caller is external. + * 2. Enumberated disable request reason if the caller is internal. + * + * For internal requests, isInternalRequest should be set to true. Since + * internal requests all share the same UID, the request managed separately. */ @VisibleForTesting boolean enableUsbDataInternal(String portId, boolean enable, int operationId, - IUsbOperationInternal callback, int callerUid) { + IUsbOperationInternal callback, int requester, boolean isInternalRequest) { Objects.requireNonNull(portId, "enableUsbData: portId must not be null. opId:" + operationId); Objects.requireNonNull(callback, "enableUsbData: callback must not be null. opId:" @@ -919,7 +936,7 @@ public class UsbService extends IUsbManager.Stub { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); if (android.hardware.usb.flags.Flags.enableUsbDataSignalStaking()) { - if (!shouldUpdateUsbSignaling(portId, enable, callerUid)) { + if (!shouldUpdateUsbSignaling(portId, enable, requester, isInternalRequest)) { try { callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL); } catch (RemoteException e) { @@ -949,25 +966,42 @@ public class UsbService extends IUsbManager.Stub { } /** + * Function to determine if USB data signaling state should be updated. + * Depending on if request is internal, input requester should be UID or enumerated disable + * reason. + * * If enable = true, exclude UID from update list. * If enable = false, include UID in update list. * Return false if enable = true and the list is empty (no updates). * Return true otherwise (let downstream decide on updates). */ - private boolean shouldUpdateUsbSignaling(String portId, boolean enable, int uid) { + private boolean shouldUpdateUsbSignaling(String portId, boolean enable, + int requester, boolean isInternalRequest) { + if(isInternalRequest && + !android.hardware.usb.flags.Flags.enableUsbDataSignalStakingInternal()) + return false; synchronized (mUsbDisableRequesters) { if (!mUsbDisableRequesters.containsKey(portId)) { - mUsbDisableRequesters.put(portId, new ArraySet<>()); + mUsbDisableRequesters.put(portId, new UsbDataSignalDisableRequesters()); } - - ArraySet<Integer> uidsOfDisableRequesters = mUsbDisableRequesters.get(portId); + UsbDataSignalDisableRequesters disableRequests = + mUsbDisableRequesters.get(portId); if (enable) { - uidsOfDisableRequesters.remove(uid); - // re-enable USB port (return true) if there are no other disable requesters - return uidsOfDisableRequesters.isEmpty(); + if(isInternalRequest) { + disableRequests.mInternalReasons.remove(requester); + } else { + disableRequests.mExternalUids.remove(requester); + } + // re-enable USB port (return true) if there are no other + // disable requesters + return disableRequests.isEmpty(); } else { - uidsOfDisableRequesters.add(uid); + if(isInternalRequest) { + disableRequests.mInternalReasons.add(requester); + } else { + disableRequests.mExternalUids.add(requester); + } } } return true; @@ -976,7 +1010,8 @@ public class UsbService extends IUsbManager.Stub { @Override public void enableUsbDataWhileDocked(String portId, int operationId, IUsbOperationInternal callback) { - enableUsbDataWhileDockedInternal(portId, operationId, callback, Binder.getCallingUid()); + enableUsbDataWhileDockedInternal(portId, operationId, callback, + Binder.getCallingUid(), false); } /** @@ -984,7 +1019,7 @@ public class UsbService extends IUsbManager.Stub { */ @VisibleForTesting void enableUsbDataWhileDockedInternal(String portId, int operationId, - IUsbOperationInternal callback, int callerUid) { + IUsbOperationInternal callback, int callerUid, boolean isInternalRequest) { Objects.requireNonNull(portId, "enableUsbDataWhileDocked: portId must not be null. opId:" + operationId); Objects.requireNonNull(callback, @@ -993,7 +1028,7 @@ public class UsbService extends IUsbManager.Stub { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); if (android.hardware.usb.flags.Flags.enableUsbDataSignalStaking()) { - if (!shouldUpdateUsbSignaling(portId, true, callerUid)) { + if (!shouldUpdateUsbSignaling(portId, true, callerUid, isInternalRequest)) { try { callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL); } catch (RemoteException e) { @@ -1455,10 +1490,11 @@ public class UsbService extends IUsbManager.Stub { public void onUidRemoved(int uid) { synchronized (mUsbDisableRequesters) { for (String portId : mUsbDisableRequesters.keySet()) { - ArraySet<Integer> disabledUid = mUsbDisableRequesters.get(portId); - if (disabledUid != null) { - disabledUid.remove(uid); - if (disabledUid.isEmpty()) { + UsbDataSignalDisableRequesters disableRequesters = + mUsbDisableRequesters.get(portId); + if (disableRequesters != null) { + disableRequesters.mExternalUids.remove(uid); + if (disableRequesters.isEmpty()) { enableUsbData(portId, true, PACKAGE_MONITOR_OPERATION_ID, new IUsbOperationInternal.Default()); } @@ -1496,4 +1532,19 @@ public class UsbService extends IUsbManager.Stub { } } } + + private class UsbManagerInternalImpl extends UsbManagerInternal { + @Override + public boolean enableUsbData(String portId, boolean enable, + int operationId, IUsbOperationInternal callback, + @OsUsbDisableReason int disableReason) { + return enableUsbDataInternal(portId, enable, operationId, callback, + disableReason, true); + } + + @Override + public UsbPort[] getPorts() { + return mPortManager.getPorts(); + } + } } diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java index ff9cba2795fd..f001232ea93e 100644 --- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java +++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java @@ -33,6 +33,7 @@ import android.util.ArrayMap; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.telephony.flags.Flags; import com.android.internal.telephony.util.TelephonyUtils; import java.util.ArrayList; @@ -185,11 +186,7 @@ public final class CarrierAppUtils { if (hasPrivileges) { // Only update enabled state for the app on /system. Once it has been // updated we shouldn't touch it. - if (!isUpdatedSystemApp(ai) && enabledSetting - == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT - || enabledSetting - == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED - || (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0) { + if (shouldUpdateEnabledState(ai, enabledSetting)) { Log.i(TAG, "Update state (" + packageName + "): ENABLED for user " + userId); context.createContextAsUser(UserHandle.of(userId), 0) @@ -330,6 +327,21 @@ public final class CarrierAppUtils { } } + private static boolean shouldUpdateEnabledState(ApplicationInfo appInfo, int enabledSetting) { + if (Flags.cleanupCarrierAppUpdateEnabledStateLogic()) { + return !isUpdatedSystemApp(appInfo) + && (enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT + || enabledSetting + == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED + || (appInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0); + } else { + return !isUpdatedSystemApp(appInfo) + && enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT + || enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED + || (appInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0; + } + } + /** * Returns the list of "default" carrier apps. * diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index ff966ae66e0a..f01cfc16868d 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -2741,7 +2741,7 @@ public class TelephonyManager { /** * Returns a constant indicating the device phone type. This - * indicates the type of radio used to transmit voice calls. + * indicates the type of radio used to transmit voice/data calls. * * @see #PHONE_TYPE_NONE * @see #PHONE_TYPE_GSM @@ -2753,7 +2753,7 @@ public class TelephonyManager { */ @RequiresFeature(PackageManager.FEATURE_TELEPHONY) public int getPhoneType() { - if (!isVoiceCapable()) { + if (!isVoiceCapable() && !isDataCapable()) { return PHONE_TYPE_NONE; } return getCurrentPhoneType(); diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java index bd5c7597ba14..49ca6f34d2d9 100644 --- a/telephony/java/android/telephony/satellite/SatelliteManager.java +++ b/telephony/java/android/telephony/satellite/SatelliteManager.java @@ -249,6 +249,13 @@ public final class SatelliteManager { public static final String KEY_PROVISION_SATELLITE_TOKENS = "provision_satellite"; /** + * Bundle key to get the response from + * {@link #deprovisionSatellite(List, Executor, OutcomeReceiver)}. + * @hide + */ + public static final String KEY_DEPROVISION_SATELLITE_TOKENS = "deprovision_satellite"; + + /** * The request was successfully processed. */ @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) @@ -2791,6 +2798,61 @@ public final class SatelliteManager { } } + /** + * Deliver the list of deprovisioned satellite subscriber infos. + * + * @param list The list of deprovisioned satellite subscriber infos. + * @param executor The executor on which the callback will be called. + * @param callback The callback object to which the result will be delivered. + * + * @throws SecurityException if the caller doesn't have required permission. + * @hide + */ + @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) + @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN) + public void deprovisionSatellite(@NonNull List<SatelliteSubscriberInfo> list, + @NonNull @CallbackExecutor Executor executor, + @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) { + Objects.requireNonNull(executor); + Objects.requireNonNull(callback); + + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + ResultReceiver receiver = new ResultReceiver(null) { + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + if (resultCode == SATELLITE_RESULT_SUCCESS) { + if (resultData.containsKey(KEY_DEPROVISION_SATELLITE_TOKENS)) { + boolean isUpdated = + resultData.getBoolean(KEY_DEPROVISION_SATELLITE_TOKENS); + executor.execute(() -> Binder.withCleanCallingIdentity(() -> + callback.onResult(isUpdated))); + } else { + loge("KEY_DEPROVISION_SATELLITE_TOKENS does not exist."); + executor.execute(() -> Binder.withCleanCallingIdentity(() -> + callback.onError(new SatelliteException( + SATELLITE_RESULT_REQUEST_FAILED)))); + } + } else { + executor.execute(() -> Binder.withCleanCallingIdentity(() -> + callback.onError(new SatelliteException(resultCode)))); + } + } + }; + telephony.deprovisionSatellite(list, receiver); + } else { + loge("deprovisionSatellite() invalid telephony"); + executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( + new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); + } + } catch (RemoteException ex) { + loge("deprovisionSatellite() RemoteException: " + ex); + executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError( + new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE)))); + } + } + @Nullable private static ITelephony getITelephony() { ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 3161d17681ed..61f01461232f 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -3444,4 +3444,15 @@ interface ITelephony { */ boolean overrideCarrierRoamingNtnEligibilityChanged( in boolean status, in boolean resetRequired); + + /** + * Deliver the list of deprovisioned satellite subscriber infos. + * + * @param list The list of deprovisioned satellite subscriber infos. + * @param result The result receiver that returns whether deliver success or fail. + * @hide + */ + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + + "android.Manifest.permission.SATELLITE_COMMUNICATION)") + void deprovisionSatellite(in List<SatelliteSubscriberInfo> list, in ResultReceiver result); } diff --git a/tests/FlickerTests/ActivityEmbedding/Android.bp b/tests/FlickerTests/ActivityEmbedding/Android.bp index c681ce96a269..529f84ac4e90 100644 --- a/tests/FlickerTests/ActivityEmbedding/Android.bp +++ b/tests/FlickerTests/ActivityEmbedding/Android.bp @@ -24,71 +24,6 @@ package { default_applicable_licenses: ["frameworks_base_license"], } -//////////////////////////////////////////////////////////////////////////////// -// Begin to cleanup after CL merges - -filegroup { - name: "FlickerTestsOtherCommon-src", - srcs: ["src/**/ActivityEmbeddingTestBase.kt"], -} - -filegroup { - name: "FlickerTestsOtherOpen-src", - srcs: ["src/**/open/*"], -} - -filegroup { - name: "FlickerTestsOtherRotation-src", - srcs: ["src/**/rotation/*"], -} - -java_library { - name: "FlickerTestsOtherCommon", - defaults: ["FlickerTestsDefault"], - srcs: [":FlickerTestsOtherCommon-src"], - static_libs: ["FlickerTestsBase"], -} - -java_defaults { - name: "FlickerTestsOtherDefaults", - defaults: ["FlickerTestsDefault"], - manifest: "AndroidManifest.xml", - package_name: "com.android.server.wm.flicker", - instrumentation_target_package: "com.android.server.wm.flicker", - test_config_template: "AndroidTestTemplate.xml", - static_libs: [ - "FlickerTestsBase", - "FlickerTestsOtherCommon", - ], - data: ["trace_config/*"], -} - -android_test { - name: "FlickerTestsOtherOpen", - defaults: ["FlickerTestsOtherDefaults"], - srcs: [":FlickerTestsOtherOpen-src"], -} - -android_test { - name: "FlickerTestsOtherRotation", - defaults: ["FlickerTestsOtherDefaults"], - srcs: [":FlickerTestsOtherRotation-src"], -} - -android_test { - name: "FlickerTestsOther", - defaults: ["FlickerTestsOtherDefaults"], - srcs: ["src/**/*"], - exclude_srcs: [ - ":FlickerTestsOtherOpen-src", - ":FlickerTestsOtherRotation-src", - ":FlickerTestsOtherCommon-src", - ], -} - -// End to cleanup after CL merges -//////////////////////////////////////////////////////////////////////////////// - android_test { name: "FlickerTestsActivityEmbedding", defaults: ["FlickerTestsDefault"], @@ -97,10 +32,7 @@ android_test { instrumentation_target_package: "com.android.server.wm.flicker", test_config_template: "AndroidTestTemplate.xml", srcs: ["src/**/*"], - static_libs: [ - "FlickerTestsBase", - "FlickerTestsOtherCommon", - ], + static_libs: ["FlickerTestsBase"], data: ["trace_config/*"], } diff --git a/tests/FlickerTests/ActivityEmbedding/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/OWNERS index 981b3168cdbb..981b3168cdbb 100644 --- a/tests/FlickerTests/ActivityEmbedding/OWNERS +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/OWNERS diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt index 519b4296d93a..f44e282e8116 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/CloseSecondaryActivityInSplitTest.kt @@ -38,7 +38,7 @@ import org.junit.runners.Parameterized * Setup: Launch A|B in split with B being the secondary activity. Transitions: Finish B and expect * A to become fullscreen. * - * To run this test: `atest FlickerTestsOther:CloseSecondaryActivityInSplitTest` + * To run this test: `atest FlickerTestsActivityEmbedding:CloseSecondaryActivityInSplitTest` */ @RequiresDevice @RunWith(Parameterized::class) diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt index 4cd6d15b2983..7a76dd9d1ebb 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/HorizontalSplitChangeRatioTest.kt @@ -39,7 +39,7 @@ import org.junit.runners.Parameterized * windows are equal in size. B is on the top and A is on the bottom. Transitions: Change the split * ratio to A:B=0.7:0.3, expect bounds change for both A and B. * - * To run this test: `atest FlickerTestsOther:HorizontalSplitChangeRatioTest` + * To run this test: `atest FlickerTestsActivityEmbedding:HorizontalSplitChangeRatioTest` */ @RequiresDevice @RunWith(Parameterized::class) diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt index 5df8b57294f0..08b5f38a4655 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/MainActivityStartsSecondaryWithAlwaysExpandTest.kt @@ -39,7 +39,7 @@ import org.junit.runners.Parameterized * Setup: Launch A|B in split with B being the secondary activity. Transitions: A start C with * alwaysExpand=true, expect C to launch in fullscreen and cover split A|B. * - * To run this test: `atest FlickerTestsOther:MainActivityStartsSecondaryWithAlwaysExpandTest` + * To run this test: `atest FlickerTestsActivityEmbedding:MainActivityStartsSecondaryWithAlwaysExpandTest` */ @RequiresDevice @RunWith(Parameterized::class) diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingPlaceholderSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingPlaceholderSplitTest.kt index 5009c7ce4e70..1f002a089486 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingPlaceholderSplitTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingPlaceholderSplitTest.kt @@ -34,7 +34,7 @@ import org.junit.runners.Parameterized * Test opening an activity that will launch another activity as ActivityEmbedding placeholder in * split. * - * To run this test: `atest FlickerTestsOther:OpenActivityEmbeddingPlaceholderSplitTest` + * To run this test: `atest FlickerTestsActivityEmbedding:OpenActivityEmbeddingPlaceholderSplitTest` */ @RequiresDevice @RunWith(Parameterized::class) diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt index 6327d92ed570..b78c3ec65e32 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenActivityEmbeddingSecondaryToSplitTest.kt @@ -34,7 +34,7 @@ import org.junit.runners.Parameterized /** * Test opening a secondary activity that will split with the main activity. * - * To run this test: `atest FlickerTestsOther:OpenActivityEmbeddingSecondaryToSplitTest` + * To run this test: `atest FlickerTestsActivityEmbedding:OpenActivityEmbeddingSecondaryToSplitTest` */ @RequiresDevice @RunWith(Parameterized::class) diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt index 78004ccc3f97..10167d71c255 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt @@ -39,7 +39,7 @@ import org.junit.runners.Parameterized * * Transitions: Let B start C, expect C to cover B and end up in split A|C. * - * To run this test: `atest FlickerTestsOther:OpenThirdActivityOverSplitTest` + * To run this test: `atest FlickerTestsActivityEmbedding:OpenThirdActivityOverSplitTest` */ @RequiresDevice @RunWith(Parameterized::class) diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt index eed9225d3da0..a0b910bb9ac3 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt @@ -41,7 +41,7 @@ import org.junit.runners.Parameterized * Setup: Start from a split A|B. Transition: B enters PIP, observe the window first goes fullscreen * then shrink to the bottom right corner on screen. * - * To run this test: `atest FlickerTestsOther:SecondaryActivityEnterPipTest` + * To run this test: `atest FlickerTestsActivityEmbedding:SecondaryActivityEnterPipTest` */ @RequiresDevice @RunWith(Parameterized::class) diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt index f5e6c7854eba..ea13f5f748e1 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/RotateSplitNoChangeTest.kt @@ -36,7 +36,7 @@ import org.junit.runners.Parameterized * Setup: Launch A|B in split with B being the secondary activity. Transitions: Rotate display, and * expect A and B to split evenly in new rotation. * - * To run this test: `atest FlickerTestsOther:RotateSplitNoChangeTest` + * To run this test: `atest FlickerTestsActivityEmbedding:RotateSplitNoChangeTest` */ @RequiresDevice @RunWith(Parameterized::class) diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/RTLStartSecondaryWithPlaceholderTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/RTLStartSecondaryWithPlaceholderTest.kt index 65a23e854e0b..2a177d53b037 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/RTLStartSecondaryWithPlaceholderTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/RTLStartSecondaryWithPlaceholderTest.kt @@ -37,7 +37,7 @@ import org.junit.runners.Parameterized * PlaceholderPrimary, which is configured to launch with PlaceholderSecondary in RTL. Expect split * PlaceholderSecondary|PlaceholderPrimary covering split B|A. * - * To run this test: `atest FlickerTestsOther:RTLStartSecondaryWithPlaceholderTest` + * To run this test: `atest FlickerTestsActivityEmbedding:RTLStartSecondaryWithPlaceholderTest` */ @RequiresDevice @RunWith(Parameterized::class) diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt index c3e1a1fa2e18..0ca8f37b239b 100644 --- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/EnterSystemSplitTest.kt @@ -47,7 +47,7 @@ import org.junit.runners.Parameterized * Setup: Launch A|B in split and secondaryApp, return to home. Transitions: Let AE Split A|B enter * splitscreen with secondaryApp. Resulting in A|B|secondaryApp. * - * To run this test: `atest FlickerTestsOther:EnterSystemSplitTest` + * To run this test: `atest FlickerTestsActivityEmbedding:EnterSystemSplitTest` */ @RequiresDevice @RunWith(Parameterized::class) diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/OWNERS new file mode 100644 index 000000000000..981b3168cdbb --- /dev/null +++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/OWNERS @@ -0,0 +1 @@ +# Bug component: 1168918 diff --git a/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt index e19e1ce35cd9..56b718a642db 100644 --- a/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt +++ b/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt @@ -31,7 +31,7 @@ import org.junit.runners.Parameterized /** * Test app closes by pressing back button * - * To run this test: `atest FlickerTests:CloseAppBackButtonTest` + * To run this test: `atest FlickerTestsAppClose:CloseAppBackButtonTest` * * Actions: * ``` diff --git a/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt index 47ed642cd5f5..5deacaf31802 100644 --- a/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt +++ b/tests/FlickerTests/AppClose/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt @@ -31,7 +31,7 @@ import org.junit.runners.Parameterized /** * Test app closes by pressing home button * - * To run this test: `atest FlickerTests:CloseAppHomeButtonTest` + * To run this test: `atest FlickerTestsAppClose:CloseAppHomeButtonTest` * * Actions: * ``` diff --git a/tests/FlickerTests/AppLaunch/Android.bp b/tests/FlickerTests/AppLaunch/Android.bp index b61739f100ab..17d0f967b1bd 100644 --- a/tests/FlickerTests/AppLaunch/Android.bp +++ b/tests/FlickerTests/AppLaunch/Android.bp @@ -24,69 +24,13 @@ package { default_applicable_licenses: ["frameworks_base_license"], } -//////////////////////////////////////////////////////////////////////////////// -// Begin to cleanup after CL merges - -filegroup { - name: "FlickerTestsAppLaunchCommon-src", - srcs: ["src/**/common/*"], -} - -filegroup { - name: "FlickerTestsAppLaunch1-src", - srcs: ["src/**/OpenAppFrom*"], -} - -java_library { - name: "FlickerTestsAppLaunchCommon", - defaults: ["FlickerTestsDefault"], - srcs: [":FlickerTestsAppLaunchCommon-src"], - static_libs: ["FlickerTestsBase"], -} - -android_test { - name: "FlickerTestsAppLaunch1", - defaults: ["FlickerTestsDefault"], - manifest: "AndroidManifest.xml", - test_config_template: "AndroidTestTemplate.xml", - srcs: [":FlickerTestsAppLaunch1-src"], - static_libs: [ - "FlickerTestsBase", - "FlickerTestsAppLaunchCommon", - ], - data: ["trace_config/*"], -} - -android_test { - name: "FlickerTestsAppLaunch2", - defaults: ["FlickerTestsDefault"], - manifest: "AndroidManifest.xml", - test_config_template: "AndroidTestTemplate.xml", - srcs: ["src/**/*"], - exclude_srcs: [ - ":FlickerTestsAppLaunchCommon-src", - ":FlickerTestsAppLaunch1-src", - ], - static_libs: [ - "FlickerTestsBase", - "FlickerTestsAppLaunchCommon", - ], - data: ["trace_config/*"], -} - -// End to cleanup after CL merges -//////////////////////////////////////////////////////////////////////////////// - android_test { name: "FlickerTestsAppLaunch", defaults: ["FlickerTestsDefault"], manifest: "AndroidManifest.xml", test_config_template: "AndroidTestTemplate.xml", srcs: ["src/**/*"], - static_libs: [ - "FlickerTestsBase", - "FlickerTestsAppLaunchCommon", - ], + static_libs: ["FlickerTestsBase"], data: ["trace_config/*"], } diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/ActivityTransitionTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/ActivityTransitionTest.kt index ffa90a33e7b3..01cdbb810379 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/ActivityTransitionTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/ActivityTransitionTest.kt @@ -35,7 +35,7 @@ import org.junit.runners.Parameterized /** * Test the back and forward transition between 2 activities. * - * To run this test: `atest FlickerTests:ActivitiesTransitionTest` + * To run this test: `atest FlickerTestsAppLaunch:ActivitiesTransitionTest` * * Actions: * ``` diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTest.kt index 8c285bda6616..3d9321c0b830 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIconColdTest.kt @@ -30,7 +30,7 @@ import org.junit.runners.Parameterized /** * Test cold launching an app from launcher * - * To run this test: `atest FlickerTests:OpenAppColdFromIcon` + * To run this test: `atest FlickerTestsAppLaunch:OpenAppColdFromIcon` * * Actions: * ``` diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt index 57da05f13bbb..92075303028c 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt @@ -30,7 +30,7 @@ import org.junit.runners.Parameterized /** * Test launching an app after cold opening camera * - * To run this test: `atest FlickerTests:OpenAppAfterCameraTest` + * To run this test: `atest FlickerTestsAppLaunch:OpenAppAfterCameraTest` * * Notes: Some default assertions are inherited [OpenAppTransition] */ diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTest.kt index 267f282db41c..cbe7c3241df3 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdTest.kt @@ -35,7 +35,7 @@ import org.junit.runners.Parameterized /** * Test cold launching an app from launcher * - * To run this test: `atest FlickerTests:OpenAppColdTest` + * To run this test: `atest FlickerTestsAppLaunch:OpenAppColdTest` * * Actions: * ``` diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTest.kt index 83065de8b592..b2941e70a2ed 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentWarmTest.kt @@ -34,7 +34,7 @@ import org.junit.runners.Parameterized /** * Test warm launching an app from launcher * - * To run this test: `atest FlickerTests:OpenAppWarmTest` + * To run this test: `atest FlickerTestsAppLaunch:OpenAppWarmTest` * * Actions: * ``` diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt index 6e6a3275191f..4048e0c89619 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromLockscreenViaIntentTest.kt @@ -41,7 +41,7 @@ import org.junit.runners.Parameterized * * This test assumes the device doesn't have AOD enabled * - * To run this test: `atest FlickerTests:OpenAppNonResizeableTest` + * To run this test: `atest FlickerTestsAppLaunch:OpenAppNonResizeableTest` * * Actions: * ``` diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt index 6d3eaeb9c1b3..064c76f1b92f 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt @@ -35,7 +35,7 @@ import org.junit.runners.Parameterized /** * Test launching an app from the recents app view (the overview) * - * To run this test: `atest FlickerTests:OpenAppFromOverviewTest` + * To run this test: `atest FlickerTestsAppLaunch:OpenAppFromOverviewTest` * * Actions: * ``` diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenCameraFromHomeOnDoubleClickPowerButtonTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenCameraFromHomeOnDoubleClickPowerButtonTest.kt index bec02d0e59c6..41423fd9eefe 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenCameraFromHomeOnDoubleClickPowerButtonTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenCameraFromHomeOnDoubleClickPowerButtonTest.kt @@ -41,7 +41,7 @@ import org.junit.runners.Parameterized /** * Test cold launching camera from launcher by double pressing power button * - * To run this test: `atest FlickerTests:OpenCameraOnDoubleClickPowerButton` + * To run this test: `atest FlickerTestsAppLaunch:OpenCameraOnDoubleClickPowerButton` * * Actions: * ``` diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenTransferSplashscreenAppFromLauncherTransition.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenTransferSplashscreenAppFromLauncherTransition.kt index e0aef8d1addd..9d7a9c6789f8 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenTransferSplashscreenAppFromLauncherTransition.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenTransferSplashscreenAppFromLauncherTransition.kt @@ -34,7 +34,7 @@ import org.junit.runners.Parameterized /** * Test cold launching an app from launcher * - * To run this test: `atest FlickerTests:OpenTransferSplashscreenAppFromLauncherTransition` + * To run this test: `atest FlickerTestsAppLaunch:OpenTransferSplashscreenAppFromLauncherTransition` * * Actions: * ``` diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt index f1144991c438..7e2d472f4c4d 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt @@ -42,7 +42,7 @@ import org.junit.runners.Parameterized /** * Test the [android.app.ActivityOptions.makeCustomTaskAnimation]. * - * To run this test: `atest FlickerTests:OverrideTaskTransitionTest` + * To run this test: `atest FlickerTestsAppLaunch:OverrideTaskTransitionTest` * * Actions: * ``` diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt index a71599d25632..95e8126964e7 100644 --- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt +++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt @@ -49,7 +49,7 @@ import org.junit.runners.Parameterized /** * Test the back and forward transition between 2 activities. * - * To run this test: `atest FlickerTests:TaskTransitionTest` + * To run this test: `atest FlickerTestsAppLaunch:TaskTransitionTest` * * Actions: * ``` diff --git a/tests/FlickerTests/IME/Android.bp b/tests/FlickerTests/IME/Android.bp index f80e6b4b2f5e..cba3d09ebefd 100644 --- a/tests/FlickerTests/IME/Android.bp +++ b/tests/FlickerTests/IME/Android.bp @@ -24,27 +24,6 @@ package { default_applicable_licenses: ["frameworks_base_license"], } -//////////////////////////////////////////////////////////////////////////////// -// Begin to cleanup after CL merges - -filegroup { - name: "FlickerTestsImeCommon-src", - srcs: ["src/**/common/*"], -} - -filegroup { - name: "FlickerTestsIme1-src", - srcs: ["src/**/Close*"], -} - -filegroup { - name: "FlickerTestsIme2-src", - srcs: ["src/**/ShowImeOnAppStart*"], -} - -// End to cleanup after CL merges -//////////////////////////////////////////////////////////////////////////////// - android_test { name: "FlickerTestsIme", defaults: ["FlickerTestsDefault"], @@ -60,67 +39,6 @@ android_test { } //////////////////////////////////////////////////////////////////////////////// -// Begin to cleanup after CL merges - -java_library { - name: "FlickerTestsImeCommon", - defaults: ["FlickerTestsDefault"], - srcs: [":FlickerTestsImeCommon-src"], - static_libs: ["FlickerTestsBase"], -} - -android_test { - name: "FlickerTestsIme1", - defaults: ["FlickerTestsDefault"], - manifest: "AndroidManifest.xml", - test_config_template: "AndroidTestTemplate.xml", - test_suites: [ - "device-tests", - "device-platinum-tests", - ], - srcs: [":FlickerTestsIme1-src"], - static_libs: [ - "FlickerTestsBase", - "FlickerTestsImeCommon", - ], - data: ["trace_config/*"], -} - -android_test { - name: "FlickerTestsIme2", - defaults: ["FlickerTestsDefault"], - manifest: "AndroidManifest.xml", - test_config_template: "AndroidTestTemplate.xml", - srcs: [":FlickerTestsIme2-src"], - static_libs: [ - "FlickerTestsBase", - "FlickerTestsImeCommon", - ], - data: ["trace_config/*"], -} - -android_test { - name: "FlickerTestsIme3", - defaults: ["FlickerTestsDefault"], - manifest: "AndroidManifest.xml", - test_config_template: "AndroidTestTemplate.xml", - srcs: ["src/**/*"], - exclude_srcs: [ - ":FlickerTestsIme1-src", - ":FlickerTestsIme2-src", - ":FlickerTestsImeCommon-src", - ], - static_libs: [ - "FlickerTestsBase", - "FlickerTestsImeCommon", - ], - data: ["trace_config/*"], -} - -// End to cleanup after CL merges -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// // Begin breakdowns for FlickerTestsIme module test_module_config { diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt index 2b6ddcb43f18..48ca36ff8012 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt @@ -33,7 +33,7 @@ import org.junit.runners.MethodSorters import org.junit.runners.Parameterized /** - * To run this test: `atest FlickerTestsIme1:CloseImeOnDismissPopupDialogTest` + * To run this test: `atest FlickerTestsIme:CloseImeOnDismissPopupDialogTest` */ @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt index 0344197c1425..e3f3aca135d1 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt @@ -34,7 +34,7 @@ import org.junit.runners.Parameterized /** * Test IME window closing to home transitions. - * To run this test: `atest FlickerTestsIme1:CloseImeOnGoHomeTest` + * To run this test: `atest FlickerTestsIme:CloseImeOnGoHomeTest` */ @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt index fde1373b032b..3509e5bfecaf 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt @@ -42,7 +42,7 @@ import org.junit.runners.Parameterized * * More details on b/190352379 * - * To run this test: `atest FlickerTestsIme1:CloseImeShownOnAppStartOnGoHomeTest` + * To run this test: `atest FlickerTestsIme:CloseImeShownOnAppStartOnGoHomeTest` */ @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt index ed6e8df3e293..53d7a3ff8f21 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt @@ -43,7 +43,7 @@ import org.junit.runners.Parameterized * * More details on b/190352379 * - * To run this test: `atest FlickerTestsIme1:CloseImeShownOnAppStartToAppOnPressBackTest` + * To run this test: `atest FlickerTestsIme:CloseImeShownOnAppStartToAppOnPressBackTest` */ @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt index 522c68bba0d1..4bc2705aa17d 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt @@ -35,7 +35,7 @@ import org.junit.runners.Parameterized /** * Test IME window closing back to app window transitions. - * To run this test: `atest FlickerTestsIme1:CloseImeToAppOnPressBackTest` + * To run this test: `atest FlickerTestsIme:CloseImeToAppOnPressBackTest` */ @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt index 05771e88fc83..6117bb0971d0 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt @@ -40,7 +40,7 @@ import org.junit.runners.Parameterized * Unlike {@link OpenImeWindowTest} testing IME window opening transitions, this test also verify * there is no flickering when back to the simple activity without requesting IME to show. * - * To run this test: `atest FlickerTestsIme1:CloseImeToHomeOnFinishActivityTest` + * To run this test: `atest FlickerTestsIme:CloseImeToHomeOnFinishActivityTest` */ @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt index 336fe6f991ca..9b8d86d82007 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt @@ -37,7 +37,7 @@ import org.junit.runners.Parameterized /** * Test IME window shown on the app with fixing portrait orientation. - * To run this test: `atest FlickerTestsIme2:OpenImeWindowToFixedPortraitAppTest` + * To run this test: `atest FlickerTestsIme:OpenImeWindowToFixedPortraitAppTest` */ @RequiresDevice @RunWith(Parameterized::class) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt index 34a708578396..f806fae01eb4 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt @@ -34,7 +34,7 @@ import org.junit.runners.Parameterized /** * Test IME window opening transitions. - * To run this test: `atest FlickerTestsIme2:ShowImeOnAppStartWhenLaunchingAppFromOverviewTest` + * To run this test: `atest FlickerTestsIme:ShowImeOnAppStartWhenLaunchingAppFromOverviewTest` */ @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt index 7c72c3187a7f..cc19f62a7cb3 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt @@ -36,7 +36,7 @@ import org.junit.runners.Parameterized /** * Test IME windows switching with 2-Buttons or gestural navigation. - * To run this test: `atest FlickerTestsIme2:ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest` + * To run this test: `atest FlickerTestsIme:ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest` */ @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt index fe5320cd1a46..4a4d3725d82c 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt @@ -36,7 +36,7 @@ import org.junit.runners.Parameterized /** * Launch an app that automatically displays the IME * - * To run this test: `atest FlickerTestsIme2:ShowImeOnAppStartWhenLaunchingAppTest` + * To run this test: `atest FlickerTestsIme:ShowImeOnAppStartWhenLaunchingAppTest` * * Actions: * ``` diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt index 82e53c81daaa..d47e7ad8d904 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt @@ -36,7 +36,7 @@ import org.junit.runners.Parameterized /** * Test IME window closing on lock and opening on screen unlock. - * To run this test: `atest FlickerTestsIme2:ShowImeOnUnlockScreenTest` + * To run this test: `atest FlickerTestsIme:ShowImeOnUnlockScreenTest` */ @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt index 9eaf998ed63f..47bf32483d69 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt @@ -33,7 +33,7 @@ import org.junit.runners.Parameterized /** * Test IME window opening transitions. - * To run this test: `atest FlickerTestsIme2:ShowImeWhenFocusingOnInputFieldTest` + * To run this test: `atest FlickerTestsIme:ShowImeWhenFocusingOnInputFieldTest` */ @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt index 7186a2c48c4c..e3118b4cae0c 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt @@ -41,7 +41,7 @@ import org.junit.runners.Parameterized /** * Test IME snapshot mechanism won't apply when transitioning from non-IME focused dialog activity. - * To run this test: `atest FlickerTestsIme2:ShowImeWhileDismissingThemedPopupDialogTest` + * To run this test: `atest FlickerTestsIme:ShowImeWhileDismissingThemedPopupDialogTest` */ @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt index eb63e4985a9f..064c07ea0dc0 100644 --- a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt +++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt @@ -39,7 +39,7 @@ import org.junit.runners.Parameterized /** * Test IME window layer will be associated with the app task when going to the overview screen. - * To run this test: `atest FlickerTestsIme2:ShowImeWhileEnteringOverviewTest` + * To run this test: `atest FlickerTestsIme:ShowImeWhileEnteringOverviewTest` */ @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) diff --git a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt index 9bb62e1e1794..1a32f2045546 100644 --- a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt +++ b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt @@ -38,7 +38,7 @@ import org.junit.runners.Parameterized /** * Test quick switching back to previous app from last opened app * - * To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsBackTest` + * To run this test: `atest FlickerTestsQuickswitch:QuickSwitchBetweenTwoAppsBackTest` * * Actions: * ``` diff --git a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt index 491b9945d12d..d82dddd9eeeb 100644 --- a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt +++ b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt @@ -37,7 +37,7 @@ import org.junit.runners.Parameterized /** * Test quick switching back to previous app from last opened app * - * To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsForwardTest` + * To run this test: `atest FlickerTestsQuickswitch:QuickSwitchBetweenTwoAppsForwardTest` * * Actions: * ``` diff --git a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt index de54c95da361..ab366286b6d8 100644 --- a/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt +++ b/tests/FlickerTests/QuickSwitch/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt @@ -38,7 +38,7 @@ import org.junit.runners.Parameterized /** * Test quick switching to last opened app from launcher * - * To run this test: `atest FlickerTests:QuickSwitchFromLauncherTest` + * To run this test: `atest FlickerTestsQuickswitch:QuickSwitchFromLauncherTest` * * Actions: * ``` diff --git a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt index 05ab364ed72c..49e2553ab4a1 100644 --- a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt +++ b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt @@ -48,7 +48,7 @@ import org.junit.runners.Parameterized * Stop tracing * ``` * - * To run this test: `atest FlickerTests:ChangeAppRotationTest` + * To run this test: `atest FlickerTestsRotation:ChangeAppRotationTest` * * To run only the presubmit assertions add: `-- * diff --git a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt index a41362857420..d7f91e009c92 100644 --- a/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt +++ b/tests/FlickerTests/Rotation/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt @@ -55,7 +55,7 @@ import org.junit.runners.Parameterized * Stop tracing * ``` * - * To run this test: `atest FlickerTests:SeamlessAppRotationTest` + * To run this test: `atest FlickerTestsRotation:SeamlessAppRotationTest` * * To run only the presubmit assertions add: `-- * diff --git a/tests/Internal/src/com/android/internal/os/ApplicationSharedMemoryTest.java b/tests/Internal/src/com/android/internal/os/ApplicationSharedMemoryTest.java index e3a129fb1059..d03ad5cb2877 100644 --- a/tests/Internal/src/com/android/internal/os/ApplicationSharedMemoryTest.java +++ b/tests/Internal/src/com/android/internal/os/ApplicationSharedMemoryTest.java @@ -61,8 +61,13 @@ public class ApplicationSharedMemoryTest { @Test public void canRead() { ApplicationSharedMemory instance = ApplicationSharedMemory.getInstance(); - instance.getLatestNetworkTimeUnixEpochMillisAtZeroElapsedRealtimeMillis(); - // Don't actually care about the value of the above. + try { + instance.getLatestNetworkTimeUnixEpochMillisAtZeroElapsedRealtimeMillis(); + // Don't actually care about the value of the above. + } catch (java.time.DateTimeException e) { + // This exception is okay during testing. It means there was no time source, which + // could be because of network problems or a feature being flagged off. + } } /** Application processes should not have mutable access. */ diff --git a/tests/Internal/src/com/android/internal/os/OWNERS b/tests/Internal/src/com/android/internal/os/OWNERS new file mode 100644 index 000000000000..64ffa463bac1 --- /dev/null +++ b/tests/Internal/src/com/android/internal/os/OWNERS @@ -0,0 +1,2 @@ +# ApplicationSharedMemory +per-file *ApplicationSharedMemory* = file:/PERFORMANCE_OWNERS diff --git a/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java b/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java index 56845aeb6a2c..51d57f0a0de9 100644 --- a/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java +++ b/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java @@ -18,6 +18,10 @@ package com.android.server.usb; import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL; +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -31,12 +35,15 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.hardware.usb.IUsbOperationInternal; import android.hardware.usb.flags.Flags; +import android.hardware.usb.UsbPort; import android.os.RemoteException; import android.os.UserManager; import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.runner.AndroidJUnit4; +import com.android.server.LocalServices; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -71,26 +78,38 @@ public class UsbServiceTest { private static final int TEST_SECOND_CALLER_ID = 2000; + private static final int TEST_INTERNAL_REQUESTER_REASON_1 = 100; + + private static final int TEST_INTERNAL_REQUESTER_REASON_2 = 200; + private UsbService mUsbService; + private UsbManagerInternal mUsbManagerInternal; + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Before public void setUp() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_USB_DATA_SIGNAL_STAKING); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_USB_DATA_SIGNAL_STAKING_INTERNAL); + LocalServices.removeAllServicesForTest(); MockitoAnnotations.initMocks(this); - when(mUsbPortManager.enableUsbData(eq(TEST_PORT_ID), anyBoolean(), eq(TEST_TRANSACTION_ID), - eq(mCallback), any())).thenReturn(true); + when(mUsbPortManager.enableUsbData(eq(TEST_PORT_ID), anyBoolean(), + eq(TEST_TRANSACTION_ID), eq(mCallback), any())).thenReturn(true); mUsbService = new UsbService(mContext, mUsbPortManager, mUsbAlsaManager, mUserManager, mUsbSettingsManager); + mUsbManagerInternal = LocalServices.getService(UsbManagerInternal.class); + assertWithMessage("LocalServices.getService(UsbManagerInternal.class)") + .that(mUsbManagerInternal).isNotNull(); } - private void assertToggleUsbSuccessfully(int uid, boolean enable) { + private void assertToggleUsbSuccessfully(int requester, boolean enable, + boolean isInternalRequest) { assertTrue(mUsbService.enableUsbDataInternal(TEST_PORT_ID, enable, - TEST_TRANSACTION_ID, mCallback, uid)); + TEST_TRANSACTION_ID, mCallback, requester, isInternalRequest)); verify(mUsbPortManager).enableUsbData(TEST_PORT_ID, enable, TEST_TRANSACTION_ID, mCallback, null); @@ -100,9 +119,10 @@ public class UsbServiceTest { clearInvocations(mCallback); } - private void assertToggleUsbFailed(int uid, boolean enable) throws Exception { + private void assertToggleUsbFailed(int requester, boolean enable, + boolean isInternalRequest) throws Exception { assertFalse(mUsbService.enableUsbDataInternal(TEST_PORT_ID, enable, - TEST_TRANSACTION_ID, mCallback, uid)); + TEST_TRANSACTION_ID, mCallback, requester, isInternalRequest)); verifyZeroInteractions(mUsbPortManager); verify(mCallback).onOperationComplete(USB_OPERATION_ERROR_INTERNAL); @@ -116,15 +136,16 @@ public class UsbServiceTest { */ @Test public void disableUsb_successfullyDisable() { - assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false); + assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false, false); } /** - * Verify enableUsbData successfully enables USB port without error given no other stakers + * Verify enableUsbData successfully enables USB port without error given + * no other stakers */ @Test public void enableUsbWhenNoOtherStakers_successfullyEnable() { - assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, true); + assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, true, false); } /** @@ -132,47 +153,132 @@ public class UsbServiceTest { */ @Test public void enableUsbPortWithOtherStakers_failsToEnable() throws Exception { - assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false); + assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false, false); - assertToggleUsbFailed(TEST_SECOND_CALLER_ID, true); + assertToggleUsbFailed(TEST_SECOND_CALLER_ID, true, false); } /** - * Verify enableUsbData successfully enables USB port when the last staker is removed + * Verify enableUsbData successfully enables USB port when the last staker + * is removed */ @Test public void enableUsbByTheOnlyStaker_successfullyEnable() { - assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false); + assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false, false); - assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, true); + assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, true, false); } /** - * Verify enableUsbDataWhileDockedInternal does not enable USB port if other stakers are present + * Verify enableUsbDataWhileDockedInternal does not enable USB port if other + * stakers are present */ @Test public void enableUsbWhileDockedWhenThereAreOtherStakers_failsToEnable() throws RemoteException { - assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false); + assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false, false); mUsbService.enableUsbDataWhileDockedInternal(TEST_PORT_ID, TEST_TRANSACTION_ID, - mCallback, TEST_SECOND_CALLER_ID); + mCallback, TEST_SECOND_CALLER_ID, false); verifyZeroInteractions(mUsbPortManager); verify(mCallback).onOperationComplete(USB_OPERATION_ERROR_INTERNAL); } /** - * Verify enableUsbDataWhileDockedInternal does enable USB port if other stakers are - * not present + * Verify enableUsbDataWhileDockedInternal does enable USB port if other + * stakers are not present */ @Test public void enableUsbWhileDockedWhenThereAreNoStakers_SuccessfullyEnable() { mUsbService.enableUsbDataWhileDockedInternal(TEST_PORT_ID, TEST_TRANSACTION_ID, - mCallback, TEST_SECOND_CALLER_ID); + mCallback, TEST_SECOND_CALLER_ID, false); verify(mUsbPortManager).enableUsbDataWhileDocked(TEST_PORT_ID, TEST_TRANSACTION_ID, mCallback, null); verifyZeroInteractions(mCallback); } + + /** + * Verify enableUsbData successfully enables USB port without error given no + * other stakers for internal requests + */ + @Test + public void enableUsbWhenNoOtherStakers_forInternalRequest_successfullyEnable() { + assertToggleUsbSuccessfully(TEST_INTERNAL_REQUESTER_REASON_1, true, true); + } + + /** + * Verify enableUsbData does not enable USB port if other internal stakers + * are present for internal requests + */ + @Test + public void enableUsbPortWithOtherInternalStakers_forInternalRequest_failsToEnable() + throws Exception { + assertToggleUsbSuccessfully(TEST_INTERNAL_REQUESTER_REASON_1, false, true); + + assertToggleUsbFailed(TEST_INTERNAL_REQUESTER_REASON_2, true, true); + } + + /** + * Verify enableUsbData does not enable USB port if other external stakers + * are present for internal requests + */ + @Test + public void enableUsbPortWithOtherExternalStakers_forInternalRequest_failsToEnable() + throws Exception { + assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false, false); + + assertToggleUsbFailed(TEST_INTERNAL_REQUESTER_REASON_2, true, true); + } + + /** + * Verify enableUsbData does not enable USB port if other internal stakers + * are present for external requests + */ + @Test + public void enableUsbPortWithOtherInternalStakers_forExternalRequest_failsToEnable() + throws Exception { + assertToggleUsbSuccessfully(TEST_INTERNAL_REQUESTER_REASON_1, false, true); + + assertToggleUsbFailed(TEST_FIRST_CALLER_ID, true, false); + } + + /** + * Verify enableUsbData successfully enables USB port when the last staker + * is removed for internal requests + */ + @Test + public void enableUsbByTheOnlyStaker_forInternalRequest_successfullyEnable() { + assertToggleUsbSuccessfully(TEST_INTERNAL_REQUESTER_REASON_1, false, false); + + assertToggleUsbSuccessfully(TEST_INTERNAL_REQUESTER_REASON_1, true, false); + } + + /** + * Verify USB Manager internal calls mPortManager to get UsbPorts + */ + @Test + public void usbManagerInternal_getPorts_callsPortManager() { + when(mUsbPortManager.getPorts()).thenReturn(new UsbPort[] {}); + + UsbPort[] ports = mUsbManagerInternal.getPorts(); + + verify(mUsbPortManager).getPorts(); + assertEquals(ports.length, 0); + } + + @Test + public void usbManagerInternal_enableUsbData_successfullyEnable() { + boolean desiredEnableState = true; + + assertTrue(mUsbManagerInternal.enableUsbData(TEST_PORT_ID, desiredEnableState, + TEST_TRANSACTION_ID, mCallback, TEST_INTERNAL_REQUESTER_REASON_1)); + + verify(mUsbPortManager).enableUsbData(TEST_PORT_ID, + desiredEnableState, TEST_TRANSACTION_ID, mCallback, null); + verifyZeroInteractions(mCallback); + clearInvocations(mUsbPortManager); + clearInvocations(mCallback); + } } diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp index 1af8d6f67bd3..b2e48bd74e8a 100644 --- a/tools/aapt/StringPool.cpp +++ b/tools/aapt/StringPool.cpp @@ -40,7 +40,7 @@ void strcpy16_htod(uint16_t* dst, const char16_t* src) void printStringPool(const ResStringPool* pool) { if (pool->getError() == NO_INIT) { - printf("String pool is unitialized.\n"); + printf("String pool is uninitialized.\n"); return; } else if (pool->getError() != NO_ERROR) { printf("String pool is corrupt/invalid.\n"); diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp index 064b4617b0a2..2527dcd26382 100644 --- a/tools/aapt2/Debug.cpp +++ b/tools/aapt2/Debug.cpp @@ -445,7 +445,7 @@ void Debug::DumpResStringPool(const android::ResStringPool* pool, text::Printer* using namespace android; if (pool->getError() == NO_INIT) { - printer->Print("String pool is unitialized.\n"); + printer->Print("String pool is uninitialized.\n"); return; } else if (pool->getError() != NO_ERROR) { printer->Print("String pool is corrupt/invalid.\n"); diff --git a/tools/processors/property_cache/Android.bp b/tools/processors/property_cache/Android.bp new file mode 100644 index 000000000000..81fab7a4c862 --- /dev/null +++ b/tools/processors/property_cache/Android.bp @@ -0,0 +1,57 @@ +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"], + default_team: "trendy_team_framework_android_multiuser", +} + +java_library_host { + name: "libcached-property-annotation-processor", + srcs: [ + ":framework-annotations", + "src/**/*.java", + ], + static_libs: [ + "codegen-version-info", + "android.multiuser.flags-aconfig-java-host", + "guava", + ], + use_tools_jar: true, +} + +java_plugin { + name: "cached-property-annotation-processor", + processor_class: "android.processor.property_cache.CachedPropertyProcessor", + static_libs: ["libcached-property-annotation-processor"], +} + +java_aconfig_library { + name: "android.multiuser.flags-aconfig-java-host", + aconfig_declarations: "android.multiuser.flags-aconfig", + host_supported: true, + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + +java_test_host { + name: "cached-property-annotation-processor-test", + srcs: ["test/java/**/*.java"], + java_resources: [":CachedPropertyAnnotationJavaTestSource"], + static_libs: [ + "compile-testing-prebuilt", + "truth", + "junit", + "guava", + "libcached-property-annotation-processor", + ], + test_suites: ["general-tests"], +} + +filegroup { + name: "CachedPropertyAnnotationJavaTestSource", + srcs: ["test/resources/*.java"], + path: "test/resources/", + visibility: ["//visibility:private"], +} diff --git a/tools/processors/property_cache/TEST_MAPPING b/tools/processors/property_cache/TEST_MAPPING new file mode 100644 index 000000000000..7177abc8c52d --- /dev/null +++ b/tools/processors/property_cache/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "postsubmit": [ + { + "name": "cached-property-annotation-processor-test" + } + ] +} diff --git a/tools/processors/property_cache/src/java/android/processor/property_cache/CacheConfig.java b/tools/processors/property_cache/src/java/android/processor/property_cache/CacheConfig.java new file mode 100644 index 000000000000..c665c840f376 --- /dev/null +++ b/tools/processors/property_cache/src/java/android/processor/property_cache/CacheConfig.java @@ -0,0 +1,138 @@ +/* + * 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.processor.property_cache; + +import com.android.internal.annotations.CachedProperty; +import com.android.internal.annotations.CachedPropertyDefaults; + +import com.google.common.base.CaseFormat; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; + +public class CacheConfig { + private final CacheModifiers mModifiers; + private final int mMaxSize; + private final String mModuleName; + private final String mApiName; + private final String mClassName; + private final String mQualifiedName; + private String mPropertyName; + private String mMethodName; + private int mNumberOfParams = 0; + private String mInputType = Constants.JAVA_LANG_VOID; + private String mResultType; + + public CacheConfig(TypeElement classElement, ExecutableElement method) { + CachedPropertyDefaults classAnnotation = classElement.getAnnotation( + CachedPropertyDefaults.class); + CachedProperty methodAnnotation = method.getAnnotation(CachedProperty.class); + + mModuleName = methodAnnotation.module().isEmpty() ? classAnnotation.module() + : methodAnnotation.module(); + mClassName = classElement.getSimpleName().toString(); + mQualifiedName = classElement.getQualifiedName().toString(); + mModifiers = new CacheModifiers(methodAnnotation.modsFlagOnOrNone()); + mMethodName = method.getSimpleName().toString(); + mPropertyName = getPropertyName(mMethodName); + mApiName = methodAnnotation.api().isEmpty() ? getUniqueApiName(mClassName, mPropertyName) + : methodAnnotation.api(); + mMaxSize = methodAnnotation.max() == -1 ? classAnnotation.max() : methodAnnotation.max(); + mNumberOfParams = method.getParameters().size(); + if (mNumberOfParams > 0) { + mInputType = primitiveTypeToObjectEquivalent( + method.getParameters().get(0).asType().toString()); + } + mResultType = primitiveTypeToObjectEquivalent(method.getReturnType().toString()); + } + + public CacheModifiers getModifiers() { + return mModifiers; + } + + public int getMaxSize() { + return mMaxSize; + } + + public String getApiName() { + return mApiName; + } + + public String getClassName() { + return mClassName; + } + + public String getQualifiedName() { + return mQualifiedName; + } + + public String getModuleName() { + return mModuleName; + } + + public String getMethodName() { + return mMethodName; + } + + public String getPropertyName() { + return mPropertyName; + } + + public String getPropertyVariable() { + return (mModifiers.isStatic() ? "s" : "m") + mPropertyName; + } + + private String getPropertyName(String methodName) { + if (methodName.startsWith("get")) { + return methodName.substring(3); + } else if (methodName.startsWith("is")) { + return methodName.substring(2); + } else { + return CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, methodName); + } + } + + public int getNumberOfParams() { + return mNumberOfParams; + } + + public String getInputType() { + return mInputType; + } + + public String getResultType() { + return mResultType; + } + + /** + * This method returns the unique api name for a given class and property name. + * Property name is retrieved from the method name. + * Both names are combined and converted to lower snake case. + * + * @param className The name of the class that contains the property. + * @param propertyName The name of the property. + * @return The registration name for the property. + */ + private String getUniqueApiName(String className, String propertyName) { + return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, className + propertyName); + } + + private String primitiveTypeToObjectEquivalent(String simpleType) { + // checking against primitive types + return Constants.PRIMITIVE_TYPE_MAP.getOrDefault(simpleType, simpleType); + } +} diff --git a/tools/processors/property_cache/src/java/android/processor/property_cache/CacheModifiers.java b/tools/processors/property_cache/src/java/android/processor/property_cache/CacheModifiers.java new file mode 100644 index 000000000000..fda9b2c40e27 --- /dev/null +++ b/tools/processors/property_cache/src/java/android/processor/property_cache/CacheModifiers.java @@ -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 android.processor.property_cache; + +import com.android.internal.annotations.CacheModifier; + +import java.util.Arrays; +import java.util.List; + +public class CacheModifiers { + private final boolean mIsStatic; + private static final String STATIC_MODIFIER_STRING = "static "; + + CacheModifiers(CacheModifier[] modifierArray) { + final List<CacheModifier> modifiers = Arrays.asList(modifierArray); + mIsStatic = modifiers.contains(CacheModifier.STATIC); + } + + public boolean isStatic() { + return mIsStatic; + } + + public String getStaticModifier() { + return mIsStatic ? STATIC_MODIFIER_STRING : Constants.EMPTY_STRING; + } +} diff --git a/tools/processors/property_cache/src/java/android/processor/property_cache/CachedPropertyProcessor.java b/tools/processors/property_cache/src/java/android/processor/property_cache/CachedPropertyProcessor.java new file mode 100644 index 000000000000..03610128d269 --- /dev/null +++ b/tools/processors/property_cache/src/java/android/processor/property_cache/CachedPropertyProcessor.java @@ -0,0 +1,95 @@ +/* + * 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.processor.property_cache; + +import com.android.internal.annotations.CachedProperty; +import com.android.internal.annotations.CachedPropertyDefaults; + +import com.google.common.collect.ImmutableSet; + +import java.io.IOException; +import java.io.Writer; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Filer; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.ElementFilter; +import javax.tools.JavaFileObject; + +public class CachedPropertyProcessor extends AbstractProcessor { + + IpcDataCacheComposer mIpcDataCacheComposer = + new IpcDataCacheComposer(); + + @Override + public Set<String> getSupportedAnnotationTypes() { + return new HashSet<String>( + ImmutableSet.of(CachedPropertyDefaults.class.getCanonicalName())); + } + + @Override + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + for (Element element : roundEnv.getElementsAnnotatedWith(CachedPropertyDefaults.class)) { + try { + generateCachedClass((TypeElement) element, processingEnv.getFiler()); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + return false; + } + + private void generateCachedClass(TypeElement classElement, Filer filer) throws IOException { + String packageName = + processingEnv + .getElementUtils() + .getPackageOf(classElement) + .getQualifiedName() + .toString(); + String className = classElement.getSimpleName().toString() + "Cache"; + JavaFileObject jfo = filer.createSourceFile(packageName + "." + className); + Writer writer = jfo.openWriter(); + writer.write("package " + packageName + ";\n\n"); + writer.write("import android.os.IpcDataCache;\n"); + writer.write("\n /** \n * This class is auto-generated \n * @hide \n **/"); + writer.write("\npublic class " + className + " {\n"); + + List<ExecutableElement> methods = + ElementFilter.methodsIn(classElement.getEnclosedElements()); + String initCache = String.format(Constants.METHOD_COMMENT, + " - initialise all caches for class " + className) + + "\npublic static void initCache() {"; + for (ExecutableElement method : methods) { + if (method.getAnnotation(CachedProperty.class) != null) { + mIpcDataCacheComposer.generatePropertyCache(writer, classElement, method); + initCache += "\n " + mIpcDataCacheComposer.generateInvalidatePropertyCall(); + } + } + initCache += "\n}"; + writer.write(initCache); + writer.write("\n}"); + writer.write("\n"); + writer.close(); + } +} diff --git a/tools/processors/property_cache/src/java/android/processor/property_cache/Constants.java b/tools/processors/property_cache/src/java/android/processor/property_cache/Constants.java new file mode 100644 index 000000000000..03961bcaaba0 --- /dev/null +++ b/tools/processors/property_cache/src/java/android/processor/property_cache/Constants.java @@ -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 android.processor.property_cache; + +import com.google.common.collect.ImmutableMap; + +public final class Constants { + public static final String EMPTY_STRING = ""; + public static final String JAVA_LANG_VOID = "java.lang.Void"; + public static final ImmutableMap<String, String> PRIMITIVE_TYPE_MAP = + ImmutableMap.of( + "int", "java.lang.Integer", + "boolean", "java.lang.Boolean", + "long", "java.lang.Long", + "float", "java.lang.Float", + "double", "java.lang.Double", + "byte", "java.lang.Byte", + "short", "java.lang.Short", + "char", "java.lang.Character"); + + public static final String METHOD_COMMENT = "\n /**" + + "\n * This method is auto-generated%s" + + "\n * " + + "\n * @hide" + + "\n */"; +} diff --git a/tools/processors/property_cache/src/java/android/processor/property_cache/IpcDataCacheComposer.java b/tools/processors/property_cache/src/java/android/processor/property_cache/IpcDataCacheComposer.java new file mode 100644 index 000000000000..8526a04e9910 --- /dev/null +++ b/tools/processors/property_cache/src/java/android/processor/property_cache/IpcDataCacheComposer.java @@ -0,0 +1,152 @@ +/* + * 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.processor.property_cache; + +import java.io.IOException; +import java.io.Writer; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; + +public class IpcDataCacheComposer { + + private static final String PROPERTY_DEFINITION_LINE = "private %s%s %s;\n"; + private static final String METHOD_NAME_LINE = "\npublic %s%s %s(%s%s%s\n) {\n"; + private static final String RETURN_IF_NOT_NULL_LINE = + "if (%s != null) {\n return %s.%s;\n }"; + + private CacheConfig mCacheConfig; + + /** + * Generates code for property cache. + * + * @param writer writer to write code to. + * @param classElement class element to generate code for. + * @param method method element to generate code for. + * @throws IOException if writer throws IOException. + */ + public void generatePropertyCache(Writer writer, TypeElement classElement, + ExecutableElement method) throws IOException { + + mCacheConfig = new CacheConfig(classElement, method); + + ParamComposer inputParam = new ParamComposer(null, null); + ParamComposer binderParam = new ParamComposer( + String.format("IpcDataCache.RemoteCall<%s, %s>", mCacheConfig.getInputType(), + mCacheConfig.getResultType()), "binderCall"); + + ParamComposer bypassParam = new ParamComposer(null, null); // empty if method have no params + String queryCall = "query(null)"; + if (mCacheConfig.getNumberOfParams() > 0) { + bypassParam = new ParamComposer( + String.format("IpcDataCache.BypassCall<%s> ", mCacheConfig.getInputType()), + "bypassPredicate"); + inputParam = new ParamComposer(mCacheConfig.getInputType(), "query"); + queryCall = "query(query)"; + } + String propertyClass = + "IpcDataCache<" + mCacheConfig.getInputType() + ", " + mCacheConfig.getResultType() + + ">"; + String invalidateName = "invalidate" + mCacheConfig.getPropertyName(); + String lockObject = mCacheConfig.getPropertyVariable() + "Lock"; + writer.write("private " + mCacheConfig.getModifiers().getStaticModifier() + "final Object " + + lockObject + " = new Object();\n"); + writer.write(String.format(PROPERTY_DEFINITION_LINE, + mCacheConfig.getModifiers().getStaticModifier(), propertyClass, + mCacheConfig.getPropertyVariable())); + + writer.write(propertyInvalidatedCacheMethod(binderParam, bypassParam, inputParam, queryCall, + lockObject)); + + // If binder param is not empty then generate getter without binder param to be called + if (!bypassParam.getParam().isEmpty()) { + writer.write(propertyInvalidatedCacheMethod(binderParam, new ParamComposer(null, null), + inputParam, queryCall, lockObject)); + } + writer.write(String.format(Constants.METHOD_COMMENT, + "- invalidate cache for {@link " + mCacheConfig.getQualifiedName() + "#" + + mCacheConfig.getMethodName() + "}")); + writer.write("\n public static final void " + invalidateName + "() {"); + writer.write( + "\n IpcDataCache.invalidateCache(\"" + mCacheConfig.getModuleName() + "\", \"" + + mCacheConfig.getApiName() + "\");"); + writer.write("\n }"); + writer.write("\n"); + writer.write("\n"); + } + + /** + * Generates code to call cache invalidation. + * + * @return code string calling cache invalidation. + */ + public String generateInvalidatePropertyCall() { + String invalidateName = "invalidate" + mCacheConfig.getPropertyName(); + return mCacheConfig.getClassName() + "Cache." + invalidateName + "();"; + } + + /** + * Generates code for getter that returns cached value or calls binder and caches result. + * + * @param binderParam parameter for binder call. + * @param bypassParam parameter for bypass predicate. + * @param inputParam parameter for input value. + * @param queryCall cache query call syntax. + * @param lockObject object to synchronize on. + * @return String with code for method. + */ + private String propertyInvalidatedCacheMethod(ParamComposer binderParam, + ParamComposer bypassParam, ParamComposer inputParam, String queryCall, + String lockObject) { + String result = "\n"; + CacheModifiers modifiers = mCacheConfig.getModifiers(); + String paramsComments = binderParam.getParamComment( + "lambda for remote call" + " {@link " + mCacheConfig.getQualifiedName() + "#" + + mCacheConfig.getMethodName() + " }") + bypassParam.getParamComment( + "lambda to bypass remote call") + inputParam.getParamComment( + "parameter to call remote lambda"); + result += String.format(Constants.METHOD_COMMENT, paramsComments); + result += String.format(METHOD_NAME_LINE, modifiers.getStaticModifier(), + mCacheConfig.getResultType(), mCacheConfig.getMethodName(), + binderParam.getParam(), bypassParam.getNextParam(), + inputParam.getNextParam()); + result += String.format(RETURN_IF_NOT_NULL_LINE, mCacheConfig.getPropertyVariable(), + mCacheConfig.getPropertyVariable(), queryCall); + result += "\n synchronized (" + lockObject + " ) {"; + result += "\n if (" + mCacheConfig.getPropertyVariable() + " == null) {"; + result += "\n " + mCacheConfig.getPropertyVariable() + " = new IpcDataCache" + "(" + + generateCreateIpcConfig() + ", " + binderParam.getName() + + bypassParam.getNextName() + ");\n"; + result += "\n }"; + result += "\n }"; + result += "\n return " + mCacheConfig.getPropertyVariable() + "." + queryCall + ";"; + result += "\n }"; + result += "\n"; + return result; + } + + /** + * Generates code for new IpcDataCache.Config object for given configuration. + * + * @return String with code for new IpcDataCache.Config object. + */ + public String generateCreateIpcConfig() { + return "new IpcDataCache.Config(" + mCacheConfig.getMaxSize() + ", " + "\"" + + mCacheConfig.getModuleName() + "\"" + ", " + "\"" + mCacheConfig.getApiName() + + "\"" + ", " + "\"" + mCacheConfig.getPropertyName() + "\"" + ")"; + } +} diff --git a/tools/processors/property_cache/src/java/android/processor/property_cache/ParamComposer.java b/tools/processors/property_cache/src/java/android/processor/property_cache/ParamComposer.java new file mode 100644 index 000000000000..307443aea730 --- /dev/null +++ b/tools/processors/property_cache/src/java/android/processor/property_cache/ParamComposer.java @@ -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 android.processor.property_cache; + +public class ParamComposer { + private String mType; + private String mName; + + /** Creates ParamComposer with given type and name. + * + * @param type type of parameter. + * @param name name of parameter. + */ + public ParamComposer(String type, String name) { + mType = type; + mName = name; + } + + /** Returns name of parameter. + * + * @return name of parameter. + */ + public String getName() { + if (mName != null) { + return mName; + } + return Constants.EMPTY_STRING; + } + + /** Returns name of parameter for next parameter followed by comma. + * + * @return name of parameter for next parameter if exists, empty string otherwise. + */ + public String getNextName() { + if (!getName().isEmpty()) { + return ", " + getName(); + } + return Constants.EMPTY_STRING; + } + + /** + * Returns type of parameter. + * + * @return type of parameter. + */ + public String getType() { + if (mType != null) { + return mType; + } + return Constants.EMPTY_STRING; + } + + /** + * Returns type and name of parameter. + * + * @return type and name of parameter if exists, empty string otherwise. + */ + public String getParam() { + if (!getType().isEmpty() && !getName().isEmpty()) { + return getType() + " " + getName(); + } + return Constants.EMPTY_STRING; + } + + /** + * Returns type and name of parameter for next parameter followed by comma. + * + * @return type and name of parameter for next parameter if exists, empty string otherwise. + */ + public String getNextParam() { + if (!getType().isEmpty() && !getName().isEmpty()) { + return ", " + getParam(); + } + return Constants.EMPTY_STRING; + } + + /** + * Returns comment for parameter. + * + * @param description of parameter. + * @return comment for parameter if exists, empty string otherwise. + */ + public String getParamComment(String description) { + if (!getType().isEmpty() && !getName().isEmpty()) { + return "\n * @param " + getName() + " - " + description; + } + return Constants.EMPTY_STRING; + } +} diff --git a/tools/processors/property_cache/test/java/android/processor/property_cache/CachedPropertyProcessorTest.java b/tools/processors/property_cache/test/java/android/processor/property_cache/CachedPropertyProcessorTest.java new file mode 100644 index 000000000000..1e23c78d4816 --- /dev/null +++ b/tools/processors/property_cache/test/java/android/processor/property_cache/CachedPropertyProcessorTest.java @@ -0,0 +1,64 @@ +/* + * 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.processor.property_cache.test; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.testing.compile.CompilationSubject.assertThat; + +import android.processor.property_cache.CachedPropertyProcessor; + +import com.google.testing.compile.Compilation; +import com.google.testing.compile.Compiler; +import com.google.testing.compile.JavaFileObjects; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import javax.tools.JavaFileObject; +import javax.tools.StandardLocation; + +/** Tests the {@link CachedPropertyProcessor}. */ +@RunWith(JUnit4.class) +public class CachedPropertyProcessorTest { + private final Compiler mCompiler = + Compiler.javac().withProcessors(new CachedPropertyProcessor()); + + @Test + public void testDefaultValues() { + JavaFileObject expectedJava = JavaFileObjects.forResource("DefaultCache.java"); + + Compilation compilation = mCompiler.compile(JavaFileObjects.forResource("Default.java")); + assertThat(compilation).succeeded(); + assertThat(compilation) + .generatedFile(StandardLocation.SOURCE_OUTPUT, + "android/processor/property_cache/test/DefaultCache.java") + .hasSourceEquivalentTo(expectedJava); + } + + @Test + public void testCustomValues() { + JavaFileObject expectedJava = JavaFileObjects.forResource("CustomCache.java"); + + Compilation compilation = mCompiler.compile(JavaFileObjects.forResource("Custom.java")); + assertThat(compilation).succeeded(); + assertThat(compilation) + .generatedFile(StandardLocation.SOURCE_OUTPUT, + "android/processor/property_cache/test/CustomCache.java") + .hasSourceEquivalentTo(expectedJava); + } +} diff --git a/tools/processors/property_cache/test/java/android/processor/property_cache/shadows/IpcDataCache.java b/tools/processors/property_cache/test/java/android/processor/property_cache/shadows/IpcDataCache.java new file mode 100644 index 000000000000..e5ef48c14436 --- /dev/null +++ b/tools/processors/property_cache/test/java/android/processor/property_cache/shadows/IpcDataCache.java @@ -0,0 +1,134 @@ +/* + * 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.os; + +// Mocked class for generation compilation tests purposes only. +public class IpcDataCache<Input, Output> { + public static class Config { + public Config(int max, String module, String api, String name) { + } + } + + /** Shadow method for generated code compilation tests purposes only. + * + * @param query - shadow parameter from IpcDataCache in Frameworks. + * @return null + */ + public Output query(Input query) { + return null; + } + + /** Shadow method for generated code compilation tests purposes only. + * + * @param key - shadow parameter from IpcDataCache in Frameworks; + */ + public static void invalidateCache(String key) { + } + + /** Shadow method for generated code compilation tests purposes only. + * + * @param query - shadow parameter from IpcDataCache in Frameworks; + * @return null + */ + public Output recompute(Input query) { + return null; + } + + /** Shadow method for generated code compilation tests purposes only. + * + * @param query - parameter equivalent to IpcDataCache in android framework. + * @param query - shadow parameter from IpcDataCache in Frameworks; + * @return false + */ + public boolean bypass(Input query) { + return false; + } + + /** Shadow method for generated code compilation tests purposes only. + * + * @param module - parameter equivalent to IpcDataCache in android framework. + * @param key - parameter equivalent to IpcDataCache in android framework. + * @return module + key sttring + */ + public static String createPropertyName(String module, String key) { + return module + key; + } + + public abstract static class QueryHandler<Input, Output> { + /** Shadow method for generated code compilation tests purposes only. + * + * @param query - parameter equivalent to IpcDataCache.QueryHandler in android framework. + * @return expected value + */ + public abstract Output apply(Input query); + /** Shadow method for generated code compilation tests purposes only. + * + * @param query - parameter equivalent to IpcDataCache.QueryHandler in android framework. + */ + public boolean shouldBypassCache(Input query) { + return false; + } + } + + public interface RemoteCall<Input, Output> { + /** Shadow method for generated code compilation tests purposes only. + * + * @param query - parameter equivalent to IpcDataCache.RemoteCall in android framework. + */ + Output apply(Input query); + } + + public interface BypassCall<Input> { + /** Shadow method for generated code compilation tests purposes only. + * + * @param query - parameter equivalent to IpcDataCache.BypassCall in android framework. + */ + boolean apply(Input query); + } + + public IpcDataCache( + int maxEntries, + String module, + String api, + String cacheName, + QueryHandler<Input, Output> computer) { + } + + public IpcDataCache(Config config, QueryHandler<Input, Output> computer) { + } + + public IpcDataCache(Config config, RemoteCall<Input, Output> computer) { + } + + public IpcDataCache(Config config, RemoteCall<Input, Output> computer, + BypassCall<Input> bypassCall) { + } + + /** Shadow method for generated code compilation tests purposes only.*/ + public void invalidateCache() { + } + + + /** Shadow method for generated code compilation tests purposes only. + * + * @param module - shadow parameter from IpcDataCache in Frameworks. + * @param api - shadow parameter from IpcDataCache in Frameworks. + */ + public static void invalidateCache(String module, String api) { + } + +} diff --git a/tools/processors/property_cache/test/resources/Custom.java b/tools/processors/property_cache/test/resources/Custom.java new file mode 100644 index 000000000000..05024da67e6c --- /dev/null +++ b/tools/processors/property_cache/test/resources/Custom.java @@ -0,0 +1,127 @@ +/* + * 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.processor.property_cache.test; + +import com.android.internal.annotations.CacheModifier; +import com.android.internal.annotations.CachedProperty; +import com.android.internal.annotations.CachedPropertyDefaults; + +import java.util.Date; + +@CachedPropertyDefaults(max = 4, module = "bluetooth") +public class Custom { + BirthdayManagerService mService = new BirthdayManagerService(); + Object mCache = new CustomCache(); + + public Custom() { + CustomCache.initCache(); + } + + /** + * Testing custom class values to generate static IpcDataCache + * + * @param userId - user Id + * @return birthday date of given user Id + */ + @CachedProperty() + public Date getBirthday(int userId) { + return CustomCache.getBirthday(mService::getBirthday, userId); + } + + /** + * Testing custom class values to generate static IpcDataCache + * + * @param userId - user Id + * @return number of days till birthday of given user Id + */ + @CachedProperty(modsFlagOnOrNone = {CacheModifier.STATIC}) + public int getDaysTillBirthday(int userId) { + return CustomCache.getDaysTillBirthday(mService::getDaysTillBirthday, userId); + } + + /** + * Testing custom class values to generate non-static IpcDataCache + * + * @param userId - user Id + * @return number of days since birthday of given user Id + */ + @CachedProperty(modsFlagOnOrNone = {}) + public int getDaysSinceBirthday(int userId) { + return ((CustomCache) mCache).getDaysSinceBirthday(mService::getDaysSinceBirthday, userId); + } + + /** + * Testing custom class values to generate static IpcDataCache with max capasity of 1 + * + * @return number of days till birthay of current user + */ + @CachedProperty(modsFlagOnOrNone = {CacheModifier.STATIC}, max = 1) + public int getDaysTillMyBirthday() { + return CustomCache.getDaysTillMyBirthday((Void) -> mService.getDaysTillMyBirthday()); + } + + /** + * Testing custom class values to generate static IpcDataCache with max capasity of 1 and custom + * api + * + * @return number of days since birthay of current user + */ + @CachedProperty(modsFlagOnOrNone = {}, max = 1, api = "my_unique_key") + public int getDaysSinceMyBirthday() { + return ((CustomCache) mCache).getDaysSinceMyBirthday( + (Void) -> mService.getDaysSinceMyBirthday()); + } + + /** + * Testing custom class values to generate static IpcDataCache with custom module name + * + * @return birthday wishes of given user Id + */ + @CachedProperty(module = "telephony") + public String getBirthdayWishesFromUser(int userId) { + return CustomCache.getBirthdayWishesFromUser(mService::getBirthdayWishesFromUser, + userId); + } + + class BirthdayManagerService { + int mDaysTillBirthday = 182; + + public Date getBirthday(int userId) { + return new Date(2024, 6, 1 + userId); + } + + public int getDaysTillBirthday(int userId) { + return mDaysTillBirthday + userId; + } + + public int getDaysSinceBirthday(int userId) { + return 365 - getDaysTillBirthday(userId); + } + + public int getDaysTillMyBirthday() { + return 0; + } + + public int getDaysSinceMyBirthday() { + return 365; + } + + public String getBirthdayWishesFromUser(int userId) { + return "Happy Birthday!\n- " + userId; + } + } +} diff --git a/tools/processors/property_cache/test/resources/CustomCache.java b/tools/processors/property_cache/test/resources/CustomCache.java new file mode 100644 index 000000000000..326467fb5639 --- /dev/null +++ b/tools/processors/property_cache/test/resources/CustomCache.java @@ -0,0 +1,384 @@ +/* + * 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.processor.property_cache.test; + +import android.os.IpcDataCache; + +/** + * This class is auto-generated + * + * @hide + **/ +public class CustomCache { + private static final Object sBirthdayLock = new Object(); + private static IpcDataCache<java.lang.Integer, java.util.Date> sBirthday; + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link android.processor.property_cache.test.Custom#getBirthday } + * @param bypassPredicate - lambda to bypass remote call + * @param query - parameter to call remote lambda + * @hide + */ + public static java.util.Date getBirthday( + IpcDataCache.RemoteCall<java.lang.Integer, java.util.Date> binderCall, + IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query) { + if (sBirthday != null) { + return sBirthday.query(query); + } + synchronized (sBirthdayLock) { + if (sBirthday == null) { + sBirthday = new IpcDataCache( + new IpcDataCache.Config(4, "bluetooth", "custom_birthday", "Birthday"), + binderCall, bypassPredicate); + + } + } + return sBirthday.query(query); + } + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link android.processor.property_cache.test.Custom#getBirthday } + * @param query - parameter to call remote lambda + * @hide + */ + public static java.util.Date getBirthday( + IpcDataCache.RemoteCall<java.lang.Integer, java.util.Date> binderCall, + java.lang.Integer query) { + if (sBirthday != null) { + return sBirthday.query(query); + } + synchronized (sBirthdayLock) { + if (sBirthday == null) { + sBirthday = new IpcDataCache( + new IpcDataCache.Config(4, "bluetooth", "custom_birthday", "Birthday"), + binderCall); + } + } + return sBirthday.query(query); + } + + /** + * This method is auto-generated- invalidate cache for + * {@link android.processor.property_cache.test.Custom#getBirthday} + * + * @hide + */ + public static final void invalidateBirthday() { + IpcDataCache.invalidateCache("bluetooth", "custom_birthday"); + } + + private static final Object sDaysTillBirthdayLock = new Object(); + private static IpcDataCache<java.lang.Integer, java.lang.Integer> sDaysTillBirthday; + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link + * android.processor.property_cache.test.Custom#getDaysTillBirthday } + * @param bypassPredicate - lambda to bypass remote call + * @param query - parameter to call remote lambda + * @hide + */ + public static java.lang.Integer getDaysTillBirthday( + IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall, + IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query) { + if (sDaysTillBirthday != null) { + return sDaysTillBirthday.query(query); + } + synchronized (sDaysTillBirthdayLock) { + if (sDaysTillBirthday == null) { + sDaysTillBirthday = new IpcDataCache( + new IpcDataCache.Config(4, "bluetooth", "custom_days_till_birthday", + "DaysTillBirthday"), binderCall, bypassPredicate); + + } + } + return sDaysTillBirthday.query(query); + } + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link android.processor.property_cache.test.Custom#getDaysTillBirthday } + * @param query - parameter to call remote lambda + * @hide + */ + public static java.lang.Integer getDaysTillBirthday( + IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall, + java.lang.Integer query) { + if (sDaysTillBirthday != null) { + return sDaysTillBirthday.query(query); + } + synchronized (sDaysTillBirthdayLock) { + if (sDaysTillBirthday == null) { + sDaysTillBirthday = new IpcDataCache( + new IpcDataCache.Config(4, "bluetooth", "custom_days_till_birthday", + "DaysTillBirthday"), binderCall); + + } + } + return sDaysTillBirthday.query(query); + } + + /** + * This method is auto-generated- invalidate cache for + * {@link android.processor.property_cache.test.Custom#getDaysTillBirthday} + * + * @hide + */ + public static final void invalidateDaysTillBirthday() { + IpcDataCache.invalidateCache("bluetooth", "custom_days_till_birthday"); + } + + private final Object mDaysSinceBirthdayLock = new Object(); + private IpcDataCache<java.lang.Integer, java.lang.Integer> mDaysSinceBirthday; + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link + * android.processor.property_cache.test.Custom#getDaysSinceBirthday } + * @param bypassPredicate - lambda to bypass remote call + * @param query - parameter to call remote lambda + * @hide + */ + public java.lang.Integer getDaysSinceBirthday( + IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall, + IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query) { + if (mDaysSinceBirthday != null) { + return mDaysSinceBirthday.query(query); + } + synchronized (mDaysSinceBirthdayLock) { + if (mDaysSinceBirthday == null) { + mDaysSinceBirthday = new IpcDataCache( + new IpcDataCache.Config(4, "bluetooth", "custom_days_since_birthday", + "DaysSinceBirthday"), binderCall, bypassPredicate); + + } + } + return mDaysSinceBirthday.query(query); + } + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link android.processor.property_cache.test.Custom#getDaysSinceBirthday + * } + * @param query - parameter to call remote lambda + * @hide + */ + public java.lang.Integer getDaysSinceBirthday( + IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall, + java.lang.Integer query) { + if (mDaysSinceBirthday != null) { + return mDaysSinceBirthday.query(query); + } + synchronized (mDaysSinceBirthdayLock) { + if (mDaysSinceBirthday == null) { + mDaysSinceBirthday = new IpcDataCache( + new IpcDataCache.Config(4, "bluetooth", "custom_days_since_birthday", + "DaysSinceBirthday"), binderCall); + + } + } + return mDaysSinceBirthday.query(query); + } + + /** + * This method is auto-generated- invalidate cache for + * {@link android.processor.property_cache.test.Custom#getDaysSinceBirthday} + * + * @hide + */ + public static final void invalidateDaysSinceBirthday() { + IpcDataCache.invalidateCache("bluetooth", "custom_days_since_birthday"); + } + + private static final Object sDaysTillMyBirthdayLock = new Object(); + private static IpcDataCache<java.lang.Void, java.lang.Integer> sDaysTillMyBirthday; + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link android.processor.property_cache.test.Custom#getDaysTillMyBirthday + * } + * @hide + */ + public static java.lang.Integer getDaysTillMyBirthday( + IpcDataCache.RemoteCall<java.lang.Void, java.lang.Integer> binderCall) { + if (sDaysTillMyBirthday != null) { + return sDaysTillMyBirthday.query(null); + } + synchronized (sDaysTillMyBirthdayLock) { + if (sDaysTillMyBirthday == null) { + sDaysTillMyBirthday = new IpcDataCache( + new IpcDataCache.Config(1, "bluetooth", "custom_days_till_my_birthday", + "DaysTillMyBirthday"), binderCall); + + } + } + return sDaysTillMyBirthday.query(null); + } + + /** + * This method is auto-generated- invalidate cache for + * {@link android.processor.property_cache.test.Custom#getDaysTillMyBirthday} + * + * @hide + */ + public static final void invalidateDaysTillMyBirthday() { + IpcDataCache.invalidateCache("bluetooth", "custom_days_till_my_birthday"); + } + + private final Object mDaysSinceMyBirthdayLock = new Object(); + private IpcDataCache<java.lang.Void, java.lang.Integer> mDaysSinceMyBirthday; + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link android.processor.property_cache.test.Custom#getDaysSinceMyBirthday + * } + * @hide + */ + public java.lang.Integer getDaysSinceMyBirthday( + IpcDataCache.RemoteCall<java.lang.Void, java.lang.Integer> binderCall) { + if (mDaysSinceMyBirthday != null) { + return mDaysSinceMyBirthday.query(null); + } + synchronized (mDaysSinceMyBirthdayLock) { + if (mDaysSinceMyBirthday == null) { + mDaysSinceMyBirthday = new IpcDataCache( + new IpcDataCache.Config(1, "bluetooth", "my_unique_key", + "DaysSinceMyBirthday"), binderCall); + + } + } + return mDaysSinceMyBirthday.query(null); + } + + /** + * This method is auto-generated- invalidate cache for + * {@link android.processor.property_cache.test.Custom#getDaysSinceMyBirthday} + * + * @hide + */ + public static final void invalidateDaysSinceMyBirthday() { + IpcDataCache.invalidateCache("bluetooth", "my_unique_key"); + } + + private static final Object sBirthdayWishesFromUserLock = new Object(); + private static IpcDataCache<java.lang.Integer, java.lang.String> sBirthdayWishesFromUser; + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link + * android.processor.property_cache.test.Custom#getBirthdayWishesFromUser + * } + * @param bypassPredicate - lambda to bypass remote call + * @param query - parameter to call remote lambda + * @hide + */ + public static java.lang.String getBirthdayWishesFromUser( + IpcDataCache.RemoteCall<java.lang.Integer, java.lang.String> binderCall, + IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query) { + if (sBirthdayWishesFromUser != null) { + return sBirthdayWishesFromUser.query(query); + } + synchronized (sBirthdayWishesFromUserLock) { + if (sBirthdayWishesFromUser == null) { + sBirthdayWishesFromUser = new IpcDataCache( + new IpcDataCache.Config(4, "telephony", "custom_birthday_wishes_from_user", + "BirthdayWishesFromUser"), binderCall, bypassPredicate); + + } + } + return sBirthdayWishesFromUser.query(query); + } + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link + * android.processor.property_cache.test.Custom#getBirthdayWishesFromUser } + * @param query - parameter to call remote lambda + * @hide + */ + public static java.lang.String getBirthdayWishesFromUser( + IpcDataCache.RemoteCall<java.lang.Integer, java.lang.String> binderCall, + java.lang.Integer query) { + if (sBirthdayWishesFromUser != null) { + return sBirthdayWishesFromUser.query(query); + } + synchronized (sBirthdayWishesFromUserLock) { + if (sBirthdayWishesFromUser == null) { + sBirthdayWishesFromUser = new IpcDataCache( + new IpcDataCache.Config(4, "telephony", "custom_birthday_wishes_from_user", + "BirthdayWishesFromUser"), binderCall); + + } + } + return sBirthdayWishesFromUser.query(query); + } + + /** + * This method is auto-generated- invalidate cache for + * {@link android.processor.property_cache.test.Custom#getBirthdayWishesFromUser} + * + * @hide + */ + public static final void invalidateBirthdayWishesFromUser() { + IpcDataCache.invalidateCache("telephony", "custom_birthday_wishes_from_user"); + } + + + /** + * This method is auto-generated - initialise all caches for class CustomCache + * + * @hide + */ + public static void initCache() { + CustomCache.invalidateBirthday(); + CustomCache.invalidateDaysTillBirthday(); + CustomCache.invalidateDaysSinceBirthday(); + CustomCache.invalidateDaysTillMyBirthday(); + CustomCache.invalidateDaysSinceMyBirthday(); + CustomCache.invalidateBirthdayWishesFromUser(); + } +} diff --git a/tools/processors/property_cache/test/resources/Default.java b/tools/processors/property_cache/test/resources/Default.java new file mode 100644 index 000000000000..d2449aad656c --- /dev/null +++ b/tools/processors/property_cache/test/resources/Default.java @@ -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 android.processor.property_cache.test; + +import com.android.internal.annotations.CacheModifier; +import com.android.internal.annotations.CachedProperty; +import com.android.internal.annotations.CachedPropertyDefaults; + +import java.util.Date; + +@CachedPropertyDefaults() +public class Default { + BirthdayManagerService mService = new BirthdayManagerService(); + Object mCache = new DefaultCache(); + + /** Testing default class values to generate static IpcDataCache + * + * @param userId - user Id + * @return birthday date of given user Id + */ + @CachedProperty() + public Date getBirthday(int userId) { + return DefaultCache.getBirthday(mService::getBirthday, userId); + } + + /** Testing default class values to generate static IpcDataCache + * + * @param userId - user Id + * @return number of days till birthday of given user Id + */ + @CachedProperty(modsFlagOnOrNone = {CacheModifier.STATIC}) + public int getDaysTillBirthday(int userId) { + return DefaultCache.getDaysTillBirthday(mService::getDaysTillBirthday, userId); + } + + /** Testing generate non-static IpcDataCache + * + * @param userId - user Id + * @return number of days since birthday of given user Id + */ + @CachedProperty(modsFlagOnOrNone = {}) + public int getDaysSinceBirthday(int userId) { + return ((DefaultCache) mCache).getDaysSinceBirthday(mService::getDaysSinceBirthday, userId); + } + + /** Testing default class values to generate static IpcDataCache with max capacity of 1 + * + * @return number of days till birthay of current user + */ + @CachedProperty( + modsFlagOnOrNone = {CacheModifier.STATIC}, + max = 1) + public int getDaysTillMyBirthday() { + return DefaultCache.getDaysTillMyBirthday((Void) -> mService.getDaysTillMyBirthday()); + } + + /** Testing default class values to generate static IpcDataCache with max capacity of 1 and + custom api + * + * @return number of days since birthay of current user + */ + @CachedProperty( + modsFlagOnOrNone = {}, + max = 1, + api = "my_unique_key") + public int getDaysSinceMyBirthday() { + return ((DefaultCache) mCache).getDaysSinceMyBirthday( + (Void) -> mService.getDaysSinceMyBirthday()); + } + + /** Testing default class values to generate static IpcDataCache with custom module name + * + * @return birthday wishes of given user Id + */ + @CachedProperty(module = "telephony") + public String getBirthdayWishesFromUser(int userId) { + return DefaultCache.getBirthdayWishesFromUser(mService::getBirthdayWishesFromUser, + userId); + } + + class BirthdayManagerService { + + BirthdayManagerService() { + DefaultCache.initCache(); + } + + public Date getBirthday(int userId) { + return new Date(); + } + + public int getDaysTillBirthday(int userId) { + return 0; + } + + public int getDaysSinceBirthday(int userId) { + return 0; + } + + public int getDaysTillMyBirthday() { + return 0; + } + + public int getDaysSinceMyBirthday() { + return 0; + } + + public String getBirthdayWishesFromUser(int userId) { + return "Happy Birthday!\n- " + userId; + } + } +} diff --git a/tools/processors/property_cache/test/resources/DefaultCache.java b/tools/processors/property_cache/test/resources/DefaultCache.java new file mode 100644 index 000000000000..9531118752bb --- /dev/null +++ b/tools/processors/property_cache/test/resources/DefaultCache.java @@ -0,0 +1,402 @@ +/* + * 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.processor.property_cache.test; + +import android.os.IpcDataCache; + +/** + * This class is auto-generated + * + * @hide + **/ +public class DefaultCache { + private static final Object sBirthdayLock = new Object(); + private static IpcDataCache<java.lang.Integer, java.util.Date> sBirthday; + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link android.processor.property_cache.test.Default#getBirthday } + * @param bypassPredicate - lambda to bypass remote call + * @param query - parameter to call remote lambda + * @hide + */ + public static java.util.Date getBirthday( + IpcDataCache.RemoteCall<java.lang.Integer, java.util.Date> binderCall, + IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query + ) { + if (sBirthday != null) { + return sBirthday.query(query); + } + synchronized (sBirthdayLock) { + if (sBirthday == null) { + sBirthday = new IpcDataCache( + new IpcDataCache.Config(32, "system_server", + "default_birthday", "Birthday"), + binderCall, bypassPredicate); + + } + } + return sBirthday.query(query); + } + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link android.processor.property_cache.test.Default#getBirthday } + * @param query - parameter to call remote lambda + * @hide + */ + public static java.util.Date getBirthday( + IpcDataCache.RemoteCall<java.lang.Integer, java.util.Date> binderCall, + java.lang.Integer query + ) { + if (sBirthday != null) { + return sBirthday.query(query); + } + synchronized (sBirthdayLock) { + if (sBirthday == null) { + sBirthday = new IpcDataCache( + new IpcDataCache.Config(32, "system_server", + "default_birthday", "Birthday"), + binderCall); + + } + } + return sBirthday.query(query); + } + + /** + * This method is auto-generated- invalidate cache for + * {@link android.processor.property_cache.test.Default#getBirthday} + * + * @hide + */ + public static final void invalidateBirthday() { + IpcDataCache.invalidateCache("system_server", "default_birthday"); + } + + private static final Object sDaysTillBirthdayLock = new Object(); + private static IpcDataCache<java.lang.Integer, java.lang.Integer> sDaysTillBirthday; + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link + * android.processor.property_cache.test.Default#getDaysTillBirthday } + * @param bypassPredicate - lambda to bypass remote call + * @param query - parameter to call remote lambda + * @hide + */ + public static java.lang.Integer getDaysTillBirthday( + IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall, + IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query + ) { + if (sDaysTillBirthday != null) { + return sDaysTillBirthday.query(query); + } + synchronized (sDaysTillBirthdayLock) { + if (sDaysTillBirthday == null) { + sDaysTillBirthday = new IpcDataCache( + new IpcDataCache.Config(32, "system_server", "default_days_till_birthday", + "DaysTillBirthday"), binderCall, bypassPredicate); + + } + } + return sDaysTillBirthday.query(query); + } + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link android.processor.property_cache.test.Default#getDaysTillBirthday + * } + * @param query - parameter to call remote lambda + * @hide + */ + public static java.lang.Integer getDaysTillBirthday( + IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall, + java.lang.Integer query + ) { + if (sDaysTillBirthday != null) { + return sDaysTillBirthday.query(query); + } + synchronized (sDaysTillBirthdayLock) { + if (sDaysTillBirthday == null) { + sDaysTillBirthday = new IpcDataCache( + new IpcDataCache.Config(32, "system_server", "default_days_till_birthday", + "DaysTillBirthday"), binderCall); + + } + } + return sDaysTillBirthday.query(query); + } + + /** + * This method is auto-generated- invalidate cache for + * {@link android.processor.property_cache.test.Default#getDaysTillBirthday} + * + * @hide + */ + public static final void invalidateDaysTillBirthday() { + IpcDataCache.invalidateCache("system_server", "default_days_till_birthday"); + } + + private final Object mDaysSinceBirthdayLock = new Object(); + private IpcDataCache<java.lang.Integer, java.lang.Integer> mDaysSinceBirthday; + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link + * android.processor.property_cache.test.Default#getDaysSinceBirthday } + * @param bypassPredicate - lambda to bypass remote call + * @param query - parameter to call remote lambda + * @hide + */ + public java.lang.Integer getDaysSinceBirthday( + IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall, + IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query + ) { + if (mDaysSinceBirthday != null) { + return mDaysSinceBirthday.query(query); + } + synchronized (mDaysSinceBirthdayLock) { + if (mDaysSinceBirthday == null) { + mDaysSinceBirthday = new IpcDataCache( + new IpcDataCache.Config(32, "system_server", "default_days_since_birthday", + "DaysSinceBirthday"), binderCall, bypassPredicate); + + } + } + return mDaysSinceBirthday.query(query); + } + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link android.processor.property_cache.test.Default#getDaysSinceBirthday + * } + * @param query - parameter to call remote lambda + * @hide + */ + public java.lang.Integer getDaysSinceBirthday( + IpcDataCache.RemoteCall<java.lang.Integer, java.lang.Integer> binderCall, + java.lang.Integer query + ) { + if (mDaysSinceBirthday != null) { + return mDaysSinceBirthday.query(query); + } + synchronized (mDaysSinceBirthdayLock) { + if (mDaysSinceBirthday == null) { + mDaysSinceBirthday = new IpcDataCache( + new IpcDataCache.Config(32, "system_server", "default_days_since_birthday", + "DaysSinceBirthday"), binderCall); + + } + } + return mDaysSinceBirthday.query(query); + } + + /** + * This method is auto-generated- invalidate cache for + * {@link android.processor.property_cache.test.Default#getDaysSinceBirthday} + * + * @hide + */ + public static final void invalidateDaysSinceBirthday() { + IpcDataCache.invalidateCache("system_server", "default_days_since_birthday"); + } + + private static final Object sDaysTillMyBirthdayLock = new Object(); + private static IpcDataCache<java.lang.Void, java.lang.Integer> sDaysTillMyBirthday; + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link android.processor.property_cache.test.Default#getDaysTillMyBirthday + * } + * @hide + */ + public static java.lang.Integer getDaysTillMyBirthday( + IpcDataCache.RemoteCall<java.lang.Void, java.lang.Integer> binderCall + ) { + if (sDaysTillMyBirthday != null) { + return sDaysTillMyBirthday.query(null); + } + synchronized (sDaysTillMyBirthdayLock) { + if (sDaysTillMyBirthday == null) { + sDaysTillMyBirthday = new IpcDataCache( + new IpcDataCache.Config(1, "system_server", "default_days_till_my_birthday", + "DaysTillMyBirthday"), binderCall); + + } + } + return sDaysTillMyBirthday.query(null); + } + + /** + * This method is auto-generated- invalidate cache for + * {@link android.processor.property_cache.test.Default#getDaysTillMyBirthday} + * + * @hide + */ + public static final void invalidateDaysTillMyBirthday() { + IpcDataCache.invalidateCache("system_server", "default_days_till_my_birthday"); + } + + private final Object mDaysSinceMyBirthdayLock = new Object(); + private IpcDataCache<java.lang.Void, java.lang.Integer> mDaysSinceMyBirthday; + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link + * android.processor.property_cache.test.Default#getDaysSinceMyBirthday } + * @hide + */ + public java.lang.Integer getDaysSinceMyBirthday( + IpcDataCache.RemoteCall<java.lang.Void, java.lang.Integer> binderCall + ) { + if (mDaysSinceMyBirthday != null) { + return mDaysSinceMyBirthday.query(null); + } + synchronized (mDaysSinceMyBirthdayLock) { + if (mDaysSinceMyBirthday == null) { + mDaysSinceMyBirthday = new IpcDataCache( + new IpcDataCache.Config(1, "system_server", "my_unique_key", + "DaysSinceMyBirthday"), binderCall); + + } + } + return mDaysSinceMyBirthday.query(null); + } + + /** + * This method is auto-generated- invalidate cache for + * {@link android.processor.property_cache.test.Default#getDaysSinceMyBirthday} + * + * @hide + */ + public static final void invalidateDaysSinceMyBirthday() { + IpcDataCache.invalidateCache("system_server", "my_unique_key"); + } + + private static final Object sBirthdayWishesFromUserLock = new Object(); + private static IpcDataCache<java.lang.Integer, java.lang.String> sBirthdayWishesFromUser; + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link + * + * android.processor.property_cache.test.Default#getBirthdayWishesFromUser + * } + * @param bypassPredicate - lambda to bypass remote call + * @param query - parameter to call remote lambda + * @hide + */ + public static java.lang.String getBirthdayWishesFromUser( + IpcDataCache.RemoteCall<java.lang.Integer, java.lang.String> binderCall, + IpcDataCache.BypassCall<java.lang.Integer> bypassPredicate, java.lang.Integer query + ) { + if (sBirthdayWishesFromUser != null) { + return sBirthdayWishesFromUser.query(query); + } + synchronized (sBirthdayWishesFromUserLock) { + if (sBirthdayWishesFromUser == null) { + sBirthdayWishesFromUser = new IpcDataCache( + new IpcDataCache.Config(32, "telephony", + "default_birthday_wishes_from_user", + "BirthdayWishesFromUser"), binderCall, bypassPredicate); + + } + } + return sBirthdayWishesFromUser.query(query); + } + + + /** + * This method is auto-generated + * + * @param binderCall - lambda for remote call + * {@link + * android.processor.property_cache.test.Default#getBirthdayWishesFromUser } + * @param query - parameter to call remote lambda + * @hide + */ + public static java.lang.String getBirthdayWishesFromUser( + IpcDataCache.RemoteCall<java.lang.Integer, java.lang.String> binderCall, + java.lang.Integer query + ) { + if (sBirthdayWishesFromUser != null) { + return sBirthdayWishesFromUser.query(query); + } + synchronized (sBirthdayWishesFromUserLock) { + if (sBirthdayWishesFromUser == null) { + sBirthdayWishesFromUser = new IpcDataCache( + new IpcDataCache.Config(32, "telephony", + "default_birthday_wishes_from_user", + "BirthdayWishesFromUser"), binderCall); + + } + } + return sBirthdayWishesFromUser.query(query); + } + + /** + * This method is auto-generated- invalidate cache for + * {@link android.processor.property_cache.test.Default#getBirthdayWishesFromUser} + * + * @hide + */ + public static final void invalidateBirthdayWishesFromUser() { + IpcDataCache.invalidateCache("telephony", "default_birthday_wishes_from_user"); + } + + + /** + * This method is auto-generated - initialise all caches for class DefaultCache + * + * @hide + */ + public static void initCache() { + DefaultCache.invalidateBirthday(); + DefaultCache.invalidateDaysTillBirthday(); + DefaultCache.invalidateDaysSinceBirthday(); + DefaultCache.invalidateDaysTillMyBirthday(); + DefaultCache.invalidateDaysSinceMyBirthday(); + DefaultCache.invalidateBirthdayWishesFromUser(); + } +} |