diff options
739 files changed, 16412 insertions, 8559 deletions
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index fdf9abc49604..c2f6e3072507 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -70,8 +70,9 @@ namespace android { using ui::DisplayMode; static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip"; -static const char PRODUCT_BOOTANIMATION_DARK_FILE[] = "/product/media/bootanimation-dark.zip"; -static const char PRODUCT_BOOTANIMATION_FILE[] = "/product/media/bootanimation.zip"; +static const char PRODUCT_BOOTANIMATION_DIR[] = "/product/media/"; +static const char PRODUCT_BOOTANIMATION_DARK_FILE[] = "bootanimation-dark.zip"; +static const char PRODUCT_BOOTANIMATION_FILE[] = "bootanimation.zip"; static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip"; static const char APEX_BOOTANIMATION_FILE[] = "/apex/com.android.bootanimation/etc/bootanimation.zip"; static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip"; @@ -749,8 +750,11 @@ bool BootAnimation::findBootAnimationFileInternal(const std::vector<std::string> void BootAnimation::findBootAnimationFile() { ATRACE_CALL(); const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1; + const std::string productBootanimationFile = PRODUCT_BOOTANIMATION_DIR + + android::base::GetProperty("ro.product.bootanim.file", playDarkAnim ? + PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE); static const std::vector<std::string> bootFiles = { - APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE, + APEX_BOOTANIMATION_FILE, productBootanimationFile, OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE }; static const std::vector<std::string> shutdownFiles = { diff --git a/core/api/current.txt b/core/api/current.txt index b2539cebb7cc..5d134c6fed7b 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -16126,24 +16126,30 @@ package android.graphics { ctor public Gainmap(@NonNull android.graphics.Bitmap); ctor @FlaggedApi("com.android.graphics.hwui.flags.gainmap_constructor_with_metadata") public Gainmap(@NonNull android.graphics.Gainmap, @NonNull android.graphics.Bitmap); method public int describeContents(); + method @FlaggedApi("com.android.graphics.hwui.flags.iso_gainmap_apis") @Nullable public android.graphics.ColorSpace getAlternativeImagePrimaries(); method @NonNull public float getDisplayRatioForFullHdr(); method @NonNull public float[] getEpsilonHdr(); method @NonNull public float[] getEpsilonSdr(); method @NonNull public android.graphics.Bitmap getGainmapContents(); + method @FlaggedApi("com.android.graphics.hwui.flags.iso_gainmap_apis") public int getGainmapDirection(); method @NonNull public float[] getGamma(); method @NonNull public float getMinDisplayRatioForHdrTransition(); method @NonNull public float[] getRatioMax(); method @NonNull public float[] getRatioMin(); + method @FlaggedApi("com.android.graphics.hwui.flags.iso_gainmap_apis") public void setAlternativeImagePrimaries(@Nullable android.graphics.ColorSpace); method public void setDisplayRatioForFullHdr(@FloatRange(from=1.0f) float); method public void setEpsilonHdr(float, float, float); method public void setEpsilonSdr(float, float, float); method public void setGainmapContents(@NonNull android.graphics.Bitmap); + method @FlaggedApi("com.android.graphics.hwui.flags.iso_gainmap_apis") public void setGainmapDirection(int); method public void setGamma(float, float, float); method public void setMinDisplayRatioForHdrTransition(@FloatRange(from=1.0f) float); method public void setRatioMax(float, float, float); method public void setRatioMin(float, float, float); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.graphics.Gainmap> CREATOR; + field @FlaggedApi("com.android.graphics.hwui.flags.iso_gainmap_apis") public static final int GAINMAP_DIRECTION_HDR_TO_SDR = 1; // 0x1 + field @FlaggedApi("com.android.graphics.hwui.flags.iso_gainmap_apis") public static final int GAINMAP_DIRECTION_SDR_TO_HDR = 0; // 0x0 } public class HardwareBufferRenderer implements java.lang.AutoCloseable { @@ -19207,10 +19213,10 @@ package android.hardware.camera2 { field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> FLASH_INFO_AVAILABLE; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> FLASH_INFO_STRENGTH_DEFAULT_LEVEL; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> FLASH_INFO_STRENGTH_MAXIMUM_LEVEL; - field @FlaggedApi("com.android.internal.camera.flags.camera_manual_flash_strength_control") @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL; - field @FlaggedApi("com.android.internal.camera.flags.camera_manual_flash_strength_control") @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> FLASH_SINGLE_STRENGTH_MAX_LEVEL; - field @FlaggedApi("com.android.internal.camera.flags.camera_manual_flash_strength_control") @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> FLASH_TORCH_STRENGTH_DEFAULT_LEVEL; - field @FlaggedApi("com.android.internal.camera.flags.camera_manual_flash_strength_control") @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> FLASH_TORCH_STRENGTH_MAX_LEVEL; + field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL; + field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> FLASH_SINGLE_STRENGTH_MAX_LEVEL; + field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> FLASH_TORCH_STRENGTH_DEFAULT_LEVEL; + field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> FLASH_TORCH_STRENGTH_MAX_LEVEL; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.DeviceStateSensorOrientationMap> INFO_DEVICE_STATE_SENSOR_ORIENTATION_MAP; field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> INFO_SESSION_CONFIGURATION_QUERY_VERSION; @@ -19370,11 +19376,9 @@ package android.hardware.camera2 { method @NonNull public java.util.List<java.lang.Integer> getSupportedExtensions(); method public boolean isCaptureProcessProgressAvailable(int); method public boolean isPostviewAvailable(int); - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Float>> EFV_PADDING_ZOOM_FACTOR_RANGE; field public static final int EXTENSION_AUTOMATIC = 0; // 0x0 field @Deprecated public static final int EXTENSION_BEAUTY = 1; // 0x1 field public static final int EXTENSION_BOKEH = 2; // 0x2 - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") public static final int EXTENSION_EYES_FREE_VIDEOGRAPHY = 5; // 0x5 field public static final int EXTENSION_FACE_RETOUCH = 1; // 0x1 field public static final int EXTENSION_HDR = 3; // 0x3 field public static final int EXTENSION_NIGHT = 4; // 0x4 @@ -19800,7 +19804,7 @@ package android.hardware.camera2 { field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> EDGE_MODE; field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> EXTENSION_STRENGTH; field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> FLASH_MODE; - field @FlaggedApi("com.android.internal.camera.flags.camera_manual_flash_strength_control") @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> FLASH_STRENGTH_LEVEL; + field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> FLASH_STRENGTH_LEVEL; field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> HOT_PIXEL_MODE; field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<android.location.Location> JPEG_GPS_LOCATION; field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> JPEG_ORIENTATION; @@ -19897,7 +19901,7 @@ package android.hardware.camera2 { field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> EXTENSION_STRENGTH; field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> FLASH_MODE; field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> FLASH_STATE; - field @FlaggedApi("com.android.internal.camera.flags.camera_manual_flash_strength_control") @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> FLASH_STRENGTH_LEVEL; + field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> FLASH_STRENGTH_LEVEL; field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> HOT_PIXEL_MODE; field @NonNull public static final android.hardware.camera2.CaptureResult.Key<android.location.Location> JPEG_GPS_LOCATION; field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> JPEG_ORIENTATION; @@ -19974,30 +19978,6 @@ package android.hardware.camera2 { field public static final int MAX_THUMBNAIL_DIMENSION = 256; // 0x100 } - @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") public final class ExtensionCaptureRequest { - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Boolean> EFV_AUTO_ZOOM; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> EFV_MAX_PADDING_ZOOM_FACTOR; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> EFV_PADDING_ZOOM_FACTOR; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> EFV_ROTATE_VIEWPORT; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> EFV_STABILIZATION_MODE; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") public static final int EFV_STABILIZATION_MODE_GIMBAL = 1; // 0x1 - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") public static final int EFV_STABILIZATION_MODE_LOCKED = 2; // 0x2 - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") public static final int EFV_STABILIZATION_MODE_OFF = 0; // 0x0 - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureRequest.Key<android.util.Pair<java.lang.Integer,java.lang.Integer>> EFV_TRANSLATE_VIEWPORT; - } - - @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") public final class ExtensionCaptureResult { - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Boolean> EFV_AUTO_ZOOM; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureResult.Key<int[]> EFV_AUTO_ZOOM_PADDING_REGION; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> EFV_MAX_PADDING_ZOOM_FACTOR; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureResult.Key<int[]> EFV_PADDING_REGION; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> EFV_PADDING_ZOOM_FACTOR; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> EFV_ROTATE_VIEWPORT; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> EFV_STABILIZATION_MODE; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureResult.Key<android.graphics.PointF[]> EFV_TARGET_COORDINATES; - field @FlaggedApi("com.android.internal.camera.flags.concert_mode_api") @NonNull public static final android.hardware.camera2.CaptureResult.Key<android.util.Pair<java.lang.Integer,java.lang.Integer>> EFV_TRANSLATE_VIEWPORT; - } - public class MultiResolutionImageReader implements java.lang.AutoCloseable { ctor public MultiResolutionImageReader(@NonNull java.util.Collection<android.hardware.camera2.params.MultiResolutionStreamInfo>, int, @IntRange(from=1) int); method public void close(); @@ -33248,6 +33228,7 @@ package android.os { } public interface IBinder { + method @FlaggedApi("android.os.binder_frozen_state_change_callback") public default void addFrozenStateChangeCallback(@NonNull android.os.IBinder.FrozenStateChangeCallback) throws android.os.RemoteException; method public void dump(@NonNull java.io.FileDescriptor, @Nullable String[]) throws android.os.RemoteException; method public void dumpAsync(@NonNull java.io.FileDescriptor, @Nullable String[]) throws android.os.RemoteException; method @Nullable public String getInterfaceDescriptor() throws android.os.RemoteException; @@ -33256,6 +33237,7 @@ package android.os { method public void linkToDeath(@NonNull android.os.IBinder.DeathRecipient, int) throws android.os.RemoteException; method public boolean pingBinder(); method @Nullable public android.os.IInterface queryLocalInterface(@NonNull String); + method @FlaggedApi("android.os.binder_frozen_state_change_callback") public default boolean removeFrozenStateChangeCallback(@NonNull android.os.IBinder.FrozenStateChangeCallback); method public boolean transact(int, @NonNull android.os.Parcel, @Nullable android.os.Parcel, int) throws android.os.RemoteException; method public boolean unlinkToDeath(@NonNull android.os.IBinder.DeathRecipient, int); field public static final int DUMP_TRANSACTION = 1598311760; // 0x5f444d50 @@ -33273,6 +33255,12 @@ package android.os { method public default void binderDied(@NonNull android.os.IBinder); } + @FlaggedApi("android.os.binder_frozen_state_change_callback") public static interface IBinder.FrozenStateChangeCallback { + method public void onFrozenStateChanged(@NonNull android.os.IBinder, int); + field public static final int STATE_FROZEN = 0; // 0x0 + field public static final int STATE_UNFROZEN = 1; // 0x1 + } + public interface IInterface { method public android.os.IBinder asBinder(); } @@ -36932,13 +36920,17 @@ package android.provider { field public static final String CONTENT_DIRECTORY = "data"; } - @FlaggedApi("android.provider.new_default_account_api_enabled") public static final class ContactsContract.RawContacts.DefaultAccountAndState { - ctor public ContactsContract.RawContacts.DefaultAccountAndState(int, @Nullable android.accounts.Account); + @FlaggedApi("android.provider.new_default_account_api_enabled") public static final class ContactsContract.RawContacts.DefaultAccount { + ctor public ContactsContract.RawContacts.DefaultAccount(); + } + + @FlaggedApi("android.provider.new_default_account_api_enabled") public static final class ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState { + ctor public ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState(int, @Nullable android.accounts.Account); method @Nullable public android.accounts.Account getCloudAccount(); method public int getState(); - method @NonNull public static android.provider.ContactsContract.RawContacts.DefaultAccountAndState ofCloud(@NonNull android.accounts.Account); - method @NonNull public static android.provider.ContactsContract.RawContacts.DefaultAccountAndState ofLocal(); - method @NonNull public static android.provider.ContactsContract.RawContacts.DefaultAccountAndState ofNotSet(); + method @NonNull public static android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState ofCloud(@NonNull android.accounts.Account); + method @NonNull public static android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState ofLocal(); + method @NonNull public static android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState ofNotSet(); field public static final int DEFAULT_ACCOUNT_STATE_CLOUD = 3; // 0x3 field public static final int DEFAULT_ACCOUNT_STATE_LOCAL = 2; // 0x2 field public static final int DEFAULT_ACCOUNT_STATE_NOT_SET = 1; // 0x1 @@ -44086,7 +44078,7 @@ package android.telephony { } public static final class CarrierConfigManager.Gps { - field @FlaggedApi("android.location.flags.enable_ni_supl_message_injection_by_carrier_config") public static final String KEY_ENABLE_NI_SUPL_MESSAGE_INJECTION_BOOL = "gps.enable_ni_supl_message_injection_bool"; + field @FlaggedApi("android.location.flags.enable_ni_supl_message_injection_by_carrier_config_bugfix") public static final String KEY_ENABLE_NI_SUPL_MESSAGE_INJECTION_BOOL = "gps.enable_ni_supl_message_injection_bool"; field public static final String KEY_PERSIST_LPP_MODE_BOOL = "gps.persist_lpp_mode_bool"; field public static final String KEY_PREFIX = "gps."; } diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 24962a33244f..df45862b4d3f 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -321,7 +321,10 @@ package android.net.netstats { package android.net.wifi { public final class WifiMigration { - method @FlaggedApi("android.net.wifi.flags.legacy_keystore_to_wifi_blobstore_migration_read_only") public static void migrateLegacyKeystoreToWifiBlobstore(); + method @FlaggedApi("android.net.wifi.flags.legacy_keystore_to_wifi_blobstore_migration_read_only") public static int migrateLegacyKeystoreToWifiBlobstore(); + field @FlaggedApi("android.net.wifi.flags.legacy_keystore_to_wifi_blobstore_migration_read_only") public static final int KEYSTORE_MIGRATION_FAILURE_ENCOUNTERED_EXCEPTION = 2; // 0x2 + field @FlaggedApi("android.net.wifi.flags.legacy_keystore_to_wifi_blobstore_migration_read_only") public static final int KEYSTORE_MIGRATION_SUCCESS_MIGRATION_COMPLETE = 0; // 0x0 + field @FlaggedApi("android.net.wifi.flags.legacy_keystore_to_wifi_blobstore_migration_read_only") public static final int KEYSTORE_MIGRATION_SUCCESS_MIGRATION_NOT_NEEDED = 1; // 0x1 } } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 4350545a1b1d..5db79fe92345 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -8288,12 +8288,12 @@ public final class ActivityThread extends ClientTransactionHandler } Context c = null; ApplicationInfo ai = info.applicationInfo; - if (context.getPackageName().equals(ai.packageName)) { + if (context != null && context.getPackageName().equals(ai.packageName)) { c = context; } else if (mInitialApplication != null && mInitialApplication.getPackageName().equals(ai.packageName)) { c = mInitialApplication; - } else { + } else if (context != null) { try { c = context.createPackageContext(ai.packageName, Context.CONTEXT_INCLUDE_CODE); diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS index adeb0451cd43..cd7e40cf174d 100644 --- a/core/java/android/app/OWNERS +++ b/core/java/android/app/OWNERS @@ -112,6 +112,7 @@ per-file *VoiceInteract* = file:/core/java/android/service/voice/OWNERS # Wallpaper per-file *Wallpaper* = file:/core/java/android/service/wallpaper/OWNERS +per-file wallpaper.aconfig = file:/core/java/android/service/wallpaper/OWNERS # WindowManager per-file *Activity* = file:/services/core/java/com/android/server/wm/OWNERS diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 337939fd2388..03bec71548a8 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -1667,11 +1667,20 @@ public final class SystemServiceRegistry { @Override public WearableSensingManager createService(ContextImpl ctx) throws ServiceNotFoundException { - IBinder iBinder = ServiceManager.getServiceOrThrow( + IBinder iBinder = ServiceManager.getService( Context.WEARABLE_SENSING_SERVICE); - IWearableSensingManager manager = - IWearableSensingManager.Stub.asInterface(iBinder); - return new WearableSensingManager(ctx.getOuterContext(), manager); + if (iBinder != null) { + IWearableSensingManager manager = + IWearableSensingManager.Stub.asInterface(iBinder); + return new WearableSensingManager(ctx.getOuterContext(), manager); + } + // Wear intentionally removes the service, so do not throw a + // ServiceNotFoundException when the service is not absent. + if (ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH) + && android.server.Flags.removeWearableSensingServiceFromWear()) { + return null; + } + throw new ServiceNotFoundException(Context.WEARABLE_SENSING_SERVICE); }}); registerService(Context.ON_DEVICE_INTELLIGENCE_SERVICE, OnDeviceIntelligenceManager.class, diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig index 9891e8930936..9b06adf4e894 100644 --- a/core/java/android/app/notification.aconfig +++ b/core/java/android/app/notification.aconfig @@ -236,4 +236,12 @@ flag { namespace: "systemui" description: "Guards new android.app.richongoingnotification api" bug: "337261753" +} + +flag { + name: "ui_rich_ongoing" + is_exported: true + namespace: "systemui" + description: "Guards new android.app.richongoingnotification promotion and new uis" + bug: "337261753" }
\ No newline at end of file diff --git a/core/java/android/companion/IOnAssociationsChangedListener.aidl b/core/java/android/companion/IOnAssociationsChangedListener.aidl index d3694564ab7b..eba3804cf5b3 100644 --- a/core/java/android/companion/IOnAssociationsChangedListener.aidl +++ b/core/java/android/companion/IOnAssociationsChangedListener.aidl @@ -19,23 +19,6 @@ package android.companion; import android.companion.AssociationInfo; /** @hide */ -interface IOnAssociationsChangedListener { - - /* - * IMPORTANT: This method is intentionally NOT "oneway". - * - * The method is intentionally "blocking" to make sure that the clients of the - * addOnAssociationsChangedListener() API (@SystemAPI guarded by a "signature" permission) are - * able to prevent race conditions that may arise if their own clients (applications) - * effectively get notified about the changes before system services do. - * - * This is safe for 2 reasons: - * 1. The addOnAssociationsChangedListener() is only available to the system components - * (guarded by a "signature" permission). - * See android.permission.MANAGE_COMPANION_DEVICES. - * 2. On the Java side addOnAssociationsChangedListener() in CDM takes an Executor, and the - * proxy implementation of onAssociationsChanged() simply "post" a Runnable to it. - * See CompanionDeviceManager.OnAssociationsChangedListenerProxy class. - */ +oneway interface IOnAssociationsChangedListener { void onAssociationsChanged(in List<AssociationInfo> associations); }
\ No newline at end of file diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 52c84dc0ac5d..26f919f99ee9 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -778,8 +778,18 @@ public class LauncherApps { public List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) { logErrorForInvalidProfileAccess(user); try { - return convertToActivityList(mService.getLauncherActivities(mContext.getPackageName(), - packageName, user), user); + final List<LauncherActivityInfo> activityList = convertToActivityList( + mService.getLauncherActivities( + mContext.getPackageName(), + packageName, + user + ), user); + if (activityList.isEmpty()) { + // b/350144057 + Log.d(TAG, "getActivityList: No launchable activities found for" + + "packageName=" + packageName + ", user=" + user); + } + return activityList; } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig index 9eec7a4e8f71..34f3b61a8a88 100644 --- a/core/java/android/content/pm/multiuser.aconfig +++ b/core/java/android/content/pm/multiuser.aconfig @@ -241,6 +241,16 @@ flag { is_fixed_read_only: true } +flag { + name: "caches_not_invalidated_at_start_read_only" + namespace: "multiuser" + description: "PIC need to be invalidated at start in order to work properly." + bug: "356167673" + metadata { + purpose: PURPOSE_BUGFIX + } + is_fixed_read_only: true +} # This flag guards the private space feature and all its implementations excluding the APIs. APIs are guarded by android.os.Flags.allow_private_profile. flag { diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 7a8a16f4b98a..37983df75f2b 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -1484,7 +1484,6 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri */ @PublicKey @NonNull - @FlaggedApi(Flags.FLAG_CAMERA_MANUAL_FLASH_STRENGTH_CONTROL) public static final Key<Integer> FLASH_SINGLE_STRENGTH_MAX_LEVEL = new Key<Integer>("android.flash.singleStrengthMaxLevel", int.class); @@ -1500,7 +1499,6 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri */ @PublicKey @NonNull - @FlaggedApi(Flags.FLAG_CAMERA_MANUAL_FLASH_STRENGTH_CONTROL) public static final Key<Integer> FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL = new Key<Integer>("android.flash.singleStrengthDefaultLevel", int.class); @@ -1524,7 +1522,6 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri */ @PublicKey @NonNull - @FlaggedApi(Flags.FLAG_CAMERA_MANUAL_FLASH_STRENGTH_CONTROL) public static final Key<Integer> FLASH_TORCH_STRENGTH_MAX_LEVEL = new Key<Integer>("android.flash.torchStrengthMaxLevel", int.class); @@ -1540,7 +1537,6 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri */ @PublicKey @NonNull - @FlaggedApi(Flags.FLAG_CAMERA_MANUAL_FLASH_STRENGTH_CONTROL) public static final Key<Integer> FLASH_TORCH_STRENGTH_DEFAULT_LEVEL = new Key<Integer>("android.flash.torchStrengthDefaultLevel", int.class); @@ -5976,28 +5972,6 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri public static final Key<android.hardware.camera2.params.StreamConfigurationDuration[]> JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS_MAXIMUM_RESOLUTION = new Key<android.hardware.camera2.params.StreamConfigurationDuration[]>("android.jpegr.availableJpegRStallDurationsMaximumResolution", android.hardware.camera2.params.StreamConfigurationDuration[].class); - /** - * <p>Minimum and maximum padding zoom factors supported by this camera device for - * android.efv.paddingZoomFactor used for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension.</p> - * <p>The minimum and maximum padding zoom factors supported by the device for - * android.efv.paddingZoomFactor used as part of the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension feature. This extension specific camera characteristic can be queried using - * {@link android.hardware.camera2.CameraExtensionCharacteristics#get }.</p> - * <p><b>Units</b>: A pair of padding zoom factors in floating-points: - * (minPaddingZoomFactor, maxPaddingZoomFactor)</p> - * <p><b>Range of valid values:</b><br></p> - * <p>1.0 < minPaddingZoomFactor <= maxPaddingZoomFactor</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<android.util.Range<Float>> EFV_PADDING_ZOOM_FACTOR_RANGE = - new Key<android.util.Range<Float>>("android.efv.paddingZoomFactorRange", new TypeReference<android.util.Range<Float>>() {{ }}); - /** * Mapping from INFO_SESSION_CONFIGURATION_QUERY_VERSION to session characteristics key. diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java index 04a810a89f47..9b87df9ad3a4 100644 --- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java @@ -141,12 +141,6 @@ public final class CameraExtensionCharacteristics { public static final int EXTENSION_NIGHT = 4; /** - * An extension that aims to lock and stabilize a given region or object of interest. - */ - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final int EXTENSION_EYES_FREE_VIDEOGRAPHY = 5; - - /** * @hide */ @Retention(RetentionPolicy.SOURCE) @@ -154,8 +148,7 @@ public final class CameraExtensionCharacteristics { EXTENSION_FACE_RETOUCH, EXTENSION_BOKEH, EXTENSION_HDR, - EXTENSION_NIGHT, - EXTENSION_EYES_FREE_VIDEOGRAPHY}) + EXTENSION_NIGHT}) public @interface Extension { } @@ -634,9 +627,6 @@ public final class CameraExtensionCharacteristics { public ExtensionConnectionManager() { IntArray extensionList = new IntArray(EXTENSION_LIST.length); extensionList.addAll(EXTENSION_LIST); - if (Flags.concertModeApi()) { - extensionList.add(EXTENSION_EYES_FREE_VIDEOGRAPHY); - } for (int extensionType : extensionList.toArray()) { mConnections.put(extensionType, new ExtensionConnection()); @@ -837,9 +827,6 @@ public final class CameraExtensionCharacteristics { IntArray extensionList = new IntArray(EXTENSION_LIST.length); extensionList.addAll(EXTENSION_LIST); - if (Flags.concertModeApi()) { - extensionList.add(EXTENSION_EYES_FREE_VIDEOGRAPHY); - } for (int extensionType : extensionList.toArray()) { try { @@ -1598,28 +1585,4 @@ public final class CameraExtensionCharacteristics { return Collections.unmodifiableSet(ret); } - - - /** - * <p>Minimum and maximum padding zoom factors supported by this camera device for - * {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } used for - * the {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension.</p> - * <p>The minimum and maximum padding zoom factors supported by the device for - * {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } used as part of the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension feature. This extension specific camera characteristic can be queried using - * {@link android.hardware.camera2.CameraExtensionCharacteristics#get}.</p> - * <p><b>Units</b>: A pair of padding zoom factors in floating-points: - * (minPaddingZoomFactor, maxPaddingZoomFactor)</p> - * <p><b>Range of valid values:</b><br></p> - * <p>1.0 < minPaddingZoomFactor <= maxPaddingZoomFactor</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<android.util.Range<Float>> EFV_PADDING_ZOOM_FACTOR_RANGE = - CameraCharacteristics.EFV_PADDING_ZOOM_FACTOR_RANGE; } diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index 4819f67cb566..a69a37133192 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -3897,36 +3897,6 @@ public abstract class CameraMetadata<TKey> { public static final int DISTORTION_CORRECTION_MODE_HIGH_QUALITY = 2; // - // Enumeration values for CaptureRequest#EFV_STABILIZATION_MODE - // - - /** - * <p>No stabilization.</p> - * @see CaptureRequest#EFV_STABILIZATION_MODE - * @hide - */ - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final int EFV_STABILIZATION_MODE_OFF = 0; - - /** - * <p>Gimbal stabilization mode.</p> - * @see CaptureRequest#EFV_STABILIZATION_MODE - * @hide - */ - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final int EFV_STABILIZATION_MODE_GIMBAL = 1; - - /** - * <p>Locked stabilization mode which uses the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * stabilization to directionally steady the target region.</p> - * @see CaptureRequest#EFV_STABILIZATION_MODE - * @hide - */ - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final int EFV_STABILIZATION_MODE_LOCKED = 2; - - // // Enumeration values for CaptureResult#CONTROL_AE_STATE // diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 3b69aa742b85..3f5ae9196577 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -2730,7 +2730,6 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> */ @PublicKey @NonNull - @FlaggedApi(Flags.FLAG_CAMERA_MANUAL_FLASH_STRENGTH_CONTROL) public static final Key<Integer> FLASH_STRENGTH_LEVEL = new Key<Integer>("android.flash.strengthLevel", int.class); @@ -4325,146 +4324,6 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> public static final Key<Integer> EXTENSION_STRENGTH = new Key<Integer>("android.extension.strength", int.class); - /** - * <p>Used to apply an additional digital zoom factor for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>For the {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * feature, an additional zoom factor is applied on top of the existing {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}. - * This additional zoom factor serves as a buffer to provide more flexibility for the - * {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } - * mode. If android.efv.paddingZoomFactor is not set, the default will be used. - * The effectiveness of the stabilization may be influenced by the amount of padding zoom - * applied. A higher padding zoom factor can stabilize the target region more effectively - * with greater flexibility but may potentially impact image quality. Conversely, a lower - * padding zoom factor may be used to prioritize preserving image quality, albeit with less - * leeway in stabilizing the target region. It is recommended to set the - * android.efv.paddingZoomFactor to at least 1.5.</p> - * <p>If android.efv.autoZoom is enabled, the requested android.efv.paddingZoomFactor will be overridden. - * android.efv.maxPaddingZoomFactor can be checked for more details on controlling the - * padding zoom factor during android.efv.autoZoom.</p> - * <p><b>Range of valid values:</b><br> - * android.efv.paddingZoomFactorRange</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see CaptureRequest#CONTROL_ZOOM_RATIO - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Float> EFV_PADDING_ZOOM_FACTOR = - new Key<Float>("android.efv.paddingZoomFactor", float.class); - - /** - * <p>Used to enable or disable auto zoom for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>Turn on auto zoom to let the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * feature decide at any given point a combination of - * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} and android.efv.paddingZoomFactor - * to keep the target region in view and stabilized. The combination chosen by the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * will equal the requested {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} multiplied with the requested - * android.efv.paddingZoomFactor. A limit can be set on the padding zoom if wanting - * to control image quality further using android.efv.maxPaddingZoomFactor.</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see CaptureRequest#CONTROL_ZOOM_RATIO - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Boolean> EFV_AUTO_ZOOM = - new Key<Boolean>("android.efv.autoZoom", boolean.class); - - /** - * <p>Used to limit the android.efv.paddingZoomFactor if - * android.efv.autoZoom is enabled for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>If android.efv.autoZoom is enabled, this key can be used to set a limit - * on the android.efv.paddingZoomFactor chosen by the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode - * to control image quality.</p> - * <p><b>Range of valid values:</b><br> - * The range of android.efv.paddingZoomFactorRange. Use a value greater than or equal to - * the android.efv.paddingZoomFactor to effectively utilize this key.</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Float> EFV_MAX_PADDING_ZOOM_FACTOR = - new Key<Float>("android.efv.maxPaddingZoomFactor", float.class); - - /** - * <p>Set the stabilization mode for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension</p> - * <p>The desired stabilization mode. Gimbal stabilization mode provides simple, non-locked - * video stabilization. Locked mode uses the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * stabilization feature to fixate on the current region, utilizing it as the target area for - * stabilization.</p> - * <p><b>Possible values:</b></p> - * <ul> - * <li>{@link #EFV_STABILIZATION_MODE_OFF OFF}</li> - * <li>{@link #EFV_STABILIZATION_MODE_GIMBAL GIMBAL}</li> - * <li>{@link #EFV_STABILIZATION_MODE_LOCKED LOCKED}</li> - * </ul> - * - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @see #EFV_STABILIZATION_MODE_OFF - * @see #EFV_STABILIZATION_MODE_GIMBAL - * @see #EFV_STABILIZATION_MODE_LOCKED - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Integer> EFV_STABILIZATION_MODE = - new Key<Integer>("android.efv.stabilizationMode", int.class); - - /** - * <p>Used to update the target region for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>A android.util.Pair<Integer,Integer> that represents the desired - * <Horizontal,Vertical> shift of the current locked view (or target region) in - * pixels. Negative values indicate left and upward shifts, while positive values indicate - * right and downward shifts in the active array coordinate system.</p> - * <p><b>Range of valid values:</b><br> - * android.util.Pair<Integer,Integer> represents the - * <Horizontal,Vertical> shift. The range for the horizontal shift is - * [-max(android.efv.paddingRegion-left), max(android.efv.paddingRegion-right)]. - * The range for the vertical shift is - * [-max(android.efv.paddingRegion-top), max(android.efv.paddingRegion-bottom)]</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<android.util.Pair<Integer,Integer>> EFV_TRANSLATE_VIEWPORT = - new Key<android.util.Pair<Integer,Integer>>("android.efv.translateViewport", new TypeReference<android.util.Pair<Integer,Integer>>() {{ }}); - - /** - * <p>Representing the desired clockwise rotation - * of the target region in degrees for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>Value representing the desired clockwise rotation of the target - * region in degrees.</p> - * <p><b>Range of valid values:</b><br> - * 0 to 360</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Float> EFV_ROTATE_VIEWPORT = - new Key<Float>("android.efv.rotateViewport", float.class); - /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ * End generated code *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/ diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 34ce92c0f498..75d617c89522 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -3022,7 +3022,6 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { */ @PublicKey @NonNull - @FlaggedApi(Flags.FLAG_CAMERA_MANUAL_FLASH_STRENGTH_CONTROL) public static final Key<Integer> FLASH_STRENGTH_LEVEL = new Key<Integer>("android.flash.strengthLevel", int.class); @@ -5940,214 +5939,6 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { public static final Key<Integer> EXTENSION_STRENGTH = new Key<Integer>("android.extension.strength", int.class); - /** - * <p>The padding region for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>An array [left, top, right, bottom] of the padding in pixels remaining on all four sides - * before the target region starts to go out of bounds.</p> - * <p>The padding region denotes the area surrounding the stabilized target region within which - * the camera can be moved while maintaining the target region in view. As the camera moves, - * the padding region adjusts to represent the proximity of the target region to the - * boundary, which is the point at which the target region will start to go out of bounds.</p> - * <p><b>Range of valid values:</b><br> - * The padding is the number of remaining pixels of padding in each direction. - * The pixels reference the active array coordinate system. Negative values indicate the target - * region is out of bounds. The value for this key may be null for when the stabilization mode is - * in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_OFF } - * or {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_GIMBAL } mode.</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<int[]> EFV_PADDING_REGION = - new Key<int[]>("android.efv.paddingRegion", int[].class); - - /** - * <p>The padding region when android.efv.autoZoom is enabled for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>An array [left, top, right, bottom] of the padding in pixels remaining on all four sides - * before the target region starts to go out of bounds.</p> - * <p>This may differ from android.efv.paddingRegion as the field of view can change - * during android.efv.autoZoom, altering the boundary region and thus updating the padding between the - * target region and the boundary.</p> - * <p><b>Range of valid values:</b><br> - * The padding is the number of remaining pixels of padding in each direction - * when android.efv.autoZoom is enabled. Negative values indicate the target region is out of bounds. - * The value for this key may be null for when the android.efv.autoZoom is not enabled.</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<int[]> EFV_AUTO_ZOOM_PADDING_REGION = - new Key<int[]>("android.efv.autoZoomPaddingRegion", int[].class); - - /** - * <p>List of coordinates representing the target region relative to the - * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE } - * for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in - * {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>A list of android.graphics.PointF that define the coordinates of the target region - * relative to the - * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE }. - * The array represents the target region coordinates as: top-left, top-right, bottom-left, - * bottom-right.</p> - * <p><b>Range of valid values:</b><br> - * The list of target coordinates will define a region within the bounds of the - * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE }</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<android.graphics.PointF[]> EFV_TARGET_COORDINATES = - new Key<android.graphics.PointF[]>("android.efv.targetCoordinates", android.graphics.PointF[].class); - - /** - * <p>Used to apply an additional digital zoom factor for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>For the {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * feature, an additional zoom factor is applied on top of the existing {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}. - * This additional zoom factor serves as a buffer to provide more flexibility for the - * {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } - * mode. If android.efv.paddingZoomFactor is not set, the default will be used. - * The effectiveness of the stabilization may be influenced by the amount of padding zoom - * applied. A higher padding zoom factor can stabilize the target region more effectively - * with greater flexibility but may potentially impact image quality. Conversely, a lower - * padding zoom factor may be used to prioritize preserving image quality, albeit with less - * leeway in stabilizing the target region. It is recommended to set the - * android.efv.paddingZoomFactor to at least 1.5.</p> - * <p>If android.efv.autoZoom is enabled, the requested android.efv.paddingZoomFactor will be overridden. - * android.efv.maxPaddingZoomFactor can be checked for more details on controlling the - * padding zoom factor during android.efv.autoZoom.</p> - * <p><b>Range of valid values:</b><br> - * android.efv.paddingZoomFactorRange</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see CaptureRequest#CONTROL_ZOOM_RATIO - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Float> EFV_PADDING_ZOOM_FACTOR = - new Key<Float>("android.efv.paddingZoomFactor", float.class); - - /** - * <p>Set the stabilization mode for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension</p> - * <p>The desired stabilization mode. Gimbal stabilization mode provides simple, non-locked - * video stabilization. Locked mode uses the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * stabilization feature to fixate on the current region, utilizing it as the target area for - * stabilization.</p> - * <p><b>Possible values:</b></p> - * <ul> - * <li>{@link #EFV_STABILIZATION_MODE_OFF OFF}</li> - * <li>{@link #EFV_STABILIZATION_MODE_GIMBAL GIMBAL}</li> - * <li>{@link #EFV_STABILIZATION_MODE_LOCKED LOCKED}</li> - * </ul> - * - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @see #EFV_STABILIZATION_MODE_OFF - * @see #EFV_STABILIZATION_MODE_GIMBAL - * @see #EFV_STABILIZATION_MODE_LOCKED - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Integer> EFV_STABILIZATION_MODE = - new Key<Integer>("android.efv.stabilizationMode", int.class); - - /** - * <p>Used to enable or disable auto zoom for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>Turn on auto zoom to let the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * feature decide at any given point a combination of - * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} and android.efv.paddingZoomFactor - * to keep the target region in view and stabilized. The combination chosen by the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * will equal the requested {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} multiplied with the requested - * android.efv.paddingZoomFactor. A limit can be set on the padding zoom if wanting - * to control image quality further using android.efv.maxPaddingZoomFactor.</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see CaptureRequest#CONTROL_ZOOM_RATIO - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Boolean> EFV_AUTO_ZOOM = - new Key<Boolean>("android.efv.autoZoom", boolean.class); - - /** - * <p>Representing the desired clockwise rotation - * of the target region in degrees for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>Value representing the desired clockwise rotation of the target - * region in degrees.</p> - * <p><b>Range of valid values:</b><br> - * 0 to 360</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Float> EFV_ROTATE_VIEWPORT = - new Key<Float>("android.efv.rotateViewport", float.class); - - /** - * <p>Used to update the target region for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>A android.util.Pair<Integer,Integer> that represents the desired - * <Horizontal,Vertical> shift of the current locked view (or target region) in - * pixels. Negative values indicate left and upward shifts, while positive values indicate - * right and downward shifts in the active array coordinate system.</p> - * <p><b>Range of valid values:</b><br> - * android.util.Pair<Integer,Integer> represents the - * <Horizontal,Vertical> shift. The range for the horizontal shift is - * [-max(android.efv.paddingRegion-left), max(android.efv.paddingRegion-right)]. - * The range for the vertical shift is - * [-max(android.efv.paddingRegion-top), max(android.efv.paddingRegion-bottom)]</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<android.util.Pair<Integer,Integer>> EFV_TRANSLATE_VIEWPORT = - new Key<android.util.Pair<Integer,Integer>>("android.efv.translateViewport", new TypeReference<android.util.Pair<Integer,Integer>>() {{ }}); - - /** - * <p>Used to limit the android.efv.paddingZoomFactor if - * android.efv.autoZoom is enabled for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>If android.efv.autoZoom is enabled, this key can be used to set a limit - * on the android.efv.paddingZoomFactor chosen by the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.CameraMetadata#EFV_STABILIZATION_MODE_LOCKED } mode - * to control image quality.</p> - * <p><b>Range of valid values:</b><br> - * The range of android.efv.paddingZoomFactorRange. Use a value greater than or equal to - * the android.efv.paddingZoomFactor to effectively utilize this key.</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @hide - */ - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Float> EFV_MAX_PADDING_ZOOM_FACTOR = - new Key<Float>("android.efv.maxPaddingZoomFactor", float.class); - /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~ * End generated code *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/ diff --git a/core/java/android/hardware/camera2/ExtensionCaptureRequest.java b/core/java/android/hardware/camera2/ExtensionCaptureRequest.java deleted file mode 100644 index b681ce40dfd9..000000000000 --- a/core/java/android/hardware/camera2/ExtensionCaptureRequest.java +++ /dev/null @@ -1,229 +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 android.hardware.camera2; - -import android.annotation.FlaggedApi; -import android.annotation.NonNull; -import android.hardware.camera2.CaptureRequest; -import android.hardware.camera2.CaptureRequest.Key; -import android.hardware.camera2.impl.ExtensionKey; -import android.hardware.camera2.impl.PublicKey; - -import com.android.internal.camera.flags.Flags; - -/** - * ExtensionCaptureRequest contains definitions for extension-specific CaptureRequest keys that - * can be used to configure a {@link android.hardware.camera2.CaptureRequest} during a - * {@link android.hardware.camera2.CameraExtensionSession}. - * - * Note that ExtensionCaptureRequest is not intended to be used as a replacement - * for CaptureRequest in the extensions. It serves as a supplementary class providing - * extension-specific CaptureRequest keys. Developers should use these keys in conjunction - * with regular CaptureRequest objects during a - * {@link android.hardware.camera2.CameraExtensionSession}. - * - * @see CaptureRequest - * @see CameraExtensionSession - */ -@FlaggedApi(Flags.FLAG_CONCERT_MODE_API) -public final class ExtensionCaptureRequest { - - /** To avoid exposing constructor */ - private ExtensionCaptureRequest() {} - - /** - * <p>Used to apply an additional digital zoom factor for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>For the {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * feature, an additional zoom factor is applied on top of the existing {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}. - * This additional zoom factor serves as a buffer to provide more flexibility for the - * {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } - * mode. If {@link ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } is not set, the default will be used. - * The effectiveness of the stabilization may be influenced by the amount of padding zoom - * applied. A higher padding zoom factor can stabilize the target region more effectively - * with greater flexibility but may potentially impact image quality. Conversely, a lower - * padding zoom factor may be used to prioritize preserving image quality, albeit with less - * leeway in stabilizing the target region. It is recommended to set the - * {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } to at least 1.5.</p> - * <p>If {@link ExtensionCaptureRequest#EFV_AUTO_ZOOM } is enabled, the requested {@link ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } will be overridden. - * {@link ExtensionCaptureRequest#EFV_MAX_PADDING_ZOOM_FACTOR } can be checked for more details on controlling the - * padding zoom factor during {@link ExtensionCaptureRequest#EFV_AUTO_ZOOM }.</p> - * <p><b>Range of valid values:</b><br> - * {@link CameraExtensionCharacteristics#EFV_PADDING_ZOOM_FACTOR_RANGE }</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see CaptureRequest#CONTROL_ZOOM_RATIO - * @see ExtensionCaptureRequest#EFV_AUTO_ZOOM - * @see ExtensionCaptureRequest#EFV_MAX_PADDING_ZOOM_FACTOR - * @see ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR - * @see CameraExtensionCharacteristics#EFV_PADDING_ZOOM_FACTOR_RANGE - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Float> EFV_PADDING_ZOOM_FACTOR = CaptureRequest.EFV_PADDING_ZOOM_FACTOR; - - /** - * <p>Used to enable or disable auto zoom for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>Turn on auto zoom to let the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * feature decide at any given point a combination of - * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} and {@link ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } - * to keep the target region in view and stabilized. The combination chosen by the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * will equal the requested {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} multiplied with the requested - * {@link ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR }. A limit can be set on the padding zoom if wanting - * to control image quality further using {@link ExtensionCaptureRequest#EFV_MAX_PADDING_ZOOM_FACTOR }.</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see CaptureRequest#CONTROL_ZOOM_RATIO - * @see ExtensionCaptureRequest#EFV_MAX_PADDING_ZOOM_FACTOR - * @see ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Boolean> EFV_AUTO_ZOOM = CaptureRequest.EFV_AUTO_ZOOM; - - /** - * <p>Used to limit the {@link ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } if - * {@link ExtensionCaptureRequest#EFV_AUTO_ZOOM } is enabled for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>If {@link ExtensionCaptureRequest#EFV_AUTO_ZOOM } is enabled, this key can be used to set a limit - * on the {@link ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } chosen by the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode - * to control image quality.</p> - * <p><b>Range of valid values:</b><br> - * The range of {@link CameraExtensionCharacteristics#EFV_PADDING_ZOOM_FACTOR_RANGE Range}. Use a value greater than or equal to - * the {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } to - * effectively utilize this key.</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see ExtensionCaptureRequest#EFV_AUTO_ZOOM - * @see ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR - * @see CameraExtensionCharacteristics#EFV_PADDING_ZOOM_FACTOR_RANGE - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Float> EFV_MAX_PADDING_ZOOM_FACTOR = CaptureRequest.EFV_MAX_PADDING_ZOOM_FACTOR; - - /** - * <p>Set the stabilization mode for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension</p> - * <p>The desired stabilization mode. Gimbal stabilization mode provides simple, non-locked - * video stabilization. Locked mode uses the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * stabilization feature to fixate on the current region, utilizing it as the target area for - * stabilization.</p> - * <p><b>Possible values:</b></p> - * <ul> - * <li>{@link #EFV_STABILIZATION_MODE_OFF OFF}</li> - * <li>{@link #EFV_STABILIZATION_MODE_GIMBAL GIMBAL}</li> - * <li>{@link #EFV_STABILIZATION_MODE_LOCKED LOCKED}</li> - * </ul> - * - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @see #EFV_STABILIZATION_MODE_OFF - * @see #EFV_STABILIZATION_MODE_GIMBAL - * @see #EFV_STABILIZATION_MODE_LOCKED - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Integer> EFV_STABILIZATION_MODE = CaptureRequest.EFV_STABILIZATION_MODE; - - /** - * <p>Used to update the target region for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>A android.util.Pair<Integer,Integer> that represents the desired - * <Horizontal,Vertical> shift of the current locked view (or target region) in - * pixels. Negative values indicate left and upward shifts, while positive values indicate - * right and downward shifts in the active array coordinate system.</p> - * <p><b>Range of valid values:</b><br> - * android.util.Pair<Integer,Integer> represents the - * <Horizontal,Vertical> shift. The range for the horizontal shift is - * [-max({@link ExtensionCaptureResult#EFV_PADDING_REGION }-left), max({@link ExtensionCaptureResult#EFV_PADDING_REGION }-right)]. - * The range for the vertical shift is - * [-max({@link ExtensionCaptureResult#EFV_PADDING_REGION }-top), max({@link ExtensionCaptureResult#EFV_PADDING_REGION }-bottom)]</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see ExtensionCaptureResult#EFV_PADDING_REGION - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<android.util.Pair<Integer,Integer>> EFV_TRANSLATE_VIEWPORT = CaptureRequest.EFV_TRANSLATE_VIEWPORT; - - /** - * <p>Representing the desired clockwise rotation - * of the target region in degrees for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>Value representing the desired clockwise rotation of the target - * region in degrees.</p> - * <p><b>Range of valid values:</b><br> - * 0 to 360</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Float> EFV_ROTATE_VIEWPORT = CaptureRequest.EFV_ROTATE_VIEWPORT; - - - // - // Enumeration values for CaptureRequest#EFV_STABILIZATION_MODE - // - - /** - * <p>No stabilization.</p> - * @see ExtensionCaptureRequest#EFV_STABILIZATION_MODE - */ - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final int EFV_STABILIZATION_MODE_OFF = CaptureRequest.EFV_STABILIZATION_MODE_OFF; - - /** - * <p>Gimbal stabilization mode.</p> - * @see ExtensionCaptureRequest#EFV_STABILIZATION_MODE - */ - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final int EFV_STABILIZATION_MODE_GIMBAL = CaptureRequest.EFV_STABILIZATION_MODE_GIMBAL; - - /** - * <p>Locked stabilization mode which uses the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * stabilization to directionally steady the target region.</p> - * @see ExtensionCaptureRequest#EFV_STABILIZATION_MODE - */ - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final int EFV_STABILIZATION_MODE_LOCKED = CaptureRequest.EFV_STABILIZATION_MODE_LOCKED; - -} diff --git a/core/java/android/hardware/camera2/ExtensionCaptureResult.java b/core/java/android/hardware/camera2/ExtensionCaptureResult.java deleted file mode 100644 index b7ba78cb34b5..000000000000 --- a/core/java/android/hardware/camera2/ExtensionCaptureResult.java +++ /dev/null @@ -1,274 +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 android.hardware.camera2; - -import android.annotation.FlaggedApi; -import android.annotation.NonNull; -import android.hardware.camera2.CameraExtensionCharacteristics; -import android.hardware.camera2.CaptureResult; -import android.hardware.camera2.CaptureResult.Key; -import android.hardware.camera2.impl.ExtensionKey; -import android.hardware.camera2.impl.PublicKey; - -import com.android.internal.camera.flags.Flags; - -/** - * ExtensionCaptureResult contains definitions for extension-specific CaptureResult keys that - * are available during a {@link android.hardware.camera2.CameraExtensionSession} after a - * {@link android.hardware.camera2.CaptureRequest} is processed. - * - * Note that ExtensionCaptureResult is not intended to be used as a replacement - * for CaptureResult in the extensions. It serves as a supplementary class providing - * extension-specific CaptureResult keys. Developers should use these keys in conjunction - * with regular CaptureResult objects during a - * {@link android.hardware.camera2.CameraExtensionSession}. - * - * @see CaptureResult - * @see CaptureRequest - * @see CameraExtensionSession - */ -@FlaggedApi(Flags.FLAG_CONCERT_MODE_API) -public final class ExtensionCaptureResult { - - /** To avoid exposing constructor */ - private ExtensionCaptureResult() {} - - /** - * <p>The padding region for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>An array [left, top, right, bottom] of the padding in pixels remaining on all four sides - * before the target region starts to go out of bounds.</p> - * <p>The padding region denotes the area surrounding the stabilized target region within which - * the camera can be moved while maintaining the target region in view. As the camera moves, - * the padding region adjusts to represent the proximity of the target region to the - * boundary, which is the point at which the target region will start to go out of bounds.</p> - * <p><b>Range of valid values:</b><br> - * The padding is the number of remaining pixels of padding in each direction. - * The pixels reference the active array coordinate system. Negative values indicate the target region - * is out of bounds. The value for this key may be null for when the stabilization mode is - * in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_OFF } - * or {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_GIMBAL } mode.</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<int[]> EFV_PADDING_REGION = CaptureResult.EFV_PADDING_REGION; - - /** - * <p>The padding region when {@link ExtensionCaptureRequest#EFV_AUTO_ZOOM } is enabled for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>An array [left, top, right, bottom] of the padding in pixels remaining on all four sides - * before the target region starts to go out of bounds.</p> - * <p>This may differ from {@link ExtensionCaptureResult#EFV_PADDING_REGION } as the field of view can change - * during {@link ExtensionCaptureRequest#EFV_AUTO_ZOOM }, altering the boundary region and thus updating the padding between the - * target region and the boundary.</p> - * <p><b>Range of valid values:</b><br> - * The padding is the number of remaining pixels of padding in each direction - * when {@link ExtensionCaptureRequest#EFV_AUTO_ZOOM } is enabled. Negative values indicate the target region is out of bounds. - * The value for this key may be null for when the {@link ExtensionCaptureRequest#EFV_AUTO_ZOOM } is not enabled.</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see ExtensionCaptureRequest#EFV_AUTO_ZOOM - * @see ExtensionCaptureResult#EFV_PADDING_REGION - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<int[]> EFV_AUTO_ZOOM_PADDING_REGION = CaptureResult.EFV_AUTO_ZOOM_PADDING_REGION; - - /** - * <p>List of coordinates representing the target region relative to the - * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE } - * for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in - * {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>A list of android.graphics.PointF that define the coordinates of the target region - * relative to the - * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE }. - * The array represents the target region coordinates as: top-left, top-right, bottom-left, - * bottom-right.</p> - * <p><b>Range of valid values:</b><br> - * The list of target coordinates will define a region within the bounds of the - * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE }</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<android.graphics.PointF[]> EFV_TARGET_COORDINATES = CaptureResult.EFV_TARGET_COORDINATES; - - /** - * <p>Used to apply an additional digital zoom factor for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>For the {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * feature, an additional zoom factor is applied on top of the existing {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio}. - * This additional zoom factor serves as a buffer to provide more flexibility for the - * {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } - * mode. If {@link ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } is not set, the default will be used. - * The effectiveness of the stabilization may be influenced by the amount of padding zoom - * applied. A higher padding zoom factor can stabilize the target region more effectively - * with greater flexibility but may potentially impact image quality. Conversely, a lower - * padding zoom factor may be used to prioritize preserving image quality, albeit with less - * leeway in stabilizing the target region. It is recommended to set the - * {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } to at least 1.5.</p> - * <p>If {@link ExtensionCaptureRequest#EFV_AUTO_ZOOM } is enabled, the requested {@link ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } will be overridden. - * {@link ExtensionCaptureRequest#EFV_MAX_PADDING_ZOOM_FACTOR } can be checked for more details on controlling the - * padding zoom factor during {@link ExtensionCaptureRequest#EFV_AUTO_ZOOM }.</p> - * <p><b>Range of valid values:</b><br> - * {@link CameraExtensionCharacteristics#EFV_PADDING_ZOOM_FACTOR_RANGE }</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see CaptureRequest#CONTROL_ZOOM_RATIO - * @see ExtensionCaptureRequest#EFV_AUTO_ZOOM - * @see ExtensionCaptureRequest#EFV_MAX_PADDING_ZOOM_FACTOR - * @see ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR - * @see CameraExtensionCharacteristics#EFV_PADDING_ZOOM_FACTOR_RANGE - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Float> EFV_PADDING_ZOOM_FACTOR = CaptureResult.EFV_PADDING_ZOOM_FACTOR; - - /** - * <p>Set the stabilization mode for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension</p> - * <p>The desired stabilization mode. Gimbal stabilization mode provides simple, non-locked - * video stabilization. Locked mode uses the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * stabilization feature to fixate on the current region, utilizing it as the target area for - * stabilization.</p> - * <p><b>Possible values:</b></p> - * <ul> - * <li>{@link #EFV_STABILIZATION_MODE_OFF OFF}</li> - * <li>{@link #EFV_STABILIZATION_MODE_GIMBAL GIMBAL}</li> - * <li>{@link #EFV_STABILIZATION_MODE_LOCKED LOCKED}</li> - * </ul> - * - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * @see #EFV_STABILIZATION_MODE_OFF - * @see #EFV_STABILIZATION_MODE_GIMBAL - * @see #EFV_STABILIZATION_MODE_LOCKED - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Integer> EFV_STABILIZATION_MODE = CaptureResult.EFV_STABILIZATION_MODE; - - /** - * <p>Used to enable or disable auto zoom for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>Turn on auto zoom to let the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * feature decide at any given point a combination of - * {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} and {@link ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } - * to keep the target region in view and stabilized. The combination chosen by the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * will equal the requested {@link CaptureRequest#CONTROL_ZOOM_RATIO android.control.zoomRatio} multiplied with the requested - * {@link ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR }. A limit can be set on the padding zoom if wanting - * to control image quality further using {@link ExtensionCaptureRequest#EFV_MAX_PADDING_ZOOM_FACTOR }.</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see CaptureRequest#CONTROL_ZOOM_RATIO - * @see ExtensionCaptureRequest#EFV_MAX_PADDING_ZOOM_FACTOR - * @see ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Boolean> EFV_AUTO_ZOOM = CaptureResult.EFV_AUTO_ZOOM; - - /** - * <p>Representing the desired clockwise rotation - * of the target region in degrees for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>Value representing the desired clockwise rotation of the target - * region in degrees.</p> - * <p><b>Range of valid values:</b><br> - * 0 to 360</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Float> EFV_ROTATE_VIEWPORT = CaptureResult.EFV_ROTATE_VIEWPORT; - - /** - * <p>Used to update the target region for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>A android.util.Pair<Integer,Integer> that represents the desired - * <Horizontal,Vertical> shift of the current locked view (or target region) in - * pixels. Negative values indicate left and upward shifts, while positive values indicate - * right and downward shifts in the active array coordinate system.</p> - * <p><b>Range of valid values:</b><br> - * android.util.Pair<Integer,Integer> represents the - * <Horizontal,Vertical> shift. The range for the horizontal shift is - * [-max({@link ExtensionCaptureResult#EFV_PADDING_REGION }-left), max({@link ExtensionCaptureResult#EFV_PADDING_REGION }-right)]. - * The range for the vertical shift is - * [-max({@link ExtensionCaptureResult#EFV_PADDING_REGION }-top), max({@link ExtensionCaptureResult#EFV_PADDING_REGION }-bottom)]</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see ExtensionCaptureResult#EFV_PADDING_REGION - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<android.util.Pair<Integer,Integer>> EFV_TRANSLATE_VIEWPORT = CaptureResult.EFV_TRANSLATE_VIEWPORT; - - /** - * <p>Used to limit the {@link ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } if - * {@link ExtensionCaptureRequest#EFV_AUTO_ZOOM } is enabled for the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode.</p> - * <p>If {@link ExtensionCaptureRequest#EFV_AUTO_ZOOM } is enabled, this key can be used to set a limit - * on the {@link ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } chosen by the - * {@link android.hardware.camera2.CameraExtensionCharacteristics#EXTENSION_EYES_FREE_VIDEOGRAPHY } - * extension in {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_STABILIZATION_MODE_LOCKED } mode - * to control image quality.</p> - * <p><b>Range of valid values:</b><br> - * The range of {@link CameraExtensionCharacteristics#EFV_PADDING_ZOOM_FACTOR_RANGE }. Use a value greater than or equal to - * the {@link android.hardware.camera2.ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR } to - * effectively utilize this key.</p> - * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p> - * - * @see ExtensionCaptureRequest#EFV_AUTO_ZOOM - * @see ExtensionCaptureRequest#EFV_PADDING_ZOOM_FACTOR - * @see CameraExtensionCharacteristics#EFV_PADDING_ZOOM_FACTOR_RANGE - */ - @PublicKey - @NonNull - @ExtensionKey - @FlaggedApi(Flags.FLAG_CONCERT_MODE_API) - public static final Key<Float> EFV_MAX_PADDING_ZOOM_FACTOR = CaptureResult.EFV_MAX_PADDING_ZOOM_FACTOR; - -} diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java index 4ddf602c447b..b5fb0502ec2c 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceSetupImpl.java @@ -205,10 +205,6 @@ public class CameraDeviceSetupImpl extends CameraDevice.CameraDeviceSetup { */ @SuppressWarnings("AndroidFrameworkCompatChange") public static boolean isCameraDeviceSetupSupported(CameraCharacteristics chars) { - if (!Flags.featureCombinationQuery()) { - return false; - } - Integer queryVersion = chars.get( CameraCharacteristics.INFO_SESSION_CONFIGURATION_QUERY_VERSION); return queryVersion != null && queryVersion > Build.VERSION_CODES.UPSIDE_DOWN_CAKE; diff --git a/core/java/android/hardware/camera2/params/SessionConfiguration.java b/core/java/android/hardware/camera2/params/SessionConfiguration.java index 9bd4860e7ccc..50c6b5b8b995 100644 --- a/core/java/android/hardware/camera2/params/SessionConfiguration.java +++ b/core/java/android/hardware/camera2/params/SessionConfiguration.java @@ -165,12 +165,10 @@ public final class SessionConfiguration implements Parcelable { source.readTypedList(outConfigs, OutputConfiguration.CREATOR); // Ignore the values for hasSessionParameters and settings because we cannot reconstruct // the CaptureRequest object. - if (Flags.featureCombinationQuery()) { - boolean hasSessionParameters = source.readBoolean(); - if (hasSessionParameters) { - CameraMetadataNative settings = new CameraMetadataNative(); - settings.readFromParcel(source); - } + boolean hasSessionParameters = source.readBoolean(); + if (hasSessionParameters) { + CameraMetadataNative settings = new CameraMetadataNative(); + settings.readFromParcel(source); } if ((inputWidth > 0) && (inputHeight > 0) && (inputFormat != -1)) { @@ -212,14 +210,12 @@ public final class SessionConfiguration implements Parcelable { dest.writeBoolean(/*isMultiResolution*/ false); } dest.writeTypedList(mOutputConfigurations); - if (Flags.featureCombinationQuery()) { - if (mSessionParameters != null) { - dest.writeBoolean(/*hasSessionParameters*/true); - CameraMetadataNative metadata = mSessionParameters.getNativeCopy(); - metadata.writeToParcel(dest, /*flags*/0); - } else { - dest.writeBoolean(/*hasSessionParameters*/false); - } + if (mSessionParameters != null) { + dest.writeBoolean(/*hasSessionParameters*/true); + CameraMetadataNative metadata = mSessionParameters.getNativeCopy(); + metadata.writeToParcel(dest, /*flags*/0); + } else { + dest.writeBoolean(/*hasSessionParameters*/false); } } diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig index 1a309c646882..983bbc3b2774 100644 --- a/core/java/android/hardware/input/input_framework.aconfig +++ b/core/java/android/hardware/input/input_framework.aconfig @@ -119,6 +119,13 @@ flag { } flag { + namespace: "input_native" + name: "use_key_gesture_event_handler_multi_press_gestures" + description: "Use KeyGestureEvent handler APIs to control multi key press gestures" + bug: "358569822" +} + +flag { name: "keyboard_repeat_keys" namespace: "input_native" description: "Allow configurable timeout before key repeat and repeat delay rate for key repeats" diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java index c22f46cdc2b5..80546cd6770f 100644 --- a/core/java/android/os/BinderProxy.java +++ b/core/java/android/os/BinderProxy.java @@ -650,13 +650,13 @@ public final class BinderProxy implements IBinder { * weakly referenced by JNI so the strong references here are needed to keep the callbacks * around until the proxy is GC'ed. */ - private List<IFrozenStateChangeCallback> mFrozenStateChangeCallbacks = + private List<FrozenStateChangeCallback> mFrozenStateChangeCallbacks = Collections.synchronizedList(new ArrayList<>()); /** - * See {@link IBinder#addFrozenStateChangeCallback(IFrozenStateChangeCallback)} + * See {@link IBinder#addFrozenStateChangeCallback(FrozenStateChangeCallback)} */ - public void addFrozenStateChangeCallback(IFrozenStateChangeCallback callback) + public void addFrozenStateChangeCallback(FrozenStateChangeCallback callback) throws RemoteException { addFrozenStateChangeCallbackNative(callback); mFrozenStateChangeCallbacks.add(callback); @@ -665,16 +665,16 @@ public final class BinderProxy implements IBinder { /** * See {@link IBinder#removeFrozenStateChangeCallback} */ - public boolean removeFrozenStateChangeCallback(IFrozenStateChangeCallback callback) { + public boolean removeFrozenStateChangeCallback(FrozenStateChangeCallback callback) { mFrozenStateChangeCallbacks.remove(callback); return removeFrozenStateChangeCallbackNative(callback); } - private native void addFrozenStateChangeCallbackNative(IFrozenStateChangeCallback callback) + private native void addFrozenStateChangeCallbackNative(FrozenStateChangeCallback callback) throws RemoteException; private native boolean removeFrozenStateChangeCallbackNative( - IFrozenStateChangeCallback callback); + FrozenStateChangeCallback callback); /** * Perform a dump on the remote object @@ -762,10 +762,9 @@ public final class BinderProxy implements IBinder { } private static void invokeFrozenStateChangeCallback( - IFrozenStateChangeCallback callback, IBinder binderProxy, int stateIndex) { + FrozenStateChangeCallback callback, IBinder binderProxy, int stateIndex) { try { - callback.onFrozenStateChanged(binderProxy, - IFrozenStateChangeCallback.State.values()[stateIndex]); + callback.onFrozenStateChanged(binderProxy, stateIndex); } catch (RuntimeException exc) { Log.w("BinderNative", "Uncaught exception from frozen state change callback", exc); diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java index 8185e8e542e1..a997f4c86704 100644 --- a/core/java/android/os/IBinder.java +++ b/core/java/android/os/IBinder.java @@ -16,11 +16,15 @@ package android.os; +import android.annotation.FlaggedApi; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import java.io.FileDescriptor; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Base interface for a remotable object, the core part of a lightweight @@ -377,9 +381,24 @@ public interface IBinder { */ public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags); - /** @hide */ - interface IFrozenStateChangeCallback { - enum State {FROZEN, UNFROZEN}; + /** + * A callback interface for receiving frozen state change events. + */ + @FlaggedApi(Flags.FLAG_BINDER_FROZEN_STATE_CHANGE_CALLBACK) + interface FrozenStateChangeCallback { + /** + * @hide + */ + @IntDef(prefix = {"STATE_"}, value = { + STATE_FROZEN, + STATE_UNFROZEN, + }) + @Retention(RetentionPolicy.SOURCE) + @interface State { + } + + int STATE_FROZEN = 0; + int STATE_UNFROZEN = 1; /** * Interface for receiving a callback when the process hosting an IBinder @@ -387,13 +406,13 @@ public interface IBinder { * @param who The IBinder whose hosting process has changed state. * @param state The latest state. */ - void onFrozenStateChanged(@NonNull IBinder who, State state); + void onFrozenStateChanged(@NonNull IBinder who, @State int state); } /** - * {@link addFrozenStateChangeCallback} provides a callback mechanism to notify about process - * frozen/unfrozen events. Upon registration and any subsequent state changes, the callback is - * invoked with the latest process frozen state. + * This method provides a callback mechanism to notify about process frozen/unfrozen events. + * Upon registration and any subsequent state changes, the callback is invoked with the latest + * process frozen state. * * <p>If the listener process (the one using this API) is itself frozen, state change events * might be combined into a single one with the latest frozen state. This single event would @@ -410,19 +429,19 @@ public interface IBinder { * * <p>@throws {@link UnsupportedOperationException} if the kernel binder driver does not support * this feature. - * @hide */ - default void addFrozenStateChangeCallback(@NonNull IFrozenStateChangeCallback callback) + @FlaggedApi(Flags.FLAG_BINDER_FROZEN_STATE_CHANGE_CALLBACK) + default void addFrozenStateChangeCallback(@NonNull FrozenStateChangeCallback callback) throws RemoteException { throw new UnsupportedOperationException(); } /** - * Unregister a {@link IFrozenStateChangeCallback}. The callback will no longer be invoked when + * Unregister a {@link FrozenStateChangeCallback}. The callback will no longer be invoked when * the hosting process changes its frozen state. - * @hide */ - default boolean removeFrozenStateChangeCallback(@NonNull IFrozenStateChangeCallback callback) { + @FlaggedApi(Flags.FLAG_BINDER_FROZEN_STATE_CHANGE_CALLBACK) + default boolean removeFrozenStateChangeCallback(@NonNull FrozenStateChangeCallback callback) { throw new UnsupportedOperationException(); } } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index a4a7a983c44c..1ca4574e79b4 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -3763,7 +3763,8 @@ public class UserManager { } private static final String CACHE_KEY_IS_USER_UNLOCKED_PROPERTY = - "cache_key.is_user_unlocked"; + PropertyInvalidatedCache.createPropertyName( + PropertyInvalidatedCache.MODULE_SYSTEM, "is_user_unlocked"); private final PropertyInvalidatedCache<Integer, Boolean> mIsUserUnlockedCache = new PropertyInvalidatedCache<Integer, Boolean>( @@ -6694,7 +6695,9 @@ public class UserManager { } /* Cache key for anything that assumes that userIds cannot be re-used without rebooting. */ - private static final String CACHE_KEY_STATIC_USER_PROPERTIES = "cache_key.static_user_props"; + private static final String CACHE_KEY_STATIC_USER_PROPERTIES = + PropertyInvalidatedCache.createPropertyName( + PropertyInvalidatedCache.MODULE_SYSTEM, "static_user_props"); private final PropertyInvalidatedCache<Integer, String> mProfileTypeCache = new PropertyInvalidatedCache<Integer, String>(32, CACHE_KEY_STATIC_USER_PROPERTIES) { @@ -6721,7 +6724,9 @@ public class UserManager { } /* Cache key for UserProperties object. */ - private static final String CACHE_KEY_USER_PROPERTIES = "cache_key.user_properties"; + private static final String CACHE_KEY_USER_PROPERTIES = + PropertyInvalidatedCache.createPropertyName( + PropertyInvalidatedCache.MODULE_SYSTEM, "user_properties"); // TODO: It would be better to somehow have this as static, so that it can work cross-context. private final PropertyInvalidatedCache<Integer, UserProperties> mUserPropertiesCache = diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig index 39bd15c968d7..738d12978aed 100644 --- a/core/java/android/os/flags.aconfig +++ b/core/java/android/os/flags.aconfig @@ -153,6 +153,14 @@ flag { } flag { + name: "binder_frozen_state_change_callback" + is_exported: true + namespace: "system_performance" + description: "Guards the frozen state change callback API." + bug: "361157077" +} + +flag { name: "message_queue_tail_tracking" namespace: "system_performance" description: "track tail of message queue." diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 01c230fe8f63..a62281049678 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -3018,169 +3018,180 @@ public final class ContactsContract { com.android.internal.R.string.config_rawContactsLocalAccountType)); } + + /** - * Represents the state of the default account, and the actual {@link Account} if it's - * a cloud account. - * If the default account is set to {@link #DEFAULT_ACCOUNT_STATE_LOCAL} or - * {@link #DEFAULT_ACCOUNT_STATE_CLOUD}, new raw contacts requested for insertion - * without a - * specified {@link Account} will be saved in the default account. - * The default account can have one of the following four states: - * <ul> - * <li> {@link #DEFAULT_ACCOUNT_STATE_NOT_SET}: The default account has not - * been set by the user. </li> - * <li> {@link #DEFAULT_ACCOUNT_STATE_LOCAL}: The default account is set to - * the local device storage. New raw contacts requested for insertion without a - * specified - * {@link Account} will be saved in a null or custom local account. </li> - * <li> {@link #DEFAULT_ACCOUNT_STATE_CLOUD}: The default account is set to a - * cloud-synced account. New raw contacts requested for insertion without a specified - * {@link Account} will be saved in the default cloud account. </li> - * </ul> + * Class containing utility methods around the default account. + * New raw contacts requested to be inserted without a specified {@link Account} will be + * saved in the default account. */ @FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED) - public static final class DefaultAccountAndState { - /** A state indicating that default account is not set. */ - public static final int DEFAULT_ACCOUNT_STATE_NOT_SET = 1; - - /** A state indicating that default account is set to local device storage. */ - public static final int DEFAULT_ACCOUNT_STATE_LOCAL = 2; + public static final class DefaultAccount { /** - * A state indicating that the default account is set as an account that is synced - * to the cloud. - */ - public static final int DEFAULT_ACCOUNT_STATE_CLOUD = 3; + * Represents the state of the default account, and the actual {@link Account} if it's + * a cloud account. + * If the default account is set to {@link #DEFAULT_ACCOUNT_STATE_LOCAL} or + * {@link #DEFAULT_ACCOUNT_STATE_CLOUD}, new raw contacts requested for insertion + * without a + * specified {@link Account} will be saved in the default account. + * The default account can have one of the following four states: + * <ul> + * <li> {@link #DEFAULT_ACCOUNT_STATE_NOT_SET}: The default account has not + * been set by the user. </li> + * <li> {@link #DEFAULT_ACCOUNT_STATE_LOCAL}: The default account is set to + * the local device storage. New raw contacts requested for insertion without a + * specified + * {@link Account} will be saved in a null or custom local account. </li> + * <li> {@link #DEFAULT_ACCOUNT_STATE_CLOUD}: The default account is set to a + * cloud-synced account. New raw contacts requested for insertion without a specified + * {@link Account} will be saved in the default cloud account. </li> + * </ul> + */ + @FlaggedApi(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED) + public static final class DefaultAccountAndState { + /** A state indicating that default account is not set. */ + public static final int DEFAULT_ACCOUNT_STATE_NOT_SET = 1; + + /** A state indicating that default account is set to local device storage. */ + public static final int DEFAULT_ACCOUNT_STATE_LOCAL = 2; - /** - * The state of the default account. One of - * {@link #DEFAULT_ACCOUNT_STATE_NOT_SET}, - * {@link #DEFAULT_ACCOUNT_STATE_LOCAL} or - * {@link #DEFAULT_ACCOUNT_STATE_CLOUD}. - */ - @DefaultAccountState - private final int mState; + /** + * A state indicating that the default account is set as an account that is synced + * to the cloud. + */ + public static final int DEFAULT_ACCOUNT_STATE_CLOUD = 3; - /** - * The account of the default account, when {@link mState} is { - * - * @link #STATE_SET_TO_CLOUD}, or null otherwise. - */ - private final Account mCloudAccount; + /** + * The state of the default account. One of + * {@link #DEFAULT_ACCOUNT_STATE_NOT_SET}, + * {@link #DEFAULT_ACCOUNT_STATE_LOCAL} or + * {@link #DEFAULT_ACCOUNT_STATE_CLOUD}. + */ + @DefaultAccountState + private final int mState; - /** - * Constructs a new `DefaultAccountAndState` instance with the specified state and - * cloud - * account. - * - * @param state The state of the default account. - * @param cloudAccount The cloud account associated with the default account, - * or null if the state is not - * {@link #DEFAULT_ACCOUNT_STATE_CLOUD}. - */ - public DefaultAccountAndState(@DefaultAccountState int state, - @Nullable Account cloudAccount) { - if (!isValidDefaultAccountState(state)) { - throw new IllegalArgumentException("Invalid default account state."); + /** + * The account of the default account, when {@link mState} is { + * + * @link #STATE_SET_TO_CLOUD}, or null otherwise. + */ + private final Account mCloudAccount; + + /** + * Constructs a new `DefaultAccountAndState` instance with the specified state and + * cloud + * account. + * + * @param state The state of the default account. + * @param cloudAccount The cloud account associated with the default account, + * or null if the state is not + * {@link #DEFAULT_ACCOUNT_STATE_CLOUD}. + */ + public DefaultAccountAndState(@DefaultAccountState int state, + @Nullable Account cloudAccount) { + if (!isValidDefaultAccountState(state)) { + throw new IllegalArgumentException("Invalid default account state."); + } + if ((state == DEFAULT_ACCOUNT_STATE_CLOUD) != (cloudAccount != null)) { + throw new IllegalArgumentException( + "Default account can be set to cloud if and only if the cloud " + + "account is provided."); + } + this.mState = state; + this.mCloudAccount = + (mState == DEFAULT_ACCOUNT_STATE_CLOUD) ? cloudAccount : null; } - if ((state == DEFAULT_ACCOUNT_STATE_CLOUD) != (cloudAccount != null)) { - throw new IllegalArgumentException( - "Default account can be set to cloud if and only if the cloud " - + "account is provided."); + + /** + * Creates a `DefaultAccountAndState` instance representing a default account + * that is set to the cloud and associated with the specified cloud account. + * + * @param cloudAccount The non-null cloud account associated with the default + * contacts + * account. + * @return A new `DefaultAccountAndState` instance with state + * {@link #DEFAULT_ACCOUNT_STATE_CLOUD}. + */ + public static @NonNull DefaultAccountAndState ofCloud( + @NonNull Account cloudAccount) { + return new DefaultAccountAndState(DEFAULT_ACCOUNT_STATE_CLOUD, cloudAccount); } - this.mState = state; - this.mCloudAccount = - (mState == DEFAULT_ACCOUNT_STATE_CLOUD) ? cloudAccount : null; - } - /** - * Creates a `DefaultAccountAndState` instance representing a default account - * that is set to the cloud and associated with the specified cloud account. - * - * @param cloudAccount The non-null cloud account associated with the default - * contacts - * account. - * @return A new `DefaultAccountAndState` instance with state - * {@link #DEFAULT_ACCOUNT_STATE_CLOUD}. - */ - public static @NonNull DefaultAccountAndState ofCloud( - @NonNull Account cloudAccount) { - return new DefaultAccountAndState(DEFAULT_ACCOUNT_STATE_CLOUD, cloudAccount); - } + /** + * Creates a `DefaultAccountAndState` instance representing a default account + * that is set to the local device storage. + * + * @return A new `DefaultAccountAndState` instance with state + * {@link #DEFAULT_ACCOUNT_STATE_LOCAL}. + */ + public static @NonNull DefaultAccountAndState ofLocal() { + return new DefaultAccountAndState(DEFAULT_ACCOUNT_STATE_LOCAL, null); + } - /** - * Creates a `DefaultAccountAndState` instance representing a default account - * that is set to the local device storage. - * - * @return A new `DefaultAccountAndState` instance with state - * {@link #DEFAULT_ACCOUNT_STATE_LOCAL}. - */ - public static @NonNull DefaultAccountAndState ofLocal() { - return new DefaultAccountAndState(DEFAULT_ACCOUNT_STATE_LOCAL, null); - } + /** + * Creates a `DefaultAccountAndState` instance representing a default account + * that is not set. + * + * @return A new `DefaultAccountAndState` instance with state + * {@link #DEFAULT_ACCOUNT_STATE_NOT_SET}. + */ + public static @NonNull DefaultAccountAndState ofNotSet() { + return new DefaultAccountAndState(DEFAULT_ACCOUNT_STATE_NOT_SET, null); + } - /** - * Creates a `DefaultAccountAndState` instance representing a default account - * that is not set. - * - * @return A new `DefaultAccountAndState` instance with state - * {@link #DEFAULT_ACCOUNT_STATE_NOT_SET}. - */ - public static @NonNull DefaultAccountAndState ofNotSet() { - return new DefaultAccountAndState(DEFAULT_ACCOUNT_STATE_NOT_SET, null); - } + /** + * @return the state of the default account. + */ + @DefaultAccountState + public int getState() { + return mState; + } - /** - * @return the state of the default account. - */ - @DefaultAccountState - public int getState() { - return mState; - } + /** + * @return the cloud account associated with the default account, or null if the + * state is not {@link #DEFAULT_ACCOUNT_STATE_CLOUD}. + */ + public @Nullable Account getCloudAccount() { + return mCloudAccount; + } - /** - * @return the cloud account associated with the default account, or null if the - * state is not {@link #DEFAULT_ACCOUNT_STATE_CLOUD}. - */ - public @Nullable Account getCloudAccount() { - return mCloudAccount; - } + @Override + public int hashCode() { + return Objects.hash(mState, mCloudAccount); + } - @Override - public int hashCode() { - return Objects.hash(mState, mCloudAccount); - } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof DefaultAccountAndState that)) { + return false; + } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof DefaultAccountAndState that)) { - return false; + return mState == that.mState && Objects.equals(mCloudAccount, + that.mCloudAccount); } - return mState == that.mState && Objects.equals(mCloudAccount, - that.mCloudAccount); - } - - private static boolean isValidDefaultAccountState(int state) { - return state == DEFAULT_ACCOUNT_STATE_NOT_SET - || state == DEFAULT_ACCOUNT_STATE_LOCAL - || state == DEFAULT_ACCOUNT_STATE_CLOUD; - } + private static boolean isValidDefaultAccountState(int state) { + return state == DEFAULT_ACCOUNT_STATE_NOT_SET + || state == DEFAULT_ACCOUNT_STATE_LOCAL + || state == DEFAULT_ACCOUNT_STATE_CLOUD; + } - /** - * Annotation for all default account states. - * - * @hide - */ - @Retention(RetentionPolicy.SOURCE) - @IntDef( - prefix = {"DEFAULT_ACCOUNT_STATE_"}, - value = {DEFAULT_ACCOUNT_STATE_NOT_SET, - DEFAULT_ACCOUNT_STATE_LOCAL, DEFAULT_ACCOUNT_STATE_CLOUD}) - public @interface DefaultAccountState { + /** + * Annotation for all default account states. + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + prefix = {"DEFAULT_ACCOUNT_STATE_"}, + value = {DEFAULT_ACCOUNT_STATE_NOT_SET, + DEFAULT_ACCOUNT_STATE_LOCAL, DEFAULT_ACCOUNT_STATE_CLOUD}) + public @interface DefaultAccountState { + } } } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index e32625e1f7a8..0ada9934482c 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -111,6 +111,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import java.net.URISyntaxException; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -3022,6 +3023,9 @@ public final class Settings { /** @hide - Private call() method to query the 'configuration' table */ public static final String CALL_METHOD_LIST_CONFIG = "LIST_config"; + /** @hide - Private call() method to query the 'configuration' tables' namespaces */ + public static final String CALL_METHOD_LIST_NAMESPACES_CONFIG = "LIST_namespaces_config"; + /** @hide - Private call() method to disable / re-enable syncs to the 'configuration' table */ public static final String CALL_METHOD_SET_SYNC_DISABLED_MODE_CONFIG = "SET_SYNC_DISABLED_MODE_config"; @@ -20458,6 +20462,10 @@ public final class Settings { * * The keys take the form {@code namespace/flag}, and the values are the flag values. * + * Note: this API is _not_ performant, and may make a large number of + * Binder calls. It is intended for use in testing and debugging, and + * should not be used in performance-sensitive code. + * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @@ -20469,13 +20477,33 @@ public final class Settings { Bundle arg = new Bundle(); arg.putInt(Settings.CALL_METHOD_USER_KEY, resolver.getUserId()); IContentProvider cp = sProviderHolder.getProvider(resolver); - Bundle b = cp.call(resolver.getAttributionSource(), - sProviderHolder.mUri.getAuthority(), CALL_METHOD_LIST_CONFIG, null, arg); - if (b != null) { - Map<String, String> flagsToValues = - (HashMap) b.getSerializable(Settings.NameValueTable.VALUE, - java.util.HashMap.class); - allFlags.putAll(flagsToValues); + + if (Flags.reduceBinderTransactionSizeForGetAllProperties()) { + Bundle b = cp.call(resolver.getAttributionSource(), + sProviderHolder.mUri.getAuthority(), + CALL_METHOD_LIST_NAMESPACES_CONFIG, null, arg); + if (b != null) { + HashSet<String> namespaces = + (HashSet) b.getSerializable(Settings.NameValueTable.VALUE, + java.util.HashSet.class); + for (String namespace : namespaces) { + Map<String, String> keyValues = + getStrings(namespace, new ArrayList()); + for (String key : keyValues.keySet()) { + allFlags.put(namespace + "/" + key, keyValues.get(key)); + } + } + } + } else { + Bundle b = cp.call(resolver.getAttributionSource(), + sProviderHolder.mUri.getAuthority(), + CALL_METHOD_LIST_CONFIG, null, arg); + if (b != null) { + Map<String, String> flagsToValues = + (HashMap) b.getSerializable(Settings.NameValueTable.VALUE, + java.util.HashMap.class); + allFlags.putAll(flagsToValues); + } } } catch (RemoteException e) { Log.w(TAG, "Can't query configuration table for " + CONTENT_URI, e); diff --git a/core/java/android/provider/flags.aconfig b/core/java/android/provider/flags.aconfig index 5c0f8737ca27..4c636735b5ce 100644 --- a/core/java/android/provider/flags.aconfig +++ b/core/java/android/provider/flags.aconfig @@ -52,3 +52,14 @@ flag { description: "Enable the new ContactsContract Default Account APIs." bug: "359957527" } + +flag { + name: "reduce_binder_transaction_size_for_get_all_properties" + namespace: "core_experiments_team_internal" + description: "Reduce Binder transaction size in getAllProperties calls" + bug: "362652574" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index 752f174504f2..d45b24ed69be 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -313,6 +313,7 @@ public class ZenModeConfig implements Parcelable { private static final String RULE_ATT_DELETION_INSTANT = "deletionInstant"; private static final String RULE_ATT_DISABLED_ORIGIN = "disabledOrigin"; private static final String RULE_ATT_LEGACY_SUPPRESSED_EFFECTS = "legacySuppressedEffects"; + private static final String RULE_ATT_CONDITION_OVERRIDE = "conditionOverride"; private static final String DEVICE_EFFECT_DISPLAY_GRAYSCALE = "zdeDisplayGrayscale"; private static final String DEVICE_EFFECT_SUPPRESS_AMBIENT_DISPLAY = @@ -1045,6 +1046,8 @@ public class ZenModeConfig implements Parcelable { DEFAULT_SUPPRESSED_VISUAL_EFFECTS); } else if (MANUAL_TAG.equals(tag)) { rt.manualRule = readRuleXml(parser); + // manualRule.enabled can never be false, but it was broken in some builds. + rt.manualRule.enabled = true; // Manual rule may be present prior to modes_ui if it were on, but in that // case it would not have a set policy, so make note of the need to set // it up later. @@ -1144,7 +1147,7 @@ public class ZenModeConfig implements Parcelable { if (manualRule != null) { out.startTag(null, MANUAL_TAG); - writeRuleXml(manualRule, out); + writeRuleXml(manualRule, out, forBackup); out.endTag(null, MANUAL_TAG); } final int N = automaticRules.size(); @@ -1153,7 +1156,7 @@ public class ZenModeConfig implements Parcelable { final ZenRule automaticRule = automaticRules.valueAt(i); out.startTag(null, AUTOMATIC_TAG); out.attribute(null, RULE_ATT_ID, id); - writeRuleXml(automaticRule, out); + writeRuleXml(automaticRule, out, forBackup); out.endTag(null, AUTOMATIC_TAG); } if (Flags.modesApi() && !forBackup) { @@ -1161,7 +1164,7 @@ public class ZenModeConfig implements Parcelable { final ZenRule deletedRule = deletedRules.valueAt(i); out.startTag(null, AUTOMATIC_DELETED_TAG); out.attribute(null, RULE_ATT_ID, deletedRule.id); - writeRuleXml(deletedRule, out); + writeRuleXml(deletedRule, out, forBackup); out.endTag(null, AUTOMATIC_DELETED_TAG); } } @@ -1220,12 +1223,15 @@ public class ZenModeConfig implements Parcelable { ORIGIN_UNKNOWN); rt.legacySuppressedEffects = safeInt(parser, RULE_ATT_LEGACY_SUPPRESSED_EFFECTS, 0); + rt.conditionOverride = safeInt(parser, RULE_ATT_CONDITION_OVERRIDE, + ZenRule.OVERRIDE_NONE); } } return rt; } - public static void writeRuleXml(ZenRule rule, TypedXmlSerializer out) throws IOException { + public static void writeRuleXml(ZenRule rule, TypedXmlSerializer out, boolean forBackup) + throws IOException { out.attributeBoolean(null, RULE_ATT_ENABLED, rule.enabled); if (rule.name != null) { out.attribute(null, RULE_ATT_NAME, rule.name); @@ -1279,6 +1285,9 @@ public class ZenModeConfig implements Parcelable { out.attributeInt(null, RULE_ATT_DISABLED_ORIGIN, rule.disabledOrigin); out.attributeInt(null, RULE_ATT_LEGACY_SUPPRESSED_EFFECTS, rule.legacySuppressedEffects); + if (rule.conditionOverride == ZenRule.OVERRIDE_ACTIVATE && !forBackup) { + out.attributeInt(null, RULE_ATT_CONDITION_OVERRIDE, rule.conditionOverride); + } } } } @@ -2622,9 +2631,12 @@ public class ZenModeConfig implements Parcelable { int legacySuppressedEffects; /** * Signals a user's action to (temporarily or permanently) activate or deactivate this - * rule, overruling the condition set by the owner. This value is not stored to disk, as - * it shouldn't survive reboots or be involved in B&R. It might be reset by certain - * owner-provided state transitions as well. + * rule, overruling the condition set by the owner. + * + * <p>An {@link #OVERRIDE_ACTIVATE} is stored to disk, since we want it to survive reboots + * (but it's not included in B&R), while an {@link #OVERRIDE_DEACTIVATE} is not (meaning + * that snoozed rules may reactivate on reboot). It might be reset by certain owner-provided + * state transitions as well. */ @FlaggedApi(Flags.FLAG_MODES_UI) @ConditionOverride diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index ad457ce6e18d..384add5cf929 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -70,6 +70,7 @@ import android.graphics.drawable.Drawable; import android.hardware.HardwareBuffer; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; +import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -370,6 +371,7 @@ public abstract class WallpaperService extends Service { private float mDefaultDimAmount = 0.05f; SurfaceControl mBbqSurfaceControl; BLASTBufferQueue mBlastBufferQueue; + IBinder mBbqApplyToken = new Binder(); private SurfaceControl mScreenshotSurfaceControl; private Point mScreenshotSize = new Point(); @@ -2390,6 +2392,7 @@ public abstract class WallpaperService extends Service { if (mBlastBufferQueue == null) { mBlastBufferQueue = new BLASTBufferQueue("Wallpaper", mBbqSurfaceControl, width, height, format); + mBlastBufferQueue.setApplyToken(mBbqApplyToken); // We only return the Surface the first time, as otherwise // it hasn't changed and there is no need to update. ret = mBlastBufferQueue.createSurface(); diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig index 3c61f4f5a33c..3846972a12e8 100644 --- a/core/java/android/text/flags/flags.aconfig +++ b/core/java/android/text/flags/flags.aconfig @@ -84,17 +84,6 @@ flag { } flag { - name: "fix_font_update_failure" - namespace: "text" - description: "There was a bug of updating system font from Android 13 to 14. This flag for fixing the migration failure." - is_fixed_read_only: true - bug: "331717791" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "fix_misaligned_context_menu" namespace: "text" description: "Fix the context menu misalignment and incosistent icon size." @@ -154,26 +143,6 @@ flag { } flag { - name: "portuguese_hyphenator" - namespace: "text" - description: "Portuguese taiored hyphenator" - bug: "344656282" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { - name: "dont_break_email_in_nobreak_tag" - namespace: "text" - description: "Prevent line break inside email." - bug: "350691716" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "handwriting_gesture_with_transformation" namespace: "text" description: "Fix handwriting gesture is not working when view has transformation." diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index f8c97eb5fa72..53935e810913 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -1341,7 +1341,7 @@ public final class Display { public HdrCapabilities getHdrCapabilities() { synchronized (mLock) { updateDisplayInfoLocked(); - if (mDisplayInfo.hdrCapabilities == null) { + if (mDisplayInfo.hdrCapabilities == null || mDisplayInfo.isForceSdr) { return null; } int[] supportedHdrTypes; @@ -1363,6 +1363,7 @@ public final class Display { supportedHdrTypes[index++] = enabledType; } } + return new HdrCapabilities(supportedHdrTypes, mDisplayInfo.hdrCapabilities.mMaxLuminance, mDisplayInfo.hdrCapabilities.mMaxAverageLuminance, @@ -2087,6 +2088,7 @@ public final class Display { /** * @hide */ + @android.ravenwood.annotation.RavenwoodKeep public static String stateToString(int state) { switch (state) { case STATE_UNKNOWN: @@ -2109,6 +2111,7 @@ public final class Display { } /** @hide */ + @android.ravenwood.annotation.RavenwoodKeep public static String stateReasonToString(@StateReason int reason) { switch (reason) { case STATE_REASON_UNKNOWN: diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 157cec8a4d0f..cac3e3c25098 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -230,6 +230,9 @@ public final class DisplayInfo implements Parcelable { /** The formats disabled by user **/ public int[] userDisabledHdrTypes = {}; + /** When true, all HDR capabilities are disabled **/ + public boolean isForceSdr; + /** * Indicates whether the display can be switched into a mode with minimal post * processing. @@ -440,6 +443,7 @@ public final class DisplayInfo implements Parcelable { && colorMode == other.colorMode && Arrays.equals(supportedColorModes, other.supportedColorModes) && Objects.equals(hdrCapabilities, other.hdrCapabilities) + && isForceSdr == other.isForceSdr && Arrays.equals(userDisabledHdrTypes, other.userDisabledHdrTypes) && minimalPostProcessingSupported == other.minimalPostProcessingSupported && logicalDensityDpi == other.logicalDensityDpi @@ -502,6 +506,7 @@ public final class DisplayInfo implements Parcelable { supportedColorModes = Arrays.copyOf( other.supportedColorModes, other.supportedColorModes.length); hdrCapabilities = other.hdrCapabilities; + isForceSdr = other.isForceSdr; userDisabledHdrTypes = other.userDisabledHdrTypes; minimalPostProcessingSupported = other.minimalPostProcessingSupported; logicalDensityDpi = other.logicalDensityDpi; @@ -567,6 +572,7 @@ public final class DisplayInfo implements Parcelable { supportedColorModes[i] = source.readInt(); } hdrCapabilities = source.readParcelable(null, android.view.Display.HdrCapabilities.class); + isForceSdr = source.readBoolean(); minimalPostProcessingSupported = source.readBoolean(); logicalDensityDpi = source.readInt(); physicalXDpi = source.readFloat(); @@ -636,6 +642,7 @@ public final class DisplayInfo implements Parcelable { dest.writeInt(supportedColorModes[i]); } dest.writeParcelable(hdrCapabilities, flags); + dest.writeBoolean(isForceSdr); dest.writeBoolean(minimalPostProcessingSupported); dest.writeInt(logicalDensityDpi); dest.writeFloat(physicalXDpi); @@ -874,6 +881,8 @@ public final class DisplayInfo implements Parcelable { sb.append(Arrays.toString(appsSupportedModes)); sb.append(", hdrCapabilities "); sb.append(hdrCapabilities); + sb.append(", isForceSdr "); + sb.append(isForceSdr); sb.append(", userDisabledHdrTypes "); sb.append(Arrays.toString(userDisabledHdrTypes)); sb.append(", minimalPostProcessingSupported "); diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index 6b4340a02edc..15a4715bd059 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -38,6 +38,7 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS; import android.annotation.NonNull; import android.annotation.Nullable; @@ -55,7 +56,6 @@ import android.view.WindowInsets.Type.InsetsType; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import com.android.internal.annotations.VisibleForTesting; -import com.android.window.flags.Flags; import java.io.PrintWriter; import java.util.Objects; @@ -146,7 +146,7 @@ public class InsetsState implements Parcelable { forceConsumingTypes |= type; } - if (Flags.enableCaptionCompatInsetForceConsumptionAlways() + if (ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS.isEnabled() && (flags & FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR) != 0) { forceConsumingOpaqueCaptionBar = true; } diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java index dd950e83dd52..b21e85aeeb6a 100644 --- a/core/java/android/view/PointerIcon.java +++ b/core/java/android/view/PointerIcon.java @@ -174,24 +174,26 @@ public final class PointerIcon implements Parcelable { @IntDef(prefix = {"POINTER_ICON_VECTOR_STYLE_FILL_"}, value = { POINTER_ICON_VECTOR_STYLE_FILL_BLACK, POINTER_ICON_VECTOR_STYLE_FILL_GREEN, - POINTER_ICON_VECTOR_STYLE_FILL_YELLOW, + POINTER_ICON_VECTOR_STYLE_FILL_RED, POINTER_ICON_VECTOR_STYLE_FILL_PINK, - POINTER_ICON_VECTOR_STYLE_FILL_BLUE + POINTER_ICON_VECTOR_STYLE_FILL_BLUE, + POINTER_ICON_VECTOR_STYLE_FILL_PURPLE }) @Retention(RetentionPolicy.SOURCE) public @interface PointerIconVectorStyleFill {} /** @hide */ public static final int POINTER_ICON_VECTOR_STYLE_FILL_BLACK = 0; /** @hide */ public static final int POINTER_ICON_VECTOR_STYLE_FILL_GREEN = 1; - /** @hide */ public static final int POINTER_ICON_VECTOR_STYLE_FILL_YELLOW = 2; + /** @hide */ public static final int POINTER_ICON_VECTOR_STYLE_FILL_RED = 2; /** @hide */ public static final int POINTER_ICON_VECTOR_STYLE_FILL_PINK = 3; /** @hide */ public static final int POINTER_ICON_VECTOR_STYLE_FILL_BLUE = 4; + /** @hide */ public static final int POINTER_ICON_VECTOR_STYLE_FILL_PURPLE = 5; // If adding a PointerIconVectorStyleFill, update END value for {@link SystemSettingsValidators} /** @hide */ public static final int POINTER_ICON_VECTOR_STYLE_FILL_BEGIN = POINTER_ICON_VECTOR_STYLE_FILL_BLACK; /** @hide */ public static final int POINTER_ICON_VECTOR_STYLE_FILL_END = - POINTER_ICON_VECTOR_STYLE_FILL_BLUE; + POINTER_ICON_VECTOR_STYLE_FILL_PURPLE; /** @hide */ @IntDef(prefix = {"POINTER_ICON_VECTOR_STYLE_STROKE_"}, value = { @@ -712,12 +714,14 @@ public final class PointerIcon implements Parcelable { com.android.internal.R.style.PointerIconVectorStyleFillBlack; case POINTER_ICON_VECTOR_STYLE_FILL_GREEN -> com.android.internal.R.style.PointerIconVectorStyleFillGreen; - case POINTER_ICON_VECTOR_STYLE_FILL_YELLOW -> - com.android.internal.R.style.PointerIconVectorStyleFillYellow; + case POINTER_ICON_VECTOR_STYLE_FILL_RED -> + com.android.internal.R.style.PointerIconVectorStyleFillRed; case POINTER_ICON_VECTOR_STYLE_FILL_PINK -> com.android.internal.R.style.PointerIconVectorStyleFillPink; case POINTER_ICON_VECTOR_STYLE_FILL_BLUE -> com.android.internal.R.style.PointerIconVectorStyleFillBlue; + case POINTER_ICON_VECTOR_STYLE_FILL_PURPLE -> + com.android.internal.R.style.PointerIconVectorStyleFillPurple; default -> com.android.internal.R.style.PointerIconVectorStyleFillBlack; }; } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e10cc28d0745..33e79059c7e5 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -125,11 +125,11 @@ import static android.view.flags.Flags.toolkitMetricsForFrameRateDecision; import static android.view.flags.Flags.toolkitSetFrameRateReadOnly; import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_FOCUS_CONTROLLER; import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INSETS_CONTROLLER; +import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import static com.android.text.flags.Flags.disableHandwritingInitiatorForIme; import static com.android.window.flags.Flags.enableBufferTransformHintFromDisplay; -import static com.android.window.flags.Flags.enableCaptionCompatInsetForceConsumption; import static com.android.window.flags.Flags.insetsControlChangedItem; import static com.android.window.flags.Flags.insetsControlSeq; import static com.android.window.flags.Flags.setScPropertiesInClient; @@ -829,6 +829,7 @@ public final class ViewRootImpl implements ViewParent, private final SurfaceControl mSurfaceControl = new SurfaceControl(); private BLASTBufferQueue mBlastBufferQueue; + private IBinder mBbqApplyToken = new Binder(); private final HdrRenderState mHdrRenderState = new HdrRenderState(this); @@ -2743,6 +2744,10 @@ public final class ViewRootImpl implements ViewParent, mBlastBufferQueue = new BLASTBufferQueue(mTag, mSurfaceControl, mSurfaceSize.x, mSurfaceSize.y, mWindowAttributes.format); mBlastBufferQueue.setTransactionHangCallback(sTransactionHangCallback); + // If we create and destroy BBQ without recreating the SurfaceControl, we can end up + // queuing buffers on multiple apply tokens causing out of order buffer submissions. We + // fix this by setting the same apply token on all BBQs created by this VRI. + mBlastBufferQueue.setApplyToken(mBbqApplyToken); Surface blastSurface; if (addSchandleToVriSurface()) { blastSurface = mBlastBufferQueue.createSurfaceWithHandle(); @@ -3209,10 +3214,10 @@ public final class ViewRootImpl implements ViewParent, typesToShow |= Type.navigationBars(); } if (captionIsHiddenByFlags && !captionWasHiddenByFlags - && enableCaptionCompatInsetForceConsumption()) { + && ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isEnabled()) { typesToHide |= Type.captionBar(); } else if (!captionIsHiddenByFlags && captionWasHiddenByFlags - && enableCaptionCompatInsetForceConsumption()) { + && ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isEnabled()) { typesToShow |= Type.captionBar(); } if (typesToHide != 0) { diff --git a/core/java/android/view/inputmethod/ImeTracker.java b/core/java/android/view/inputmethod/ImeTracker.java index b9751c8cab52..d90455ab971d 100644 --- a/core/java/android/view/inputmethod/ImeTracker.java +++ b/core/java/android/view/inputmethod/ImeTracker.java @@ -920,7 +920,8 @@ public interface ImeTracker { final Configuration.Builder builder = Configuration.Builder.withSurface( cujType, jankContext.getDisplayContext(), - jankContext.getTargetSurfaceControl()) + jankContext.getTargetSurfaceControl(), + jankContext.getDisplayContext().getMainThreadHandler()) .setTag(String.format(Locale.US, "%d@%d@%s", animType, useSeparatedThread ? 0 : 1, jankContext.getHostPackageName())); InteractionJankMonitor.getInstance().begin(builder); diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index e1154ca0701c..06820cd4c2ce 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -1003,6 +1003,55 @@ public class RemoteViews implements Parcelable, Filter { public int getActionTag() { return SET_EMPTY_VIEW_ACTION_TAG; } + + @Override + public boolean canWriteToProto() { + return true; + } + + @Override + public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) { + final long token = out.start(RemoteViewsProto.Action.SET_EMPTY_VIEW_ACTION); + out.write(RemoteViewsProto.SetEmptyViewAction.VIEW_ID, + appResources.getResourceName(mViewId)); + out.write(RemoteViewsProto.SetEmptyViewAction.EMPTY_VIEW_ID, + appResources.getResourceName(mViewId)); + out.end(token); + } + + public static PendingResources<Action> createFromProto(ProtoInputStream in) + throws Exception { + final LongSparseArray<Object> values = new LongSparseArray<>(); + + final long token = in.start(RemoteViewsProto.Action.SET_EMPTY_VIEW_ACTION); + while (in.nextField() != NO_MORE_FIELDS) { + switch (in.getFieldNumber()) { + case (int) RemoteViewsProto.SetEmptyViewAction.VIEW_ID: + values.put(RemoteViewsProto.SetEmptyViewAction.VIEW_ID, + in.readString(RemoteViewsProto.SetEmptyViewAction.VIEW_ID)); + break; + case (int) RemoteViewsProto.SetEmptyViewAction.EMPTY_VIEW_ID: + values.put(RemoteViewsProto.SetEmptyViewAction.EMPTY_VIEW_ID, + in.readString(RemoteViewsProto.SetEmptyViewAction.EMPTY_VIEW_ID)); + break; + default: + Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n" + + ProtoUtils.currentFieldToString(in)); + } + } + in.end(token); + + checkContainsKeys(values, new long[]{RemoteViewsProto.SetEmptyViewAction.VIEW_ID, + RemoteViewsProto.SetEmptyViewAction.EMPTY_VIEW_ID}); + + return (context, resources, rootData, depth) -> { + int viewId = getAsIdentifier(resources, values, + RemoteViewsProto.SetEmptyViewAction.VIEW_ID); + int emptyViewId = getAsIdentifier(resources, values, + RemoteViewsProto.SetEmptyViewAction.EMPTY_VIEW_ID); + return new SetEmptyView(viewId, emptyViewId); + }; + } } private static class SetPendingIntentTemplate extends Action { @@ -1243,6 +1292,68 @@ public class RemoteViews implements Parcelable, Filter { mItems.visitUris(visitor); } + + @Override + public boolean canWriteToProto() { + // Skip actions that do not contain items (intent only actions) + return mItems != null; + } + + @Override + public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) { + if (mItems == null) return; + final long token = out.start( + RemoteViewsProto.Action.SET_REMOTE_COLLECTION_ITEM_LIST_ADAPTER_ACTION); + out.write(RemoteViewsProto.SetRemoteCollectionItemListAdapterAction.VIEW_ID, + appResources.getResourceName(mViewId)); + final long itemsToken = out.start( + RemoteViewsProto.SetRemoteCollectionItemListAdapterAction.ITEMS); + mItems.writeToProto(context, out, /* attached= */ true); + out.end(itemsToken); + out.end(token); + } + } + + private PendingResources<Action> createSetRemoteCollectionItemListAdapterActionFromProto( + ProtoInputStream in) throws Exception { + final LongSparseArray<Object> values = new LongSparseArray<>(); + + final long token = in.start( + RemoteViewsProto.Action.SET_REMOTE_COLLECTION_ITEM_LIST_ADAPTER_ACTION); + while (in.nextField() != NO_MORE_FIELDS) { + switch (in.getFieldNumber()) { + case (int) RemoteViewsProto.SetRemoteCollectionItemListAdapterAction.VIEW_ID: + values.put(RemoteViewsProto.SetRemoteCollectionItemListAdapterAction.VIEW_ID, + in.readString( + RemoteViewsProto + .SetRemoteCollectionItemListAdapterAction.VIEW_ID)); + break; + case (int) RemoteViewsProto.SetRemoteCollectionItemListAdapterAction.ITEMS: + final long itemsToken = in.start( + RemoteViewsProto.SetRemoteCollectionItemListAdapterAction.ITEMS); + values.put(RemoteViewsProto.SetRemoteCollectionItemListAdapterAction.ITEMS, + RemoteCollectionItems.createFromProto(in)); + in.end(itemsToken); + break; + default: + Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n" + + ProtoUtils.currentFieldToString(in)); + } + } + in.end(token); + + checkContainsKeys(values, + new long[]{RemoteViewsProto.SetRemoteCollectionItemListAdapterAction.VIEW_ID, + RemoteViewsProto.SetRemoteCollectionItemListAdapterAction.ITEMS}); + + return (context, resources, rootData, depth) -> { + int viewId = getAsIdentifier(resources, values, + RemoteViewsProto.SetRemoteCollectionItemListAdapterAction.VIEW_ID); + return new SetRemoteCollectionItemListAdapterAction(viewId, + ((PendingResources<RemoteCollectionItems>) values.get( + RemoteViewsProto.SetRemoteCollectionItemListAdapterAction.ITEMS)) + .create(context, resources, rootData, depth)); + }; } /** @@ -2036,6 +2147,68 @@ public class RemoteViews implements Parcelable, Filter { public int getActionTag() { return SET_DRAWABLE_TINT_TAG; } + + @Override + public boolean canWriteToProto() { + return true; + } + + @Override + public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) { + final long token = out.start(RemoteViewsProto.Action.SET_DRAWABLE_TINT_ACTION); + out.write(RemoteViewsProto.SetDrawableTintAction.VIEW_ID, + appResources.getResourceName(mViewId)); + out.write(RemoteViewsProto.SetDrawableTintAction.COLOR_FILTER, mColorFilter); + out.write(RemoteViewsProto.SetDrawableTintAction.FILTER_MODE, + PorterDuff.modeToInt(mFilterMode)); + out.write(RemoteViewsProto.SetDrawableTintAction.TARGET_BACKGROUND, mTargetBackground); + out.end(token); + } + + public static PendingResources<Action> createFromProto(ProtoInputStream in) + throws Exception { + final LongSparseArray<Object> values = new LongSparseArray<>(); + + final long token = in.start(RemoteViewsProto.Action.SET_DRAWABLE_TINT_ACTION); + while (in.nextField() != NO_MORE_FIELDS) { + switch (in.getFieldNumber()) { + case (int) RemoteViewsProto.SetDrawableTintAction.VIEW_ID: + values.put(RemoteViewsProto.SetDrawableTintAction.VIEW_ID, + in.readString(RemoteViewsProto.SetDrawableTintAction.VIEW_ID)); + break; + case (int) RemoteViewsProto.SetDrawableTintAction.TARGET_BACKGROUND: + values.put(RemoteViewsProto.SetDrawableTintAction.TARGET_BACKGROUND, + in.readBoolean( + RemoteViewsProto.SetDrawableTintAction.TARGET_BACKGROUND)); + break; + case (int) RemoteViewsProto.SetDrawableTintAction.COLOR_FILTER: + values.put(RemoteViewsProto.SetDrawableTintAction.COLOR_FILTER, + in.readInt(RemoteViewsProto.SetDrawableTintAction.COLOR_FILTER)); + break; + case (int) RemoteViewsProto.SetDrawableTintAction.FILTER_MODE: + values.put(RemoteViewsProto.SetDrawableTintAction.FILTER_MODE, + PorterDuff.intToMode(in.readInt( + RemoteViewsProto.SetDrawableTintAction.FILTER_MODE))); + break; + default: + Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n" + + ProtoUtils.currentFieldToString(in)); + } + } + in.end(token); + + checkContainsKeys(values, new long[]{RemoteViewsProto.SetDrawableTintAction.VIEW_ID}); + + return (context, resources, rootData, depth) -> { + int viewId = getAsIdentifier(resources, values, + RemoteViewsProto.SetDrawableTintAction.VIEW_ID); + return new SetDrawableTint(viewId, (boolean) values.get( + RemoteViewsProto.SetDrawableTintAction.TARGET_BACKGROUND, false), + (int) values.get(RemoteViewsProto.SetDrawableTintAction.COLOR_FILTER, 0), + (PorterDuff.Mode) values.get( + RemoteViewsProto.SetDrawableTintAction.FILTER_MODE)); + }; + } } /** @@ -2047,7 +2220,7 @@ public class RemoteViews implements Parcelable, Filter { * target {@link View#getBackground()}. * <p> */ - private class SetRippleDrawableColor extends Action { + private static class SetRippleDrawableColor extends Action { ColorStateList mColorStateList; SetRippleDrawableColor(@IdRes int id, ColorStateList colorStateList) { @@ -2082,6 +2255,58 @@ public class RemoteViews implements Parcelable, Filter { public int getActionTag() { return SET_RIPPLE_DRAWABLE_COLOR_TAG; } + + @Override + public boolean canWriteToProto() { + return true; + } + + @Override + public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) { + final long token = out.start(RemoteViewsProto.Action.SET_RIPPLE_DRAWABLE_COLOR_ACTION); + out.write(RemoteViewsProto.SetRippleDrawableColorAction.VIEW_ID, + appResources.getResourceName(mViewId)); + writeColorStateListToProto(out, mColorStateList, + RemoteViewsProto.SetRippleDrawableColorAction.COLOR_STATE_LIST); + out.end(token); + } + + public static PendingResources<Action> createFromProto(ProtoInputStream in) + throws Exception { + final LongSparseArray<Object> values = new LongSparseArray<>(); + + final long token = in.start(RemoteViewsProto.Action.SET_RIPPLE_DRAWABLE_COLOR_ACTION); + while (in.nextField() != NO_MORE_FIELDS) { + switch (in.getFieldNumber()) { + case (int) RemoteViewsProto.SetRippleDrawableColorAction.VIEW_ID: + values.put(RemoteViewsProto.SetRippleDrawableColorAction.VIEW_ID, + in.readString( + RemoteViewsProto.SetRippleDrawableColorAction.VIEW_ID)); + break; + case (int) RemoteViewsProto.SetRippleDrawableColorAction.COLOR_STATE_LIST: + values.put(RemoteViewsProto.SetRippleDrawableColorAction.COLOR_STATE_LIST, + createColorStateListFromProto(in, + RemoteViewsProto + .SetRippleDrawableColorAction.COLOR_STATE_LIST)); + break; + default: + Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n" + + ProtoUtils.currentFieldToString(in)); + } + } + in.end(token); + + checkContainsKeys(values, + new long[]{RemoteViewsProto.SetRippleDrawableColorAction.VIEW_ID, + RemoteViewsProto.SetRippleDrawableColorAction.COLOR_STATE_LIST}); + + return (context, resources, rootData, depth) -> { + int viewId = getAsIdentifier(resources, values, + RemoteViewsProto.SetRippleDrawableColorAction.VIEW_ID); + return new SetRippleDrawableColor(viewId, (ColorStateList) values.get( + RemoteViewsProto.SetRippleDrawableColorAction.COLOR_STATE_LIST)); + }; + } } /** @@ -2987,6 +3212,82 @@ public class RemoteViews implements Parcelable, Filter { public int getActionTag() { return RESOURCE_REFLECTION_ACTION_TAG; } + + @Override + public boolean canWriteToProto() { + return true; + } + + @Override + public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) { + final long token = out.start(RemoteViewsProto.Action.RESOURCE_REFLECTION_ACTION); + out.write(RemoteViewsProto.ResourceReflectionAction.VIEW_ID, + appResources.getResourceName(mViewId)); + out.write(RemoteViewsProto.ResourceReflectionAction.METHOD_NAME, mMethodName); + out.write(RemoteViewsProto.ResourceReflectionAction.PARAMETER_TYPE, mType); + out.write(RemoteViewsProto.ResourceReflectionAction.RESOURCE_TYPE, mResourceType); + if (mResId != 0) { + out.write(RemoteViewsProto.ResourceReflectionAction.RES_ID, + appResources.getResourceName(mResId)); + } + out.end(token); + } + + public static PendingResources<Action> createFromProto(ProtoInputStream in) + throws Exception { + final LongSparseArray<Object> values = new LongSparseArray<>(); + + final long token = in.start(RemoteViewsProto.Action.RESOURCE_REFLECTION_ACTION); + while (in.nextField() != NO_MORE_FIELDS) { + switch (in.getFieldNumber()) { + case (int) RemoteViewsProto.ResourceReflectionAction.VIEW_ID: + values.put(RemoteViewsProto.ResourceReflectionAction.VIEW_ID, + in.readString(RemoteViewsProto.ResourceReflectionAction.VIEW_ID)); + break; + case (int) RemoteViewsProto.ResourceReflectionAction.METHOD_NAME: + values.put(RemoteViewsProto.ResourceReflectionAction.METHOD_NAME, + in.readString( + RemoteViewsProto.ResourceReflectionAction.METHOD_NAME)); + break; + case (int) RemoteViewsProto.ResourceReflectionAction.RESOURCE_TYPE: + values.put(RemoteViewsProto.ResourceReflectionAction.RESOURCE_TYPE, + in.readInt( + RemoteViewsProto.ResourceReflectionAction.RESOURCE_TYPE)); + break; + case (int) RemoteViewsProto.ResourceReflectionAction.RES_ID: + values.put(RemoteViewsProto.ResourceReflectionAction.RES_ID, + in.readString(RemoteViewsProto.ResourceReflectionAction.RES_ID)); + break; + case (int) RemoteViewsProto.ResourceReflectionAction.PARAMETER_TYPE: + values.put(RemoteViewsProto.ResourceReflectionAction.PARAMETER_TYPE, + in.readInt( + RemoteViewsProto.ResourceReflectionAction.PARAMETER_TYPE)); + break; + default: + Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n" + + ProtoUtils.currentFieldToString(in)); + } + } + in.end(token); + + checkContainsKeys(values, new long[]{RemoteViewsProto.ResourceReflectionAction.VIEW_ID, + RemoteViewsProto.ResourceReflectionAction.METHOD_NAME, + RemoteViewsProto.ResourceReflectionAction.PARAMETER_TYPE}); + + return (context, resources, rootData, depth) -> { + int viewId = getAsIdentifier(resources, values, + RemoteViewsProto.ResourceReflectionAction.VIEW_ID); + + int resId = (values.indexOfKey(RemoteViewsProto.ResourceReflectionAction.RES_ID) + >= 0) ? getAsIdentifier(resources, values, + RemoteViewsProto.ResourceReflectionAction.RES_ID) : 0; + return new ResourceReflectionAction(viewId, + (String) values.get(RemoteViewsProto.ResourceReflectionAction.METHOD_NAME), + (int) values.get(RemoteViewsProto.ResourceReflectionAction.PARAMETER_TYPE), + (int) values.get(RemoteViewsProto.ResourceReflectionAction.RESOURCE_TYPE, + 0), resId); + }; + } } private static final class AttributeReflectionAction extends BaseReflectionAction { @@ -4593,6 +4894,61 @@ public class RemoteViews implements Parcelable, Filter { public int getActionTag() { return SET_INT_TAG_TAG; } + + @Override + public boolean canWriteToProto() { + return true; + } + + @Override + public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) { + final long token = out.start(RemoteViewsProto.Action.SET_INT_TAG_ACTION); + out.write(RemoteViewsProto.SetIntTagAction.VIEW_ID, + appResources.getResourceName(mViewId)); + out.write(RemoteViewsProto.SetIntTagAction.KEY, + appResources.getResourceName(mKey)); // rebase + out.write(RemoteViewsProto.SetIntTagAction.TAG, mTag); + out.end(token); + } + + public static PendingResources<Action> createFromProto(ProtoInputStream in) + throws Exception { + final LongSparseArray<Object> values = new LongSparseArray<>(); + + final long token = in.start(RemoteViewsProto.Action.SET_INT_TAG_ACTION); + while (in.nextField() != NO_MORE_FIELDS) { + switch (in.getFieldNumber()) { + case (int) RemoteViewsProto.SetIntTagAction.VIEW_ID: + values.put(RemoteViewsProto.SetIntTagAction.VIEW_ID, + in.readString(RemoteViewsProto.SetIntTagAction.VIEW_ID)); + break; + case (int) RemoteViewsProto.SetIntTagAction.KEY: + values.put(RemoteViewsProto.SetIntTagAction.KEY, + in.readString(RemoteViewsProto.SetIntTagAction.KEY)); + break; + case (int) RemoteViewsProto.SetIntTagAction.TAG: + values.put(RemoteViewsProto.SetIntTagAction.TAG, + in.readInt(RemoteViewsProto.SetIntTagAction.TAG)); + break; + default: + Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n" + + ProtoUtils.currentFieldToString(in)); + } + } + in.end(token); + + checkContainsKeys(values, new long[]{RemoteViewsProto.SetIntTagAction.VIEW_ID, + RemoteViewsProto.SetIntTagAction.KEY}); + + return (context, resources, rootData, depth) -> { + int viewId = getAsIdentifier(resources, values, + RemoteViewsProto.SetIntTagAction.VIEW_ID); + int keyId = getAsIdentifier(resources, values, + RemoteViewsProto.SetIntTagAction.KEY); + return new SetIntTagAction(viewId, keyId, + (int) values.get(RemoteViewsProto.SetIntTagAction.TAG, 0)); + }; + } } private static class SetCompoundButtonCheckedAction extends Action { @@ -4643,6 +4999,56 @@ public class RemoteViews implements Parcelable, Filter { public int getActionTag() { return SET_COMPOUND_BUTTON_CHECKED_TAG; } + + @Override + public boolean canWriteToProto() { + return true; + } + + @Override + public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) { + final long token = out.start( + RemoteViewsProto.Action.SET_COMPOUND_BUTTON_CHECKED_ACTION); + out.write(RemoteViewsProto.SetCompoundButtonCheckedAction.VIEW_ID, + appResources.getResourceName(mViewId)); + out.write(RemoteViewsProto.SetCompoundButtonCheckedAction.CHECKED, mChecked); + out.end(token); + } + + public static PendingResources<Action> createFromProto(ProtoInputStream in) + throws Exception { + final LongSparseArray<Object> values = new LongSparseArray<>(); + + final long token = in.start(RemoteViewsProto.Action.SET_COMPOUND_BUTTON_CHECKED_ACTION); + while (in.nextField() != NO_MORE_FIELDS) { + switch (in.getFieldNumber()) { + case (int) RemoteViewsProto.SetCompoundButtonCheckedAction.VIEW_ID: + values.put(RemoteViewsProto.SetCompoundButtonCheckedAction.VIEW_ID, + in.readString( + RemoteViewsProto.SetCompoundButtonCheckedAction.VIEW_ID)); + break; + case (int) RemoteViewsProto.SetCompoundButtonCheckedAction.CHECKED: + values.put(RemoteViewsProto.SetCompoundButtonCheckedAction.CHECKED, + in.readBoolean( + RemoteViewsProto.SetCompoundButtonCheckedAction.CHECKED)); + break; + default: + Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n" + + ProtoUtils.currentFieldToString(in)); + } + } + in.end(token); + + checkContainsKeys(values, + new long[]{RemoteViewsProto.SetCompoundButtonCheckedAction.VIEW_ID}); + + return (context, resources, rootData, depth) -> { + int viewId = getAsIdentifier(resources, values, + RemoteViewsProto.SetCompoundButtonCheckedAction.VIEW_ID); + return new SetCompoundButtonCheckedAction(viewId, (boolean) values.get( + RemoteViewsProto.SetCompoundButtonCheckedAction.CHECKED, false)); + }; + } } private static class SetRadioGroupCheckedAction extends Action { @@ -4707,6 +5113,61 @@ public class RemoteViews implements Parcelable, Filter { public int getActionTag() { return SET_RADIO_GROUP_CHECKED; } + + @Override + public boolean canWriteToProto() { + return true; + } + + @Override + public void writeToProto(ProtoOutputStream out, Context context, Resources appResources) { + final long token = out.start(RemoteViewsProto.Action.SET_RADIO_GROUP_CHECKED_ACTION); + out.write(RemoteViewsProto.SetRadioGroupCheckedAction.VIEW_ID, + appResources.getResourceName(mViewId)); + if (mCheckedId != -1) { + out.write(RemoteViewsProto.SetRadioGroupCheckedAction.CHECKED_ID, + appResources.getResourceName(mCheckedId)); + } + out.end(token); + } + + public static PendingResources<Action> createFromProto(ProtoInputStream in) + throws Exception { + final LongSparseArray<Object> values = new LongSparseArray<>(); + + final long token = in.start(RemoteViewsProto.Action.SET_RADIO_GROUP_CHECKED_ACTION); + while (in.nextField() != NO_MORE_FIELDS) { + switch (in.getFieldNumber()) { + case (int) RemoteViewsProto.SetRadioGroupCheckedAction.VIEW_ID: + values.put(RemoteViewsProto.SetRadioGroupCheckedAction.VIEW_ID, + in.readString(RemoteViewsProto.SetRadioGroupCheckedAction.VIEW_ID)); + break; + case (int) RemoteViewsProto.SetRadioGroupCheckedAction.CHECKED_ID: + values.put(RemoteViewsProto.SetRadioGroupCheckedAction.CHECKED_ID, + in.readString( + RemoteViewsProto.SetRadioGroupCheckedAction.CHECKED_ID)); + break; + default: + Log.w(LOG_TAG, "Unhandled field while reading RemoteViews proto!\n" + + ProtoUtils.currentFieldToString(in)); + } + } + in.end(token); + + checkContainsKeys(values, + new long[]{RemoteViewsProto.SetRadioGroupCheckedAction.VIEW_ID}); + + return (context, resources, rootData, depth) -> { + int viewId = getAsIdentifier(resources, values, + RemoteViewsProto.SetRadioGroupCheckedAction.VIEW_ID); + + int checkedId = (values.indexOfKey( + RemoteViewsProto.SetRadioGroupCheckedAction.CHECKED_ID) >= 0) + ? getAsIdentifier(resources, values, + RemoteViewsProto.SetRadioGroupCheckedAction.CHECKED_ID) : -1; + return new SetRadioGroupCheckedAction(viewId, checkedId); + }; + } } private static class SetViewOutlinePreferredRadiusAction extends Action { @@ -8450,6 +8911,7 @@ public class RemoteViews implements Parcelable, Filter { public static PendingResources<RemoteCollectionItems> createFromProto(ProtoInputStream in) throws Exception { final LongSparseArray<Object> values = new LongSparseArray<>(); + values.put(RemoteViewsProto.RemoteCollectionItems.IDS, new ArrayList<Long>()); values.put(RemoteViewsProto.RemoteCollectionItems.VIEWS, new ArrayList<PendingResources<RemoteViews>>()); @@ -9207,6 +9669,22 @@ public class RemoteViews implements Parcelable, Filter { return ReflectionAction.createFromProto(in); case (int) RemoteViewsProto.Action.REMOVE_FROM_PARENT_ACTION: return RemoveFromParentAction.createFromProto(in); + case (int) RemoteViewsProto.Action.RESOURCE_REFLECTION_ACTION: + return ResourceReflectionAction.createFromProto(in); + case (int) RemoteViewsProto.Action.SET_COMPOUND_BUTTON_CHECKED_ACTION: + return SetCompoundButtonCheckedAction.createFromProto(in); + case (int) RemoteViewsProto.Action.SET_DRAWABLE_TINT_ACTION: + return SetDrawableTint.createFromProto(in); + case (int) RemoteViewsProto.Action.SET_EMPTY_VIEW_ACTION: + return SetEmptyView.createFromProto(in); + case (int) RemoteViewsProto.Action.SET_INT_TAG_ACTION: + return SetIntTagAction.createFromProto(in); + case (int) RemoteViewsProto.Action.SET_RADIO_GROUP_CHECKED_ACTION: + return SetRadioGroupCheckedAction.createFromProto(in); + case (int) RemoteViewsProto.Action.SET_REMOTE_COLLECTION_ITEM_LIST_ADAPTER_ACTION: + return rv.createSetRemoteCollectionItemListAdapterActionFromProto(in); + case (int) RemoteViewsProto.Action.SET_RIPPLE_DRAWABLE_COLOR_ACTION: + return SetRippleDrawableColor.createFromProto(in); default: throw new RuntimeException("Unhandled field while reading Action proto!\n" + ProtoUtils.currentFieldToString(in)); diff --git a/core/java/android/window/flags/DesktopModeFlags.java b/core/java/android/window/flags/DesktopModeFlags.java index 5c53d66e49fe..701b6be06e72 100644 --- a/core/java/android/window/flags/DesktopModeFlags.java +++ b/core/java/android/window/flags/DesktopModeFlags.java @@ -17,7 +17,9 @@ package android.window.flags; import android.annotation.Nullable; -import android.content.Context; +import android.app.ActivityThread; +import android.app.Application; +import android.content.ContentResolver; import android.provider.Settings; import android.util.Log; @@ -39,9 +41,13 @@ import java.util.function.Supplier; */ public enum DesktopModeFlags { // All desktop mode related flags to be overridden by developer option toggle will be added here - DESKTOP_WINDOWING_MODE( + ENABLE_DESKTOP_WINDOWING_MODE( Flags::enableDesktopWindowingMode, /* shouldOverrideByDevOption= */ true), - DYNAMIC_INITIAL_BOUNDS(Flags::enableWindowingDynamicInitialBounds, false); + ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS(Flags::enableWindowingDynamicInitialBounds, false), + ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION( + Flags::enableCaptionCompatInsetForceConsumption, true), + ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS( + Flags::enableCaptionCompatInsetForceConsumptionAlways, true); private static final String TAG = "DesktopModeFlagsUtil"; // Function called to obtain aconfig flag value. @@ -62,14 +68,15 @@ public enum DesktopModeFlags { * Determines state of flag based on the actual flag and desktop mode developer option * overrides. */ - public boolean isEnabled(Context context) { + public boolean isEnabled() { + Application application = ActivityThread.currentApplication(); if (!Flags.showDesktopWindowingDevOption() || !mShouldOverrideByDevOption - || context.getContentResolver() == null) { + || application == null) { return mFlagFunction.get(); } else { boolean shouldToggleBeEnabledByDefault = Flags.enableDesktopWindowingMode(); - return switch (getToggleOverride(context)) { + return switch (getToggleOverride(application.getContentResolver())) { case OVERRIDE_UNSET -> mFlagFunction.get(); // When toggle override matches its default state, don't override flags. This // helps users reset their feature overrides. @@ -79,14 +86,14 @@ public enum DesktopModeFlags { } } - private ToggleOverride getToggleOverride(Context context) { + private ToggleOverride getToggleOverride(ContentResolver contentResolver) { // If cached, return it if (sCachedToggleOverride != null) { return sCachedToggleOverride; } // Otherwise, fetch and cache it - ToggleOverride override = getToggleOverrideFromSystem(context); + ToggleOverride override = getToggleOverrideFromSystem(contentResolver); sCachedToggleOverride = override; Log.d(TAG, "Toggle override initialized to: " + override); return override; @@ -95,9 +102,9 @@ public enum DesktopModeFlags { /** * Returns {@link ToggleOverride} from Settings.Global set by toggle. */ - private ToggleOverride getToggleOverrideFromSystem(Context context) { + private ToggleOverride getToggleOverrideFromSystem(ContentResolver contentResolver) { int settingValue = Settings.Global.getInt( - context.getContentResolver(), + contentResolver, Settings.Global.DEVELOPMENT_OVERRIDE_DESKTOP_MODE_FEATURES, ToggleOverride.OVERRIDE_UNSET.getSetting() ); diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig index fc3f5ab9a9b3..cc5e583034a5 100644 --- a/core/java/android/window/flags/lse_desktop_experience.aconfig +++ b/core/java/android/window/flags/lse_desktop_experience.aconfig @@ -117,6 +117,13 @@ flag { } flag { + name: "enable_tile_resizing" + namespace: "lse_desktop_experience" + description: "Enables drawing a divider bar upon tiling tasks left and right in desktop mode for simultaneous resizing" + bug: "351769839" +} + +flag { name: "respect_orientation_change_for_unresizeable" namespace: "lse_desktop_experience" description: "Whether to resize task to respect requested orientation change of unresizeable activity" @@ -253,6 +260,16 @@ flag { } flag { + name: "enable_hold_to_drag_app_handle" + namespace: "lse_desktop_experience" + description: "Requires hold-to-drag the App Handle when using touchscreen input" + bug: "356409496" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "skip_compat_ui_education_in_desktop_mode" namespace: "lse_desktop_experience" description: "Ignore Compat UI educations when in Desktop Mode." @@ -275,3 +292,10 @@ flag { description: "Creates a shell transition when display focus switches." bug: "356109871" } + +flag { + name: "enter_desktop_by_default_on_freeform_displays" + namespace: "lse_desktop_experience" + description: "Allow entering desktop mode by default on freeform displays" + bug: "361419732" +} diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java index c7e1fba66d7f..ef08e49ce6d9 100644 --- a/core/java/com/android/internal/jank/InteractionJankMonitor.java +++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java @@ -330,9 +330,10 @@ public class InteractionJankMonitor { * @param cujType the specific {@link Cuj.CujType}. * @return boolean true if the tracker is started successfully, false otherwise. */ - public boolean begin(SurfaceControl surface, Context context, @Cuj.CujType int cujType) { + public boolean begin(SurfaceControl surface, Context context, Handler handler, + @Cuj.CujType int cujType) { try { - return begin(Configuration.Builder.withSurface(cujType, context, surface)); + return begin(Configuration.Builder.withSurface(cujType, context, surface, handler)); } catch (IllegalArgumentException ex) { Log.d(TAG, "Build configuration failed!", ex); return false; @@ -348,11 +349,12 @@ public class InteractionJankMonitor { * @param tag a tag containing extra information about the interaction. * @return boolean true if the tracker is started successfully, false otherwise. */ - public boolean begin(SurfaceControl surface, Context context, @Cuj.CujType int cujType, + public boolean begin(SurfaceControl surface, Context context, Handler handler, + @Cuj.CujType int cujType, String tag) { try { final Configuration.Builder builder = - Configuration.Builder.withSurface(cujType, context, surface); + Configuration.Builder.withSurface(cujType, context, surface, handler); if (!TextUtils.isEmpty(tag)) { builder.setTag(tag); } @@ -689,20 +691,23 @@ public class InteractionJankMonitor { private SurfaceControl mAttrSurfaceControl; private final @Cuj.CujType int mAttrCujType; private boolean mAttrDeferMonitor = true; + private Handler mHandler = null; /** * Creates a builder which instruments only surface. * @param cuj The enum defined in {@link Cuj.CujType}. * @param context context * @param surfaceControl surface control + * @param uiThreadHandler UI thread for that surface * @return builder */ public static Builder withSurface(@Cuj.CujType int cuj, @NonNull Context context, - @NonNull SurfaceControl surfaceControl) { + @NonNull SurfaceControl surfaceControl, @NonNull Handler uiThreadHandler) { return new Builder(cuj) .setContext(context) .setSurfaceControl(surfaceControl) - .setSurfaceOnly(true); + .setSurfaceOnly(true) + .setHandler(uiThreadHandler); } /** @@ -722,6 +727,18 @@ public class InteractionJankMonitor { } /** + * Specifies the UI thread handler. If not provided, the View's one will be used. + * If only a surface is provided without handler, the app main thread will be used. + * + * @param uiThreadHandler handler associated to the cuj UI thread + * @return builder + */ + public Builder setHandler(Handler uiThreadHandler) { + mHandler = uiThreadHandler; + return this; + } + + /** * Specifies a view, must be set if {@link #setSurfaceOnly(boolean)} is set to false. * @param view an attached view * @return builder @@ -798,13 +815,13 @@ public class InteractionJankMonitor { return new Configuration( mAttrCujType, mAttrView, mAttrTag, mAttrTimeout, mAttrSurfaceOnly, mAttrContext, mAttrSurfaceControl, - mAttrDeferMonitor); + mAttrDeferMonitor, mHandler); } } private Configuration(@Cuj.CujType int cuj, View view, @NonNull String tag, long timeout, boolean surfaceOnly, Context context, SurfaceControl surfaceControl, - boolean deferMonitor) { + boolean deferMonitor, Handler handler) { mCujType = cuj; mTag = tag; mSessionName = generateSessionName(Cuj.getNameOfCuj(cuj), tag); @@ -816,8 +833,16 @@ public class InteractionJankMonitor { : (view != null ? view.getContext().getApplicationContext() : null); mSurfaceControl = surfaceControl; mDeferMonitor = deferMonitor; + if (handler != null) { + mHandler = handler; + } else if (mSurfaceOnly) { + Log.w(TAG, "No UIThread provided for " + mSessionName + + " (surface only). Defaulting to app main thread."); + mHandler = mContext.getMainThreadHandler(); + } else { + mHandler = mView.getHandler(); + } validate(); - mHandler = mSurfaceOnly ? mContext.getMainThreadHandler() : mView.getHandler(); } @VisibleForTesting @@ -858,6 +883,12 @@ public class InteractionJankMonitor { shouldThrow = true; msg.append("Must pass in a valid surface control if only instrument surface; "); } + if (mHandler == null) { + shouldThrow = true; + msg.append( + "Must pass a UI thread handler when only a surface control is " + + "provided."); + } } else { if (!hasValidView()) { shouldThrow = true; diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 4708be8108c2..84dfc497dc84 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -38,6 +38,8 @@ import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATIO import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.flags.Flags.customizableWindowHeaders; +import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION; +import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS; import static com.android.internal.policy.PhoneWindow.FEATURE_OPTIONS_PANEL; @@ -114,7 +116,6 @@ import com.android.internal.view.menu.MenuHelper; import com.android.internal.widget.ActionBarContextView; import com.android.internal.widget.BackgroundFallback; import com.android.internal.widget.floatingtoolbar.FloatingToolbar; -import com.android.window.flags.Flags; import java.util.List; import java.util.concurrent.Executor; @@ -1217,14 +1218,15 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind final boolean hideCaptionBar = fullscreen || (requestedVisibleTypes & WindowInsets.Type.captionBar()) == 0; - final boolean consumingCaptionBar = Flags.enableCaptionCompatInsetForceConsumption() - && ((mLastForceConsumingTypes & WindowInsets.Type.captionBar()) != 0 + final boolean consumingCaptionBar = + ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isEnabled() + && ((mLastForceConsumingTypes & WindowInsets.Type.captionBar()) != 0 && hideCaptionBar); final boolean isOpaqueCaptionBar = customizableWindowHeaders() && (appearance & APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND) == 0; final boolean consumingOpaqueCaptionBar = - Flags.enableCaptionCompatInsetForceConsumptionAlways() + ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS.isEnabled() && mLastForceConsumingOpaqueCaptionBar && isOpaqueCaptionBar; diff --git a/core/java/com/android/internal/policy/ScreenDecorationsUtils.java b/core/java/com/android/internal/policy/ScreenDecorationsUtils.java index 067e5e8813a7..b23515aa51f3 100644 --- a/core/java/com/android/internal/policy/ScreenDecorationsUtils.java +++ b/core/java/com/android/internal/policy/ScreenDecorationsUtils.java @@ -37,6 +37,8 @@ public class ScreenDecorationsUtils { * * Note that if the context is not an UI context(not associated with Display), it will use * default display. + * + * If the associated display is not internal, will return 0. */ public static float getWindowCornerRadius(Context context) { final Resources resources = context.getResources(); @@ -44,7 +46,13 @@ public class ScreenDecorationsUtils { return 0f; } // Use Context#getDisplayNoVerify() in case the context is not an UI context. - final String displayUniqueId = context.getDisplayNoVerify().getUniqueId(); + final Display display = context.getDisplayNoVerify(); + // The radius is only valid for internal displays, since the corner radius of external or + // virtual displays is not known when window corners are configured or are not supported. + if (display.getType() != Display.TYPE_INTERNAL) { + return 0f; + } + final String displayUniqueId = display.getUniqueId(); // Radius that should be used in case top or bottom aren't defined. float defaultRadius = RoundedCorners.getRoundedCornerRadius(resources, displayUniqueId) - RoundedCorners.getRoundedCornerRadiusAdjustment(resources, displayUniqueId); diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java index e440dc9053fd..4db9ddf128da 100644 --- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java +++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java @@ -223,17 +223,17 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto "ServiceManager returned a null ProtoLog Configuration Service"); try { - var args = new ProtoLogConfigurationService.RegisterClientArgs(); + var args = new ProtoLogConfigurationServiceImpl.RegisterClientArgs(); if (viewerConfigFilePath != null) { args.setViewerConfigFile(viewerConfigFilePath); } final var groupArgs = Stream.of(groups) - .map(group -> new ProtoLogConfigurationService.RegisterClientArgs + .map(group -> new ProtoLogConfigurationServiceImpl.RegisterClientArgs .GroupConfig(group.name(), group.isLogToLogcat())) - .toArray( - ProtoLogConfigurationService.RegisterClientArgs.GroupConfig[]::new); + .toArray(ProtoLogConfigurationServiceImpl + .RegisterClientArgs.GroupConfig[]::new); args.setGroups(groupArgs); mProtoLogConfigurationService.registerClient(this, args); diff --git a/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java b/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java index 7031d694f09c..d65aaae7deaa 100644 --- a/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java +++ b/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java @@ -16,434 +16,32 @@ package com.android.internal.protolog; -import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.GROUPS; -import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.ID; -import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.NAME; -import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.TAG; -import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MESSAGES; -import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.GROUP_ID; -import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.LEVEL; -import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.LOCATION; -import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE; -import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID; - import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemService; -import android.content.Context; -import android.os.RemoteException; -import android.os.ResultReceiver; -import android.os.ShellCallback; -import android.tracing.perfetto.DataSourceParams; -import android.tracing.perfetto.InitArguments; -import android.tracing.perfetto.Producer; -import android.util.Log; -import android.util.proto.ProtoInputStream; -import android.util.proto.ProtoOutputStream; - -import com.android.internal.annotations.VisibleForTesting; - -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -/** - * The ProtoLog service is responsible for orchestrating centralized actions of the protolog tracing - * system. Currently this service has the following roles: - * - Handle shell commands to toggle logging ProtoLog messages for specified groups to logcat. - * - Handle viewer config dumping (the mapping from message hash to message string) for all protolog - * clients. This is for two reasons: firstly, because client processes might be frozen so might - * not response to the request to dump their viewer config when the trace is stopped; secondly, - * multiple processes might be running the same code with the same viewer config, this centralized - * service ensures we don't dump the same viewer config multiple times across processes. - * <p> - * {@link com.android.internal.protolog.IProtoLogClient ProtoLog clients} register themselves to - * this service on initialization. - * <p> - * This service is intended to run on the system server, such that it never gets frozen. - */ -@SystemService(Context.PROTOLOG_CONFIGURATION_SERVICE) -public final class ProtoLogConfigurationService extends IProtoLogConfigurationService.Stub { - private static final String LOG_TAG = "ProtoLogConfigurationService"; - - private final ProtoLogDataSource mDataSource; - - /** - * Keeps track of how many of each viewer config file is currently registered. - * Use to keep track of which viewer config files are actively being used in tracing and might - * need to be dumped on flush. - */ - private final Map<String, Integer> mConfigFileCounts = new HashMap<>(); - /** - * Keeps track of the viewer config file of each client if available. - */ - private final Map<IProtoLogClient, String> mClientConfigFiles = new HashMap<>(); - - /** - * Keeps track of all the protolog groups that have been registered by clients and are still - * being actively traced. - */ - private final Set<String> mRegisteredGroups = new HashSet<>(); - /** - * Keeps track of all the clients that are actively tracing a given protolog group. - */ - private final Map<String, Set<IProtoLogClient>> mGroupToClients = new HashMap<>(); - - /** - * Keeps track of whether or not a given group should be logged to logcat. - * True when logging to logcat, false otherwise. - */ - private final Map<String, Boolean> mLogGroupToLogcatStatus = new TreeMap<>(); - - /** - * Keeps track of all the tracing instance ids that are actively running for ProtoLog. - */ - private final Set<Integer> mRunningInstances = new HashSet<>(); - - private final ViewerConfigFileTracer mViewerConfigFileTracer; - - public ProtoLogConfigurationService() { - this(ProtoLogDataSource::new, ProtoLogConfigurationService::dumpTransitionTraceConfig); - } - - @VisibleForTesting - public ProtoLogConfigurationService(@NonNull ProtoLogDataSourceBuilder dataSourceBuilder) { - this(dataSourceBuilder, ProtoLogConfigurationService::dumpTransitionTraceConfig); - } - - @VisibleForTesting - public ProtoLogConfigurationService(@NonNull ViewerConfigFileTracer tracer) { - this(ProtoLogDataSource::new, tracer); - } - - @VisibleForTesting - public ProtoLogConfigurationService( - @NonNull ProtoLogDataSourceBuilder dataSourceBuilder, - @NonNull ViewerConfigFileTracer tracer) { - mDataSource = dataSourceBuilder.build( - this::onTracingInstanceStart, - this::onTracingInstanceFlush, - this::onTracingInstanceStop - ); - - // Initialize the Perfetto producer and register the Perfetto ProtoLog datasource to be - // receive the lifecycle callbacks of the datasource and write the viewer configs if and - // when required to the datasource. - Producer.init(InitArguments.DEFAULTS); - final var params = new DataSourceParams.Builder() - .setBufferExhaustedPolicy(DataSourceParams.PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_DROP) - .build(); - mDataSource.register(params); - - mViewerConfigFileTracer = tracer; - } - - public static class RegisterClientArgs extends IRegisterClientArgs.Stub { - /** - * The viewer config file to be registered for this client ProtoLog process. - */ - @Nullable - private String mViewerConfigFile = null; - /** - * The list of all groups that this client protolog process supports and might trace. - */ - @NonNull - private String[] mGroups = new String[0]; - /** - * The default logcat status of the ProtoLog client. True is logging to logcat, false - * otherwise. The indices should match the indices in {@link mGroups}. - */ - @NonNull - private boolean[] mLogcatStatus = new boolean[0]; - - public record GroupConfig(@NonNull String group, boolean logToLogcat) {} - - /** - * Specify groups to register with this client that will be used for protologging in this - * process. - * @param groups to register with this client. - * @return self - */ - public RegisterClientArgs setGroups(GroupConfig... groups) { - mGroups = new String[groups.length]; - mLogcatStatus = new boolean[groups.length]; - - for (int i = 0; i < groups.length; i++) { - mGroups[i] = groups[i].group; - mLogcatStatus[i] = groups[i].logToLogcat; - } - - return this; - } - - /** - * Set the viewer config file that the logs in this process are using. - * @param viewerConfigFile The file path of the viewer config. - * @return self - */ - public RegisterClientArgs setViewerConfigFile(@NonNull String viewerConfigFile) { - mViewerConfigFile = viewerConfigFile; - - return this; - } - - @Override - @NonNull - public String[] getGroups() { - return mGroups; - } - - @Override - @NonNull - public boolean[] getGroupsDefaultLogcatStatus() { - return mLogcatStatus; - } - - @Nullable - @Override - public String getViewerConfigFile() { - return mViewerConfigFile; - } - } - - @FunctionalInterface - public interface ViewerConfigFileTracer { - /** - * Write the viewer config data to the trace buffer. - * - * @param dataSource The target datasource to write the viewer config to. - * @param viewerConfigFilePath The path of the viewer config file which contains the data we - * want to write to the trace buffer. - * @throws FileNotFoundException if the viewerConfigFilePath is invalid. - */ - void trace(@NonNull ProtoLogDataSource dataSource, @NonNull String viewerConfigFilePath); - } - - @Override - public void registerClient(@NonNull IProtoLogClient client, @NonNull IRegisterClientArgs args) - throws RemoteException { - client.asBinder().linkToDeath(() -> onClientBinderDeath(client), /* flags */ 0); - - final String viewerConfigFile = args.getViewerConfigFile(); - if (viewerConfigFile != null) { - registerViewerConfigFile(client, viewerConfigFile); - } - - registerGroups(client, args.getGroups(), args.getGroupsDefaultLogcatStatus()); - } - - @Override - public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out, - @Nullable FileDescriptor err, @NonNull String[] args, @Nullable ShellCallback callback, - @NonNull ResultReceiver resultReceiver) throws RemoteException { - new ProtoLogCommandHandler(this) - .exec(this, in, out, err, args, callback, resultReceiver); - } +public interface ProtoLogConfigurationService extends IProtoLogConfigurationService { /** * Get the list of groups clients have registered to the protolog service. * @return The list of ProtoLog groups registered with this service. */ @NonNull - public String[] getGroups() { - return mRegisteredGroups.toArray(new String[0]); - } + String[] getGroups(); + + /** + * Check if a group is logging to logcat + * @param group The group we want to check for + * @return True iff we are logging this group to logcat. + */ + boolean isLoggingToLogcat(@NonNull String group); /** * Enable logging target groups to logcat. * @param groups we want to enable logging them to logcat for. */ - public void enableProtoLogToLogcat(String... groups) { - toggleProtoLogToLogcat(true, groups); - } + void enableProtoLogToLogcat(@NonNull String... groups); /** * Disable logging target groups to logcat. * @param groups we want to disable from being logged to logcat. */ - public void disableProtoLogToLogcat(String... groups) { - toggleProtoLogToLogcat(false, groups); - } - - /** - * Check if a group is logging to logcat - * @param group The group we want to check for - * @return True iff we are logging this group to logcat. - */ - public boolean isLoggingToLogcat(@NonNull String group) { - final Boolean isLoggingToLogcat = mLogGroupToLogcatStatus.get(group); - - if (isLoggingToLogcat == null) { - throw new RuntimeException( - "Trying to get logcat logging status of non-registered group " + group); - } - - return isLoggingToLogcat; - } - - private void registerViewerConfigFile( - @NonNull IProtoLogClient client, @NonNull String viewerConfigFile) { - final var count = mConfigFileCounts.getOrDefault(viewerConfigFile, 0); - mConfigFileCounts.put(viewerConfigFile, count + 1); - mClientConfigFiles.put(client, viewerConfigFile); - } - - private void registerGroups(@NonNull IProtoLogClient client, @NonNull String[] groups, - @NonNull boolean[] logcatStatuses) throws RemoteException { - if (groups.length != logcatStatuses.length) { - throw new RuntimeException( - "Expected groups and logcatStatuses to have the same length, " - + "but groups has length " + groups.length - + " and logcatStatuses has length " + logcatStatuses.length); - } - - for (int i = 0; i < groups.length; i++) { - String group = groups[i]; - boolean logcatStatus = logcatStatuses[i]; - - mRegisteredGroups.add(group); - - mGroupToClients.putIfAbsent(group, new HashSet<>()); - mGroupToClients.get(group).add(client); - - if (!mLogGroupToLogcatStatus.containsKey(group)) { - mLogGroupToLogcatStatus.put(group, logcatStatus); - } - - boolean requestedLogToLogcat = mLogGroupToLogcatStatus.get(group); - if (requestedLogToLogcat != logcatStatus) { - client.toggleLogcat(requestedLogToLogcat, new String[] { group }); - } - } - } - - private void toggleProtoLogToLogcat(boolean enabled, @NonNull String[] groups) { - final var clientToGroups = new HashMap<IProtoLogClient, Set<String>>(); - - for (String group : groups) { - final var clients = mGroupToClients.get(group); - - if (clients == null) { - // No clients associated to this group - Log.w(LOG_TAG, "Attempting to toggle log to logcat for group " + group - + " with no registered clients."); - continue; - } - - for (IProtoLogClient client : clients) { - clientToGroups.putIfAbsent(client, new HashSet<>()); - clientToGroups.get(client).add(group); - } - } - - for (IProtoLogClient client : clientToGroups.keySet()) { - try { - client.toggleLogcat(enabled, clientToGroups.get(client).toArray(new String[0])); - } catch (RemoteException e) { - throw new RuntimeException( - "Failed to toggle logcat status for groups on client", e); - } - } - - for (String group : groups) { - mLogGroupToLogcatStatus.put(group, enabled); - } - } - - private void onTracingInstanceStart(int instanceIdx, ProtoLogDataSource.ProtoLogConfig config) { - mRunningInstances.add(instanceIdx); - } - - private void onTracingInstanceFlush() { - for (String fileName : mConfigFileCounts.keySet()) { - mViewerConfigFileTracer.trace(mDataSource, fileName); - } - } - - private void onTracingInstanceStop(int instanceIdx, ProtoLogDataSource.ProtoLogConfig config) { - mRunningInstances.remove(instanceIdx); - } - - private static void dumpTransitionTraceConfig(@NonNull ProtoLogDataSource dataSource, - @NonNull String viewerConfigFilePath) { - Utils.dumpViewerConfig(dataSource, () -> { - try { - return new ProtoInputStream(new FileInputStream(viewerConfigFilePath)); - } catch (FileNotFoundException e) { - throw new RuntimeException( - "Failed to load viewer config file " + viewerConfigFilePath, e); - } - }); - } - - private void onClientBinderDeath(@NonNull IProtoLogClient client) { - // Dump the tracing config now if no other client is going to dump the same config file. - String configFile = mClientConfigFiles.get(client); - if (configFile != null) { - final var newCount = mConfigFileCounts.get(configFile) - 1; - mConfigFileCounts.put(configFile, newCount); - boolean lastProcessWithViewerConfig = newCount == 0; - if (lastProcessWithViewerConfig) { - mViewerConfigFileTracer.trace(mDataSource, configFile); - } - } - } - - private static void writeViewerConfigGroup( - @NonNull ProtoInputStream pis, @NonNull ProtoOutputStream os) throws IOException { - final long inGroupToken = pis.start(GROUPS); - final long outGroupToken = os.start(GROUPS); - - while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) { - switch (pis.getFieldNumber()) { - case (int) ID -> { - int id = pis.readInt(ID); - os.write(ID, id); - } - case (int) NAME -> { - String name = pis.readString(NAME); - os.write(NAME, name); - } - case (int) TAG -> { - String tag = pis.readString(TAG); - os.write(TAG, tag); - } - default -> - throw new RuntimeException( - "Unexpected field id " + pis.getFieldNumber()); - } - } - - pis.end(inGroupToken); - os.end(outGroupToken); - } - - private static void writeViewerConfigMessage( - @NonNull ProtoInputStream pis, @NonNull ProtoOutputStream os) throws IOException { - final long inMessageToken = pis.start(MESSAGES); - final long outMessagesToken = os.start(MESSAGES); - - while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) { - switch (pis.getFieldNumber()) { - case (int) MESSAGE_ID -> os.write(MESSAGE_ID, - pis.readLong(MESSAGE_ID)); - case (int) MESSAGE -> os.write(MESSAGE, pis.readString(MESSAGE)); - case (int) LEVEL -> os.write(LEVEL, pis.readInt(LEVEL)); - case (int) GROUP_ID -> os.write(GROUP_ID, pis.readInt(GROUP_ID)); - case (int) LOCATION -> os.write(LOCATION, pis.readString(LOCATION)); - default -> - throw new RuntimeException( - "Unexpected field id " + pis.getFieldNumber()); - } - } - - pis.end(inMessageToken); - os.end(outMessagesToken); - } + void disableProtoLogToLogcat(@NonNull String... groups); } diff --git a/core/java/com/android/internal/protolog/ProtoLogConfigurationServiceImpl.java b/core/java/com/android/internal/protolog/ProtoLogConfigurationServiceImpl.java new file mode 100644 index 000000000000..e382ac1513e0 --- /dev/null +++ b/core/java/com/android/internal/protolog/ProtoLogConfigurationServiceImpl.java @@ -0,0 +1,454 @@ +/* + * 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.protolog; + +import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.GROUPS; +import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.ID; +import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.NAME; +import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.TAG; +import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MESSAGES; +import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.GROUP_ID; +import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.LEVEL; +import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.LOCATION; +import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE; +import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemService; +import android.content.Context; +import android.os.RemoteException; +import android.os.ResultReceiver; +import android.os.ShellCallback; +import android.tracing.perfetto.DataSourceParams; +import android.tracing.perfetto.InitArguments; +import android.tracing.perfetto.Producer; +import android.util.Log; +import android.util.proto.ProtoInputStream; +import android.util.proto.ProtoOutputStream; + +import com.android.internal.annotations.VisibleForTesting; + +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +/** + * The ProtoLog service is responsible for orchestrating centralized actions of the protolog tracing + * system. Currently this service has the following roles: + * - Handle shell commands to toggle logging ProtoLog messages for specified groups to logcat. + * - Handle viewer config dumping (the mapping from message hash to message string) for all protolog + * clients. This is for two reasons: firstly, because client processes might be frozen so might + * not response to the request to dump their viewer config when the trace is stopped; secondly, + * multiple processes might be running the same code with the same viewer config, this centralized + * service ensures we don't dump the same viewer config multiple times across processes. + * <p> + * {@link com.android.internal.protolog.IProtoLogClient ProtoLog clients} register themselves to + * this service on initialization. + * <p> + * This service is intended to run on the system server, such that it never gets frozen. + */ +@SystemService(Context.PROTOLOG_CONFIGURATION_SERVICE) +public class ProtoLogConfigurationServiceImpl extends IProtoLogConfigurationService.Stub + implements ProtoLogConfigurationService { + private static final String LOG_TAG = "ProtoLogConfigurationService"; + + private final ProtoLogDataSource mDataSource; + + /** + * Keeps track of how many of each viewer config file is currently registered. + * Use to keep track of which viewer config files are actively being used in tracing and might + * need to be dumped on flush. + */ + private final Map<String, Integer> mConfigFileCounts = new HashMap<>(); + /** + * Keeps track of the viewer config file of each client if available. + */ + private final Map<IProtoLogClient, String> mClientConfigFiles = new HashMap<>(); + + /** + * Keeps track of all the protolog groups that have been registered by clients and are still + * being actively traced. + */ + private final Set<String> mRegisteredGroups = new HashSet<>(); + /** + * Keeps track of all the clients that are actively tracing a given protolog group. + */ + private final Map<String, Set<IProtoLogClient>> mGroupToClients = new HashMap<>(); + + /** + * Keeps track of whether or not a given group should be logged to logcat. + * True when logging to logcat, false otherwise. + */ + private final Map<String, Boolean> mLogGroupToLogcatStatus = new TreeMap<>(); + + /** + * Keeps track of all the tracing instance ids that are actively running for ProtoLog. + */ + private final Set<Integer> mRunningInstances = new HashSet<>(); + + private final ViewerConfigFileTracer mViewerConfigFileTracer; + + public ProtoLogConfigurationServiceImpl() { + this(ProtoLogDataSource::new, ProtoLogConfigurationServiceImpl::dumpTransitionTraceConfig); + } + + @VisibleForTesting + public ProtoLogConfigurationServiceImpl(@NonNull ProtoLogDataSourceBuilder dataSourceBuilder) { + this(dataSourceBuilder, ProtoLogConfigurationServiceImpl::dumpTransitionTraceConfig); + } + + @VisibleForTesting + public ProtoLogConfigurationServiceImpl(@NonNull ViewerConfigFileTracer tracer) { + this(ProtoLogDataSource::new, tracer); + } + + @VisibleForTesting + public ProtoLogConfigurationServiceImpl( + @NonNull ProtoLogDataSourceBuilder dataSourceBuilder, + @NonNull ViewerConfigFileTracer tracer) { + mDataSource = dataSourceBuilder.build( + this::onTracingInstanceStart, + this::onTracingInstanceFlush, + this::onTracingInstanceStop + ); + + // Initialize the Perfetto producer and register the Perfetto ProtoLog datasource to be + // receive the lifecycle callbacks of the datasource and write the viewer configs if and + // when required to the datasource. + Producer.init(InitArguments.DEFAULTS); + final var params = new DataSourceParams.Builder() + .setBufferExhaustedPolicy(DataSourceParams.PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_DROP) + .build(); + mDataSource.register(params); + + mViewerConfigFileTracer = tracer; + } + + public static class RegisterClientArgs extends IRegisterClientArgs.Stub { + /** + * The viewer config file to be registered for this client ProtoLog process. + */ + @Nullable + private String mViewerConfigFile = null; + /** + * The list of all groups that this client protolog process supports and might trace. + */ + @NonNull + private String[] mGroups = new String[0]; + /** + * The default logcat status of the ProtoLog client. True is logging to logcat, false + * otherwise. The indices should match the indices in {@link mGroups}. + */ + @NonNull + private boolean[] mLogcatStatus = new boolean[0]; + + public record GroupConfig(@NonNull String group, boolean logToLogcat) {} + + /** + * Specify groups to register with this client that will be used for protologging in this + * process. + * @param groups to register with this client. + * @return self + */ + public RegisterClientArgs setGroups(GroupConfig... groups) { + mGroups = new String[groups.length]; + mLogcatStatus = new boolean[groups.length]; + + for (int i = 0; i < groups.length; i++) { + mGroups[i] = groups[i].group; + mLogcatStatus[i] = groups[i].logToLogcat; + } + + return this; + } + + /** + * Set the viewer config file that the logs in this process are using. + * @param viewerConfigFile The file path of the viewer config. + * @return self + */ + public RegisterClientArgs setViewerConfigFile(@NonNull String viewerConfigFile) { + mViewerConfigFile = viewerConfigFile; + + return this; + } + + @Override + @NonNull + public String[] getGroups() { + return mGroups; + } + + @Override + @NonNull + public boolean[] getGroupsDefaultLogcatStatus() { + return mLogcatStatus; + } + + @Nullable + @Override + public String getViewerConfigFile() { + return mViewerConfigFile; + } + } + + @FunctionalInterface + public interface ViewerConfigFileTracer { + /** + * Write the viewer config data to the trace buffer. + * + * @param dataSource The target datasource to write the viewer config to. + * @param viewerConfigFilePath The path of the viewer config file which contains the data we + * want to write to the trace buffer. + * @throws FileNotFoundException if the viewerConfigFilePath is invalid. + */ + void trace(@NonNull ProtoLogDataSource dataSource, @NonNull String viewerConfigFilePath); + } + + @Override + public void registerClient(@NonNull IProtoLogClient client, @NonNull IRegisterClientArgs args) + throws RemoteException { + client.asBinder().linkToDeath(() -> onClientBinderDeath(client), /* flags */ 0); + + final String viewerConfigFile = args.getViewerConfigFile(); + if (viewerConfigFile != null) { + registerViewerConfigFile(client, viewerConfigFile); + } + + registerGroups(client, args.getGroups(), args.getGroupsDefaultLogcatStatus()); + } + + @Override + public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out, + @Nullable FileDescriptor err, @NonNull String[] args, @Nullable ShellCallback callback, + @NonNull ResultReceiver resultReceiver) throws RemoteException { + new ProtoLogCommandHandler(this) + .exec(this, in, out, err, args, callback, resultReceiver); + } + + /** + * Get the list of groups clients have registered to the protolog service. + * @return The list of ProtoLog groups registered with this service. + */ + @Override + @NonNull + public String[] getGroups() { + return mRegisteredGroups.toArray(new String[0]); + } + + /** + * Enable logging target groups to logcat. + * @param groups we want to enable logging them to logcat for. + */ + @Override + public void enableProtoLogToLogcat(@NonNull String... groups) { + toggleProtoLogToLogcat(true, groups); + } + + /** + * Disable logging target groups to logcat. + * @param groups we want to disable from being logged to logcat. + */ + @Override + public void disableProtoLogToLogcat(@NonNull String... groups) { + toggleProtoLogToLogcat(false, groups); + } + + /** + * Check if a group is logging to logcat + * @param group The group we want to check for + * @return True iff we are logging this group to logcat. + */ + @Override + public boolean isLoggingToLogcat(@NonNull String group) { + final Boolean isLoggingToLogcat = mLogGroupToLogcatStatus.get(group); + + if (isLoggingToLogcat == null) { + throw new RuntimeException( + "Trying to get logcat logging status of non-registered group " + group); + } + + return isLoggingToLogcat; + } + + private void registerViewerConfigFile( + @NonNull IProtoLogClient client, @NonNull String viewerConfigFile) { + final var count = mConfigFileCounts.getOrDefault(viewerConfigFile, 0); + mConfigFileCounts.put(viewerConfigFile, count + 1); + mClientConfigFiles.put(client, viewerConfigFile); + } + + private void registerGroups(@NonNull IProtoLogClient client, @NonNull String[] groups, + @NonNull boolean[] logcatStatuses) throws RemoteException { + if (groups.length != logcatStatuses.length) { + throw new RuntimeException( + "Expected groups and logcatStatuses to have the same length, " + + "but groups has length " + groups.length + + " and logcatStatuses has length " + logcatStatuses.length); + } + + for (int i = 0; i < groups.length; i++) { + String group = groups[i]; + boolean logcatStatus = logcatStatuses[i]; + + mRegisteredGroups.add(group); + + mGroupToClients.putIfAbsent(group, new HashSet<>()); + mGroupToClients.get(group).add(client); + + if (!mLogGroupToLogcatStatus.containsKey(group)) { + mLogGroupToLogcatStatus.put(group, logcatStatus); + } + + boolean requestedLogToLogcat = mLogGroupToLogcatStatus.get(group); + if (requestedLogToLogcat != logcatStatus) { + client.toggleLogcat(requestedLogToLogcat, new String[] { group }); + } + } + } + + private void toggleProtoLogToLogcat(boolean enabled, @NonNull String[] groups) { + final var clientToGroups = new HashMap<IProtoLogClient, Set<String>>(); + + for (String group : groups) { + final var clients = mGroupToClients.get(group); + + if (clients == null) { + // No clients associated to this group + Log.w(LOG_TAG, "Attempting to toggle log to logcat for group " + group + + " with no registered clients."); + continue; + } + + for (IProtoLogClient client : clients) { + clientToGroups.putIfAbsent(client, new HashSet<>()); + clientToGroups.get(client).add(group); + } + } + + for (IProtoLogClient client : clientToGroups.keySet()) { + try { + client.toggleLogcat(enabled, clientToGroups.get(client).toArray(new String[0])); + } catch (RemoteException e) { + throw new RuntimeException( + "Failed to toggle logcat status for groups on client", e); + } + } + + for (String group : groups) { + mLogGroupToLogcatStatus.put(group, enabled); + } + } + + private void onTracingInstanceStart(int instanceIdx, ProtoLogDataSource.ProtoLogConfig config) { + mRunningInstances.add(instanceIdx); + } + + private void onTracingInstanceFlush() { + for (String fileName : mConfigFileCounts.keySet()) { + mViewerConfigFileTracer.trace(mDataSource, fileName); + } + } + + private void onTracingInstanceStop(int instanceIdx, ProtoLogDataSource.ProtoLogConfig config) { + mRunningInstances.remove(instanceIdx); + } + + private static void dumpTransitionTraceConfig(@NonNull ProtoLogDataSource dataSource, + @NonNull String viewerConfigFilePath) { + Utils.dumpViewerConfig(dataSource, () -> { + try { + return new ProtoInputStream(new FileInputStream(viewerConfigFilePath)); + } catch (FileNotFoundException e) { + throw new RuntimeException( + "Failed to load viewer config file " + viewerConfigFilePath, e); + } + }); + } + + private void onClientBinderDeath(@NonNull IProtoLogClient client) { + // Dump the tracing config now if no other client is going to dump the same config file. + String configFile = mClientConfigFiles.get(client); + if (configFile != null) { + final var newCount = mConfigFileCounts.get(configFile) - 1; + mConfigFileCounts.put(configFile, newCount); + boolean lastProcessWithViewerConfig = newCount == 0; + if (lastProcessWithViewerConfig) { + mViewerConfigFileTracer.trace(mDataSource, configFile); + } + } + } + + private static void writeViewerConfigGroup( + @NonNull ProtoInputStream pis, @NonNull ProtoOutputStream os) throws IOException { + final long inGroupToken = pis.start(GROUPS); + final long outGroupToken = os.start(GROUPS); + + while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + switch (pis.getFieldNumber()) { + case (int) ID -> { + int id = pis.readInt(ID); + os.write(ID, id); + } + case (int) NAME -> { + String name = pis.readString(NAME); + os.write(NAME, name); + } + case (int) TAG -> { + String tag = pis.readString(TAG); + os.write(TAG, tag); + } + default -> + throw new RuntimeException( + "Unexpected field id " + pis.getFieldNumber()); + } + } + + pis.end(inGroupToken); + os.end(outGroupToken); + } + + private static void writeViewerConfigMessage( + @NonNull ProtoInputStream pis, @NonNull ProtoOutputStream os) throws IOException { + final long inMessageToken = pis.start(MESSAGES); + final long outMessagesToken = os.start(MESSAGES); + + while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) { + switch (pis.getFieldNumber()) { + case (int) MESSAGE_ID -> os.write(MESSAGE_ID, + pis.readLong(MESSAGE_ID)); + case (int) MESSAGE -> os.write(MESSAGE, pis.readString(MESSAGE)); + case (int) LEVEL -> os.write(LEVEL, pis.readInt(LEVEL)); + case (int) GROUP_ID -> os.write(GROUP_ID, pis.readInt(GROUP_ID)); + case (int) LOCATION -> os.write(LOCATION, pis.readString(LOCATION)); + default -> + throw new RuntimeException( + "Unexpected field id " + pis.getFieldNumber()); + } + } + + pis.end(inMessageToken); + os.end(outMessagesToken); + } +} diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 90cb10aa62b2..9a4ff8fc264f 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -290,7 +290,6 @@ cc_library_shared_for_libandroid_runtime { "libasync_safe", "libbinderthreadstateutils", "libdmabufinfo", - "libgif", "libgui_window_info_static", "libkernelconfigs", "libnativehelper_lazy", diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp index 70505a45fa1b..b9c3bf73f11c 100644 --- a/core/jni/android_graphics_BLASTBufferQueue.cpp +++ b/core/jni/android_graphics_BLASTBufferQueue.cpp @@ -16,16 +16,16 @@ #define LOG_TAG "BLASTBufferQueue" -#include <nativehelper/JNIHelp.h> - #include <android_runtime/AndroidRuntime.h> #include <android_runtime/android_view_Surface.h> -#include <utils/Log.h> -#include <utils/RefBase.h> - +#include <android_util_Binder.h> #include <gui/BLASTBufferQueue.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> +#include <nativehelper/JNIHelp.h> +#include <utils/Log.h> +#include <utils/RefBase.h> + #include "core_jni_helpers.h" namespace android { @@ -209,6 +209,12 @@ static jobject nativeGatherPendingTransactions(JNIEnv* env, jclass clazz, jlong reinterpret_cast<jlong>(transaction)); } +static void nativeSetApplyToken(JNIEnv* env, jclass clazz, jlong ptr, jobject applyTokenObject) { + sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); + sp<IBinder> token(ibinderForJavaObject(env, applyTokenObject)); + return queue->setApplyToken(std::move(token)); +} + static const JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ // clang-format off @@ -227,6 +233,7 @@ static const JNINativeMethod gMethods[] = { {"nativeSetTransactionHangCallback", "(JLandroid/graphics/BLASTBufferQueue$TransactionHangCallback;)V", (void*)nativeSetTransactionHangCallback}, + {"nativeSetApplyToken", "(JLandroid/os/IBinder;)V", (void*)nativeSetApplyToken}, // clang-format on }; diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index f2c70b5f41d4..8003bb7d442b 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -1747,9 +1747,9 @@ static const JNINativeMethod gBinderProxyMethods[] = { {"linkToDeathNative", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath}, {"unlinkToDeathNative", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath}, {"addFrozenStateChangeCallbackNative", - "(Landroid/os/IBinder$IFrozenStateChangeCallback;)V", (void*)android_os_BinderProxy_addFrozenStateChangeCallback}, + "(Landroid/os/IBinder$FrozenStateChangeCallback;)V", (void*)android_os_BinderProxy_addFrozenStateChangeCallback}, {"removeFrozenStateChangeCallbackNative", - "(Landroid/os/IBinder$IFrozenStateChangeCallback;)Z", (void*)android_os_BinderProxy_removeFrozenStateChangeCallback}, + "(Landroid/os/IBinder$FrozenStateChangeCallback;)Z", (void*)android_os_BinderProxy_removeFrozenStateChangeCallback}, {"getNativeFinalizer", "()J", (void*)android_os_BinderProxy_getNativeFinalizer}, {"getExtension", "()Landroid/os/IBinder;", (void*)android_os_BinderProxy_getExtension}, }; @@ -1774,7 +1774,7 @@ static int int_register_android_os_BinderProxy(JNIEnv* env) "(Landroid/os/IBinder$DeathRecipient;Landroid/os/IBinder;)V"); gBinderProxyOffsets.mInvokeFrozenStateChangeCallback = GetStaticMethodIDOrDie(env, clazz, "invokeFrozenStateChangeCallback", - "(Landroid/os/IBinder$IFrozenStateChangeCallback;Landroid/os/" + "(Landroid/os/IBinder$FrozenStateChangeCallback;Landroid/os/" "IBinder;I)V"); gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J"); diff --git a/core/jni/jni_wrappers.h b/core/jni/jni_wrappers.h index 3b29e305e410..21b5b1308fcf 100644 --- a/core/jni/jni_wrappers.h +++ b/core/jni/jni_wrappers.h @@ -69,9 +69,47 @@ 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; +} + +// Potentially translates the given JNINativeMethods if setJniMethodFormat has been set. +// Has no effect otherwise +inline const JNINativeMethod* maybeRenameJniMethods(const JNINativeMethod* gMethods, + int numMethods) { + if (jniMethodFormat.empty()) { + return gMethods; + } + // 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; + } + return modifiedMethods; +} + static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { - int res = jniRegisterNativeMethods(env, className, gMethods, numMethods); + const JNINativeMethod* modifiedMethods = maybeRenameJniMethods(gMethods, numMethods); + int res = jniRegisterNativeMethods(env, className, modifiedMethods, numMethods); LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods."); return res; } diff --git a/core/proto/android/widget/remoteviews.proto b/core/proto/android/widget/remoteviews.proto index 47c97b08666b..f477d32cd915 100644 --- a/core/proto/android/widget/remoteviews.proto +++ b/core/proto/android/widget/remoteviews.proto @@ -299,6 +299,14 @@ message RemoteViewsProto { NightModeReflectionAction night_mode_reflection_action = 5; ReflectionAction reflection_action = 6; RemoveFromParentAction remove_from_parent_action = 7; + ResourceReflectionAction resource_reflection_action = 8; + SetCompoundButtonCheckedAction set_compound_button_checked_action = 9; + SetDrawableTintAction set_drawable_tint_action = 10; + SetEmptyViewAction set_empty_view_action = 11; + SetIntTagAction set_int_tag_action = 12; + SetRadioGroupCheckedAction set_radio_group_checked_action = 13; + SetRemoteCollectionItemListAdapterAction set_remote_collection_item_list_adapter_action = 14; + SetRippleDrawableColorAction set_ripple_drawable_color_action = 15; } } @@ -374,6 +382,52 @@ message RemoteViewsProto { message RemoveFromParentAction { optional string view_id = 1; } + + message ResourceReflectionAction { + optional string view_id = 1; + optional string method_name = 2; + optional int32 resource_type = 3; + optional string res_id = 4; + optional int32 parameter_type = 5; + } + + message SetCompoundButtonCheckedAction { + optional string view_id = 1; + optional bool checked = 2; + } + + message SetDrawableTintAction { + optional string view_id = 1; + optional bool target_background = 2; + optional int32 color_filter = 3; + optional int32 filter_mode = 4; + } + + message SetEmptyViewAction { + optional string view_id = 1; + optional string empty_view_id = 2; + } + + message SetIntTagAction { + optional string view_id = 1; + optional string key = 2; + optional int32 tag = 3; + } + + message SetRadioGroupCheckedAction { + optional string view_id = 1; + optional string checked_id = 2; + } + + message SetRemoteCollectionItemListAdapterAction { + optional string view_id = 1; + optional RemoteCollectionItems items = 2; + } + + message SetRippleDrawableColorAction { + optional string view_id = 1; + optional android.content.res.ColorStateListProto color_state_list = 2; + } } diff --git a/core/res/res/layout/miniresolver.xml b/core/res/res/layout/miniresolver.xml index e60e0b0079a9..db1c779d0087 100644 --- a/core/res/res/layout/miniresolver.xml +++ b/core/res/res/layout/miniresolver.xml @@ -122,7 +122,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentStart="true" - android:maxLines="2" + android:layout_toStartOf="@id/button_open" + android:layout_marginEnd="8dp" android:background="@drawable/resolver_outlined_button_bg" style="?android:attr/borderlessButtonStyle" android:paddingHorizontal="16dp" @@ -136,7 +137,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" - android:maxLines="2" android:paddingHorizontal="16dp" android:background="@drawable/resolver_button_bg" style="?android:attr/borderlessButtonStyle" diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index a1dea8236bd4..93524136c247 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"’n App verberg die toestemmingversoek en jou antwoord kan dus nie geverifieer word nie."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tik op \'n kenmerk om dit te begin gebruik:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Kies kenmerke om saam met die toeganklikheidknoppie te gebruik"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Kies kenmerke om saam met die volumesleutelskortpad te gebruik"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> is afgeskakel"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Wysig kortpaaie"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klaar"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Stel ’n skermslot"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Stel skermslot"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Stel ’n skermslot op dié toestel om jou privaat ruimte te gebruik"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Program is nie beskikbaar nie"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is nie op die oomblik beskikbaar nie."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> is nie beskikbaar nie"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index a7b6661a42e5..10855c8f8e03 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"ማያ ገጽ መቆለፊያን ያቀናብሩ"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"ማያ ገጽ መቆለፊያውን ያቀናብሩ"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"የግል ቦታዎን ለመጠቀም፣ በዚህ መሣሪያ ላይ ማያ ገጽ መቆለፊያን ያቀናብሩ"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"መተግበሪያ አይገኝም"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> አሁን አይገኝም።"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> አይገኝም"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 7f025760466b..623ef23b6869 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -1750,8 +1750,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"تعذَّر التحقّق من ردّك بسبب حجب أحد التطبيقات طلب الحصول على الإذن."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"انقر على ميزة لبدء استخدامها:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"اختيار الميزات التي تريد استخدامها مع زر أدوات تمكين الوصول"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"اختيار الميزات التي تريد استخدامها مع اختصار مفتاحَي مستوى الصوت"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"تم إيقاف <xliff:g id="SERVICE_NAME">%s</xliff:g>."</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"تعديل الاختصارات"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"تم"</string> @@ -2015,6 +2014,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"ضبط قفل شاشة"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"ضبط قفل الشاشة"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"لاستخدام مساحتك الخاصة، يجب ضبط قفل شاشة على هذا الجهاز"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"التطبيق غير متاح"</string> <string name="app_blocked_message" msgid="542972921087873023">"تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> غير متاح الآن."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"تطبيق <xliff:g id="ACTIVITY">%1$s</xliff:g> غير متاح"</string> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index c5ad8bab39d0..ba1095b43e4a 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"এটা স্ক্ৰীন লক ছেট কৰক"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"স্ক্ৰীন লক ছেট কৰা"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"আপোনাৰ প্ৰাইভেট স্পে\'চ ব্যৱহাৰ কৰিবলৈ এই ডিভাইচটোত স্ক্ৰীন লক ছেট কৰক"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"এপ্টো উপলব্ধ নহয়"</string> <string name="app_blocked_message" msgid="542972921087873023">"এই মুহূৰ্তত <xliff:g id="APP_NAME">%1$s</xliff:g> উপলব্ধ নহয়।"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> উপলব্ধ নহয়"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index e93a57ba76cc..1b574d1e82d8 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Bir tətbiq icazə sorğusunu gizlətdiyi üçün cavabı yoxlamaq mümkün deyil."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Funksiyanı istifadə etmək üçün onun üzərinə toxunun:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Xüsusi imkanlar düyməsinin köməyilə işə salınacaq funksiyaları seçin"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Səs səviyyəsi düyməsinin qısayolu ilə istifadə edəcəyiniz funksiyaları seçin"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> deaktiv edilib"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Qısayolları redaktə edin"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hazırdır"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Ekran kilidi ayarlayın"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Ekran kilidi ayarlayın"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Bu cihazda ekran kilidi ayarlamaqla şəxsi sahədən istifadə edin"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Tətbiq əlçatan deyil"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> hazırda əlçatan deyil."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> əlçatan deyil"</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 8f0f4b2259c8..2116a6ef2ed8 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -2011,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Podesite otključavanje ekrana"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Podesi otključavanje ekrana"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Da biste koristili privatni prostor, podesite otključavanje ekrana na ovom uređaju"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string> <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno nije dostupna."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> – nije dostupno"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index 7a49bf348acf..0219b6c479fe 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -2012,6 +2012,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Наладзьце блакіроўку экрана"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Наладзіць блакіроўку экрана"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Каб выкарыстоўваць прыватную прастору, на прыладзе неабходна наладзіць блакіроўку экрана"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Праграма недаступная"</string> <string name="app_blocked_message" msgid="542972921087873023">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" цяпер недаступная."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"Недаступна: <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index b6fad9e9a848..93fdf3dc5207 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Отговорът ви не може да бъде потвърден, тъй като приложение прикрива заявката за разрешение."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Докоснете дадена функция, за да започнете да я използвате:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Избиране на функции, които да използвате с бутона за достъпност"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Избиране на функции, които да използвате с прекия път чрез бутоните за силата на звука"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Изключихте <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Редактиране на преките пътища"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string> @@ -2011,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Настройте заключване на екрана"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Заключване на екрана"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"За да ползвате частното си пространство, настройте заключване на екрана"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"За да изтриете личното пространство, настройте заключване на екрана"</string> <string name="app_blocked_title" msgid="7353262160455028160">"Приложението не е достъпно"</string> <string name="app_blocked_message" msgid="542972921087873023">"В момента няма достъп до <xliff:g id="APP_NAME">%1$s</xliff:g>."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> не е налице"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index c434fe91d11e..019068bec99a 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"কোনও অ্যাপ অনুমতির অনুরোধ আড়াল করছে তাই আপনার উত্তর যাচাই করা যাবে না।"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"কোনও ফিচার ব্যবহার করা শুরু করতে, সেটিতে ট্যাপ করুন:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"অ্যাক্সেসিবিলিটি বোতামের সাহায্যে আপনি যেসব ফিচার ব্যবহার করতে চান সেগুলি বেছে নিন"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"ভলিউম কী শর্টকাটের সাহায্যে আপনি যেসব ফিচার ব্যবহার করতে চান সেগুলি বেছে নিন"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> বন্ধ করে দেওয়া হয়েছে"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"শর্টকাট এডিট করুন"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"হয়ে গেছে"</string> @@ -2011,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"\'স্ক্রিন লক\' সেট-আপ করুন"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"\'স্ক্রিন লক\' ফিচার সেট করুন"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"নিজের প্রাইভেট স্পেস ব্যবহার করতে এই ডিভাইসে \'স্ক্রিন লক\' সেট করুন"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"প্রাইভেট স্পেস মুছে দিতে, এই ডিভাইসে \'স্ক্রিন লক\' সেট করুন।"</string> <string name="app_blocked_title" msgid="7353262160455028160">"অ্যাপ পাওয়া যাচ্ছে না"</string> <string name="app_blocked_message" msgid="542972921087873023">"এই মুহূর্তে <xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপ পাওয়া যাচ্ছে না।"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> উপলভ্য নেই"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 91c77018810d..bdd9f159b1e9 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -1240,7 +1240,7 @@ <string name="whichHomeApplicationNamed" msgid="5855990024847433794">"Koristi %1$s kao glavnu aplikaciju"</string> <string name="whichHomeApplicationLabel" msgid="8907334282202933959">"Snimanje slike"</string> <string name="whichImageCaptureApplication" msgid="2737413019463215284">"Snimanje slike koristeći"</string> - <string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"Snimanje slike koristeći %1$s"</string> + <string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"Snimite sliku aplikacijom %1$s"</string> <string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"Snimanje slike"</string> <string name="alwaysUse" msgid="3153558199076112903">"Koristiti kao zadanu rezoluciju za ovu akciju."</string> <string name="use_a_different_app" msgid="4987790276170972776">"Koristi drugu aplikaciju"</string> @@ -1747,8 +1747,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacija skriva zahtjev za odobrenje, pa se vaš odgovor ne može potvrditi."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Dodirnite funkciju da je počnete koristiti:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Odaberite funkcije koje ćete koristiti s dugmetom Pristupačnost"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Odabir funkcija za korištenje pomoću prečice tipki za jačinu zvuka"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usluga <xliff:g id="SERVICE_NAME">%s</xliff:g> je isključena"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi prečice"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gotovo"</string> @@ -2012,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Postavite zaključavanje ekrana"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Postavite zaključavanje ekrana"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Za upotrebu privatnog prostora postavite zaključavanje ekrana na uređaju"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string> <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno nije dostupna."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"Nedostupno: <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index cbe9c3927726..5728aed8551a 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -1747,8 +1747,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Una aplicació està ocultant la sol·licitud de permís, de manera que la teva resposta no es pot verificar"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toca una funció per començar a utilitzar-la:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Tria les funcions que vols utilitzar amb el botó d\'accessibilitat"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Tria les funcions que vols utilitzar amb la drecera de les tecles de volum"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> s\'ha desactivat"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edita les dreceres"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fet"</string> @@ -2012,6 +2011,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Defineix un bloqueig de pantalla"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Defineix un bloqueig de pantalla"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Per utilitzar l\'espai privat, defineix un bloqueig de pantalla en aquest dispositiu"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"Per suprimir l\'espai privat, defineix un bloqueig de pantalla en aquest dispositiu."</string> <string name="app_blocked_title" msgid="7353262160455028160">"L\'aplicació no està disponible"</string> <string name="app_blocked_message" msgid="542972921087873023">"Ara mateix, <xliff:g id="APP_NAME">%1$s</xliff:g> no està disponible."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> no està disponible"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 69e6483a03f4..8aa1224fbb22 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -2012,6 +2012,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Nastavte si zámek obrazovky"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Nastavit zámek obrazovky"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Pokud chcete používat soukromý prostor, nastavte na tomto zařízení zámek obrazovky"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Aplikace není k dispozici"</string> <string name="app_blocked_message" msgid="542972921087873023">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> v tuto chvíli není k dispozici."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> není k dispozici"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index d66ebd907237..95e61b95cbae 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"En app skjuler anmodningen om tilladelse, så dit svar kan ikke verificeres."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tryk på en funktion for at bruge den:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Vælg, hvilke funktioner du vil bruge med knappen til hjælpefunktioner"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Vælg de funktioner, du vil bruge med genvejen til lydstyrkeknapperne"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> er blevet deaktiveret"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Rediger genveje"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Udfør"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Konfigurer en skærmlås"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Konfigurer skærmlås"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Konfigurer en skærmlås på enheden for at bruge dit private område"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Appen er ikke tilgængelig"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ikke tilgængelig lige nu."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> er ikke understøttet"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 387976758672..41c1e4b20d67 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Die Berechtigungsanfrage wird durch eine andere App verdeckt. Daher kann deine Antwort nicht geprüft werden."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Zum Auswählen der gewünschten Funktion tippen:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Funktionen auswählen, die du mit der Schaltfläche \"Bedienungshilfen\" verwenden möchtest"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Funktionen für den Kurzbefehl für die Lautstärketasten auswählen"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> wurde deaktiviert"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kurzbefehle bearbeiten"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fertig"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Displaysperre einrichten"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Displaysperre einrichten"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Richte zur Nutzung des vertraulichen Profils auf dem Gerät die Displaysperre ein"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"App ist nicht verfügbar"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ist derzeit nicht verfügbar."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nicht verfügbar"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 28a5e55fc284..0556a0820dea 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Μια εφαρμογή αποκρύπτει το αίτημα άδειας, με αποτέλεσμα να μην είναι δυνατή η επαλήθευση της απάντησής σας."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Πατήστε μια λειτουργία για να ξεκινήσετε να τη χρησιμοποιείτε:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Επιλέξτε τις λειτουργίες που θέλετε να χρησιμοποιείτε με το κουμπί προσβασιμότητας."</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Επιλέξτε τις λειτουργίες που θέλετε να χρησιμοποιείτε με τη συντόμευση κουμπιών έντασης ήχου"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Η υπηρεσία <xliff:g id="SERVICE_NAME">%s</xliff:g> έχει απενεργοποιηθεί."</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Επεξεργασία συντομεύσεων"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Τέλος"</string> @@ -2011,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Ρυθμίστε ένα κλείδωμα οθόνης"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Ρύθμιση κλειδώματος οθόνης"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Ορίστε κλείδωμα οθόνης"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"Για να διαγράψετε τον ιδιωτικό χώρο, ορίστε ένα κλείδωμα οθόνης σε αυτή τη συσκευή"</string> <string name="app_blocked_title" msgid="7353262160455028160">"Η εφαρμογή δεν είναι διαθέσιμη"</string> <string name="app_blocked_message" msgid="542972921087873023">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν είναι διαθέσιμη αυτήν τη στιγμή."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> δεν διατίθεται"</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 70d86e7de732..086835c1cd5a 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"An app is obscuring the permission request so your response cannot be verified."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tap a feature to start using it:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choose features to use with the Accessibility button"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Choose features to use with the volume keys shortcut"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> has been turned off"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Done"</string> @@ -2011,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Set a screen lock"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Set screen lock"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"To use your private space, set a screen lock on this device"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"To delete private space, set a screen lock on this device"</string> <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index dad63334dc6c..88a83b595520 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -2010,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Set a screen lock"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Set screen lock"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"To use your private space, set a screen lock on this device"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"To delete private space, set a screen lock on this device"</string> <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index d3f0c6410e24..ef399b715631 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"An app is obscuring the permission request so your response cannot be verified."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tap a feature to start using it:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choose features to use with the Accessibility button"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Choose features to use with the volume keys shortcut"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> has been turned off"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Done"</string> @@ -2011,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Set a screen lock"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Set screen lock"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"To use your private space, set a screen lock on this device"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"To delete private space, set a screen lock on this device"</string> <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 7c3be159a01f..94ddc434926f 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"An app is obscuring the permission request so your response cannot be verified."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tap a feature to start using it:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choose features to use with the Accessibility button"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Choose features to use with the volume keys shortcut"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> has been turned off"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Done"</string> @@ -2011,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Set a screen lock"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Set screen lock"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"To use your private space, set a screen lock on this device"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"To delete private space, set a screen lock on this device"</string> <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index 0bcbed786d44..a0a891eefac2 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -2010,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Set a screen lock"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Set screen lock"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"To use your private space, set a screen lock on this device"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"To delete private space, set a screen lock on this device"</string> <string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 773edd3e5ba7..12d2756bbe88 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1747,8 +1747,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Una app está cubriendo la solicitud de permiso, por lo que no se puede verificar tu respuesta."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Presiona una función para comenzar a usarla:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Selecciona las funciones a utilizar con el botón de accesibilidad"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Selecciona las funciones que usarás con la combinación de teclas de volumen"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Se desactivó <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar accesos directos"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Listo"</string> @@ -2012,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Configurar bloqueo de pantalla"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Configurar bloqueo de pantalla"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Para usar tu espacio privado, configura un bloqueo de pantalla"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"La app no está disponible"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> no está disponible en este momento."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> no disponible"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index e50d5faea41b..c6ee8ef77006 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -2011,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Define un bloqueo de pantalla"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Establecer bloqueo de pantalla"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Para usar el espacio privado, define un bloqueo de pantalla"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"La aplicación no está disponible"</string> <string name="app_blocked_message" msgid="542972921087873023">"En estos momentos, <xliff:g id="APP_NAME">%1$s</xliff:g> no está disponible."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> no disponible"</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index f313fb29b92a..4389b4b9506c 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Rakendus varjab loataotlust, nii et teie vastust ei saa kinnitada."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Puudutage funktsiooni, et selle kasutamist alustada."</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Valige funktsioonid, mida juurdepääsetavuse nupuga kasutada"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Valige helitugevuse nuppude otsetee funktsioonid"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> on välja lülitatud"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Muuda otseteid"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Valmis"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Seadistage ekraanilukk"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Seadistage ekraanilukk"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Seadistage oma privaatse ruumi jaoks seadmele ekraanilukk"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Rakendus ei ole saadaval"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei ole praegu saadaval."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ei ole saadaval"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index b0775d0796a9..56b10d124d55 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikazio bat baimen-eskaera oztopatzen ari da eta, ondorioz, ezin da egiaztatu erantzuna."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Eginbide bat erabiltzen hasteko, saka ezazu:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Aukeratu zein eginbide erabili nahi duzun Erabilerraztasuna botoiarekin"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Aukeratu zein eginbide erabili nahi duzun bolumen-botoien lasterbidearekin"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Desaktibatu da <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editatu lasterbideak"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Eginda"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Ezarri pantailaren blokeoa"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Ezarri pantailaren blokeoa"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Eremu pribatua erabiltzeko, ezarri pantailaren blokeoa gailuan"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Aplikazioa ez dago erabilgarri"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ez dago erabilgarri une honetan."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ez dago erabilgarri"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 0c46ed93a602..34edd03838d4 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"قفل صفحه تنظیم کنید"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"تنظیم قفل صفحه"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"برای استفاده از فضای خصوصی، قفل صفحه تنظیم کنید"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"برنامه در دسترس نیست"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> درحالحاضر در دسترس نیست."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> دردسترس نیست"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index dec5b64b9592..ecc7a3f01ad0 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Sovellus peittää lupapyynnön, joten vastaustasi ei voi vahvistaa."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Aloita ominaisuuden käyttö napauttamalla sitä:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Valitse ominaisuudet, joita käytetään esteettömyyspainikkeella"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Valitse ominaisuudet, joita käytetään äänenvoimakkuuspikanäppäimillä"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> on laitettu pois päältä"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Muokkaa pikakuvakkeita"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Valmis"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Näytön lukituksen asettaminen"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Aseta näytön lukitus"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Edellyttää näytön lukitusta"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Sovellus ei ole käytettävissä"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei ole nyt käytettävissä."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ei käytettävissä"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 7cb9e06c287a..86b83a09dabf 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -1747,8 +1747,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Une appli masque la demande d\'autorisation de sorte que votre réponse ne peut pas être vérifiée."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toucher une fonctionnalité pour commencer à l\'utiliser :"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choisir les fonctionnalités à utiliser à l\'aide du bouton d\'accessibilité"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Choisir les fonctionnalités à utiliser avec le raccourci des touches de volume"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> a été désactivé"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifier les raccourcis"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string> @@ -2012,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Config. Verrouillage d\'écran"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Config. Verrouillage d\'écran"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Configurez verrouillage de l\'écran pour utiliser Espace privé"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"L\'appli n\'est pas accessible"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas accessible pour le moment."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> non accessible"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index ca3998c6f43c..5fa4a3b53205 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1747,8 +1747,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Une application masque la demande d\'autorisation. Votre réponse ne peut donc pas être vérifiée."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Appuyez sur une fonctionnalité pour commencer à l\'utiliser :"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choisir les fonctionnalités à utiliser avec le bouton Accessibilité"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Choisir les fonctionnalités à utiliser avec le raccourci des boutons de volume"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Le service <xliff:g id="SERVICE_NAME">%s</xliff:g> a été désactivé"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifier les raccourcis"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string> @@ -2012,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Activer verrouillage écran"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Activer verrouillage écran"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Pour utiliser votre espace privé, activez le verrouillage de l\'écran sur cet appareil"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Application non disponible"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas disponible pour le moment."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> indisponible"</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index e07218cd9555..2f3cffa6a862 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Hai unha aplicación que está ocultando a solicitude de permiso, polo que non se pode verificar a túa resposta."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tocar unha función para comezar a utilizala:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escoller as funcións que queres utilizar co botón Accesibilidade"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Escolle as funcións que queres utilizar co atallo das teclas de volume"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g>: desactivouse"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atallos"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Feito"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Define un bloqueo de pantalla"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Define un bloqueo de pantalla"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Para usar o espazo privado, define un bloqueo de pantalla"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"A aplicación non está dispoñible"</string> <string name="app_blocked_message" msgid="542972921087873023">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> non está dispoñible neste momento."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> non está dispoñible"</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 2ac70ab79c3b..aa190a5a503a 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"સ્ક્રીન લૉક સેટ કરો"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"સ્ક્રીન લૉક સેટ કરો"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"તમારી ખાનગી સ્પેસનો ઉપયોગ કરવા, આ ડિવાઇસ પર સ્ક્રીન લૉક સેટ કરો"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"ઍપ ઉપલબ્ધ નથી"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> હાલમાં ઉપલબ્ધ નથી."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ઉપલબ્ધ નથી"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 5f1bb9a74d27..4c76cffd518c 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"स्क्रीन लॉक सेट करें"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"स्क्रीन लॉक सेट करें"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"प्राइवेट स्पेस के लिए, इस डिवाइस पर स्क्रीन लॉक सेट करें"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"ऐप्लिकेशन उपलब्ध नहीं है"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> इस समय उपलब्ध नहीं है."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> उपलब्ध नहीं है"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 2596de21fadd..bf972b8cb961 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -1747,8 +1747,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacija prekriva upit za dopuštenje pa se vaš odgovor ne može potvrditi."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Dodirnite značajku da biste je počeli koristiti:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Odabir značajki za upotrebu pomoću gumba za Pristupačnost"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Odabir značajki za upotrebu pomoću prečaca tipki za glasnoću"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usluga <xliff:g id="SERVICE_NAME">%s</xliff:g> je isključena"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredite prečace"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gotovo"</string> @@ -2012,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Postavite zaključavanje zaslona"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Postavi zaključavanje zaslona"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Da biste upotrebljavali privatni prostor, postavite zaključavanje zaslona na ovom uređaju"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string> <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutačno nije dostupna."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> – nije dostupno"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 09af50603643..357328c9a188 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Az egyik alkalmazás eltakarja az engedélykérelmet, így az Ön válasza nem ellenőrizhető."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Koppintson valamelyik funkcióra a használatához:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Kiválaszthatja a Kisegítő lehetőségek gombbal használni kívánt funkciókat"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Kiválaszthatja a hangerőszabályzó gombokkal használni kívánt funkciókat"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kikapcsolva"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Gyorsparancsszerkesztés"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Kész"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Állítson be képernyőzárat"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Képernyőzár beállítása"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"A privát terület használatához állítson be képernyőzárat"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Az alkalmazás nem hozzáférhető"</string> <string name="app_blocked_message" msgid="542972921087873023">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> jelenleg nem hozzáférhető."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"A(z) <xliff:g id="ACTIVITY">%1$s</xliff:g> nem áll rendelkezése"</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index a28f413b9572..5405bb283415 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Հավելվածը թաքցնում է թույլտվության հայտը, ուստի ձեր պատասխանը հնարավոր չէ ստուգել։"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Ընտրեք՝ որ գործառույթն օգտագործել"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Ընտրեք գործառույթները, որոնք կբացվեն «Հատուկ գործառույթներ» կոճակի միջոցով"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Ընտրեք գործառույթները, որոնք պետք է բացվեն ձայնի կարգավորման կոճակների միջոցով"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ծառայությունն անջատված է"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Փոփոխել դյուրանցումները"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Պատրաստ է"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Կարգավորեք էկրանի կողպումը"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Կարգավորել էկրանի կողպումը"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Մասնավոր տարածքն օգտագործելու համար այս սարքում կարգավորեք էկրանի կողպումը"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Հավելվածը հասանելի չէ"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածն այս պահին հասանելի չէ։"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>՝ անհասանելի է"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 76c89eaa2ddf..f5a2a14525a3 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikasi menghalangi permintaan izin sehingga respons Anda tidak dapat diverifikasi."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Ketuk fitur untuk mulai menggunakannya:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Pilih fitur yang akan digunakan dengan tombol aksesibilitas"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Pilih fitur yang akan digunakan dengan pintasan tombol volume"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> telah dinonaktifkan"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit pintasan"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Selesai"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Setel kunci layar"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Setel kunci layar"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Untuk menggunakan ruang privasi, setel kunci layar di perangkat ini"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Aplikasi tidak tersedia"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak tersedia saat ini."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> tidak tersedia"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 057b830d4fb7..baeaa3f37789 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Stilltu skjálás"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Stilla skjálás"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Stilltu skjálás í tækinu til að nota leynirými"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Forrit er ekki tiltækt"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ekki tiltækt núna."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ekki í boði"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 29533d50eac8..48766b882bef 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -1747,8 +1747,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Un\'app nasconde la tua richiesta di autorizzazione, per cui non abbiamo potuto verificare la tua risposta."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tocca una funzionalità per iniziare a usarla:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Scegli le funzionalità da usare con il pulsante Accessibilità"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Scegli le funzionalità da usare con la scorciatoia tasti del volume"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Il servizio <xliff:g id="SERVICE_NAME">%s</xliff:g> è stato disattivato"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifica scorciatoie"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fine"</string> @@ -2012,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Imposta un blocco schermo"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Imposta il blocco schermo"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Per utilizzare il tuo spazio privato, imposta un blocco schermo sul dispositivo"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"L\'app non è disponibile"</string> <string name="app_blocked_message" msgid="542972921087873023">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> non è al momento disponibile."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> non disponibile"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 52b6173745b5..d3f0d98c42f6 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -1747,8 +1747,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"אפליקציה מסתירה את בקשת ההרשאה כך שלא ניתן לאמת את התשובה שלך."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"יש להקיש על תכונה כדי להתחיל להשתמש בה:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"בחירת תכונה לשימוש עם לחצן הנגישות"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"בחירת תכונות לשימוש עם קיצור דרך באמצעות מקשי עוצמת הקול"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"שירות <xliff:g id="SERVICE_NAME">%s</xliff:g> כבוי"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"עריכת קיצורי הדרך"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"סיום"</string> @@ -2012,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"הגדרת נעילת מסך"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"הגדרה של נעילת מסך"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"כדי להשתמש במרחב הפרטי יש להגדיר נעילת מסך במכשיר"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"האפליקציה לא זמינה"</string> <string name="app_blocked_message" msgid="542972921087873023">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> לא זמינה בשלב זה."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> לא זמינה"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 0705b36d9450..bcea959a00fc 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -2010,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"画面ロックの設定"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"画面ロックを設定"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"プライベート スペースには画面ロックの設定が必要です"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"プライベート スペースを削除するには、このデバイスに画面ロックを設定してください"</string> <string name="app_blocked_title" msgid="7353262160455028160">"アプリの利用不可"</string> <string name="app_blocked_message" msgid="542972921087873023">"現在 <xliff:g id="APP_NAME">%1$s</xliff:g> はご利用になれません。"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>は利用できません"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index bac23337e0d1..9a88e545b0c6 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -2010,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"ეკრანის დაბლოკვის დაყენება"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"ეკრანის დაბლოკვის დაყენება"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"კერძო სივრცის გამოსაყენებლად დააყენეთ ამ მოწყობილობაზე ეკრანის დაბლოკვა"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"კერძო სივრცის წასაშლელად დააყენეთ ეკრანის დაბლოკვა ამ მოწყობილობაზე"</string> <string name="app_blocked_title" msgid="7353262160455028160">"აპი მიუწვდომელია"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ამჟამად მიუწვდომელია."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> მიუწვდომელია"</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index d9ee240ef48a..29dfbbab171a 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Қолданба рұқсат сұрауын жасырып тұрғандықтан, жауабыңыз расталмайды."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Функцияны пайдалана бастау үшін түртіңіз:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"\"Арнайы мүмкіндіктер\" түймесімен қолданылатын функцияларды таңдаңыз"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Дыбыс деңгейі пернелері тіркесімімен қолданылатын функцияларды таңдаңыз"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> қызметі өшірулі."</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Жылдам пәрмендерді өзгерту"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Дайын"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Экран құлпын орнатыңыз"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Экран құлпын орнату"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Құпия кеңістігіңізді қолдану үшін осы құрылғыда экран құлпын орнатыңыз."</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Қолданба қолжетімді емес"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> қазір қолжетімді емес."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> қолжетімсіз"</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 1f931c6644e3..aeea5dc42849 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -1216,7 +1216,7 @@ <string name="rating_label" msgid="1837085249662154601">"{rating,plural, =1{ផ្កាយមួយក្នុងចំណោមផ្កាយ {max}}other{ផ្កាយ # ក្នុងចំណោមផ្កាយ {max}}}"</string> <string name="in_progress" msgid="2149208189184319441">"កំពុងដំណើរការ"</string> <string name="whichApplication" msgid="5432266899591255759">"បញ្ចប់សកម្មភាពដោយប្រើ"</string> - <string name="whichApplicationNamed" msgid="6969946041713975681">"បញ្ចប់សកម្មភាពដោយប្រើ %1$s"</string> + <string name="whichApplicationNamed" msgid="6969946041713975681">"បញ្ចប់សកម្មភាពដោយប្រើ %%1$s"</string> <string name="whichApplicationLabel" msgid="7852182961472531728">"បញ្ចប់សកម្មភាព"</string> <string name="whichViewApplication" msgid="5733194231473132945">"បើកជាមួយ"</string> <string name="whichViewApplicationNamed" msgid="415164730629690105">"បើកជាមួយ %1$s"</string> @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"កំណត់ការចាក់សោអេក្រង់"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"កំណត់ការចាក់សោអេក្រង់"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"ដើម្បីប្រើលំហឯកជនរបស់អ្នក សូមកំណត់ការចាក់សោអេក្រង់នៅលើឧបករណ៍នេះ"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"មិនអាចប្រើកម្មវិធីនេះបានទេ"</string> <string name="app_blocked_message" msgid="542972921087873023">"មិនអាចប្រើ <xliff:g id="APP_NAME">%1$s</xliff:g> នៅពេលនេះបានទេ។"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"មិនអាចប្រើ <xliff:g id="ACTIVITY">%1$s</xliff:g> បានទេ"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 941a1b2572ce..126d55eec3e2 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -2010,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಸೆಟ್ ಮಾಡಿ"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಸೆಟ್ ಮಾಡಿ"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"ನಿಮ್ಮ ಪ್ರೈವೆಟ್ ಸ್ಪೇಸ್ ಅನ್ನು ಬಳಸಲು, ಈ ಸಾಧನದಲ್ಲಿ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಸೆಟ್ ಮಾಡಿ"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"ಪ್ರೈವೆಟ್ ಸ್ಪೇಸ್ ಅನ್ನು ಅಳಿಸಲು ಈ ಸಾಧನದಲ್ಲಿ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಸೆಟ್ ಮಾಡಿ"</string> <string name="app_blocked_title" msgid="7353262160455028160">"ಆ್ಯಪ್ ಲಭ್ಯವಿಲ್ಲ"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಇದೀಗ ಲಭ್ಯವಿಲ್ಲ."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ಲಭ್ಯವಿಲ್ಲ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 0e47e59c35f9..5ed69591390e 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"앱에서 권한 요청을 가려서 응답을 확인할 수 없습니다."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"기능을 사용하려면 탭하세요"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"접근성 버튼으로 사용할 기능 선택"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"볼륨 키 바로가기로 사용할 기능 선택"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g>이(가) 사용 중지됨"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"단축키 수정"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"완료"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"화면 잠금 설정"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"화면 잠금 설정"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"비공개 스페이스를 사용하려면 이 기기에 화면 잠금을 설정하세요"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"앱을 사용할 수 없습니다"</string> <string name="app_blocked_message" msgid="542972921087873023">"현재 <xliff:g id="APP_NAME">%1$s</xliff:g> 앱을 사용할 수 없습니다."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> 사용할 수 없음"</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index 43fd6a78cc73..0c3a5e1ea6e4 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Экран кулпусун коюп алыңыз"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Экран кулпусун коюу"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Жеке мейкиндикти колдонуу үчүн бул түзмөктүн экранын кулпулаңыз"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Колдонмо учурда жеткиликсиз"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> учурда жеткиликсиз"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> жеткиликсиз"</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index dc15e9afc0cf..fb677cf1e44f 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -2010,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"ຕັ້ງການລັອກໜ້າຈໍ"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"ຕັ້ງການລັອກໜ້າຈໍ"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"ເພື່ອໃຊ້ພື້ນທີ່ສ່ວນບຸກຄົນ, ໃຫ້ຕັ້ງລັອກໜ້າຈໍຢູ່ອຸປະກອນນີ້"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"ເພື່ອລຶບພື້ນທີ່ສ່ວນບຸກຄົນ, ໃຫ້ຕັ້ງການລັອກໜ້າຈໍຢູ່ອຸປະກອນນີ້"</string> <string name="app_blocked_title" msgid="7353262160455028160">"ແອັບບໍ່ສາມາດໃຊ້ໄດ້"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່ສາມາດໃຊ້ໄດ້ໃນຕອນນີ້."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"ບໍ່ສາມາດໃຊ້ <xliff:g id="ACTIVITY">%1$s</xliff:g> ໄດ້"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 8eace89c0a6b..56945c2b1359 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -1748,8 +1748,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Programa užstoja leidimo užklausą, todėl negalima patvirtinti jūsų atsakymo."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Norėdami naudoti funkciją, palieskite ją:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Funkcijų, kurioms bus naudojamas pritaikomumo mygtukas, pasirinkimas"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Funkcijų, kurioms bus naudojami garsumo spartieji klavišai, pasirinkimas"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Paslauga „<xliff:g id="SERVICE_NAME">%s</xliff:g>“ išjungta"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redaguoti sparčiuosius klavišus"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Atlikta"</string> @@ -2013,6 +2012,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Ekrano užrako nustatymas"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Nustatykite ekrano užraktą"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Jei norite naudoti privačią erdvę, nustatykite ekrano užraktą šiame įrenginyje"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Programa nepasiekiama."</string> <string name="app_blocked_message" msgid="542972921087873023">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ šiuo metu nepasiekiama."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"„<xliff:g id="ACTIVITY">%1$s</xliff:g>“ nepasiekiama"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 01fb9da42198..8b271d942193 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -1747,8 +1747,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Kāda lietotne padara atļaujas pieprasījumu nesaprotamu, tāpēc nevar verificēt jūsu atbildi."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Pieskarieties funkcijai, lai sāktu to izmantot"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Izvēlieties funkcijas, ko izmantot ar pieejamības pogu"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Izvēlieties funkcijas, kuras piešķirt skaļuma pogu saīsnei"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Pakalpojums <xliff:g id="SERVICE_NAME">%s</xliff:g> ir izslēgts."</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Rediģēt īsinājumtaustiņus"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gatavs"</string> @@ -2012,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Iestatiet ekrāna bloķēšanu"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Iestatīt ekrāna bloķēšanu"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Lai izmantotu privāto telpu, iestatiet ekrāna bloķēšanu."</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Lietotne nav pieejama"</string> <string name="app_blocked_message" msgid="542972921087873023">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> pašlaik nav pieejama."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nav pieejams"</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index dbc4b757c4a2..a5ce587b688f 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Апликација го прикрива барањето за дозвола, па вашиот одговор не може да се потврди."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Допрете на функција за да почнете да ја користите:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Изберете ги функциите што ќе ги користите со копчето за пристапност"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Изберете ги функциите што ќе ги користите со кратенката за копчињата за јачина на звук"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> е исклучена"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Изменете ги кратенките"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Поставете заклучување екран"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Поставете заклучување екран"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"За да користите „Приватен простор“, поставете заклучување екран на уредов"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Апликацијата не е достапна"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> не е достапна во моментов."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> е недостапна"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 6d60696f40e9..ef9d6c8cba16 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"സ്ക്രീൻ ലോക്ക് സജ്ജീകരിക്കൂ"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"സ്ക്രീൻ ലോക്ക് സജ്ജീകരിക്കൂ"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"സ്വകാര്യ സ്പേസിന്, ഇതിൽ സ്ക്രീൻ ലോക്ക് സജ്ജീകരിക്കൂ"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"ആപ്പ് ലഭ്യമല്ല"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ഇപ്പോൾ ലഭ്യമല്ല."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ലഭ്യമല്ല"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index bf2f78c9c9db..01a175af58fd 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Апп зөвшөөрлийн хүсэлтийг хааж байгаа тул таны хариултыг баталгаажуулах боломжгүй."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Үүнийг ашиглаж эхлэхийн тулд онцлог дээр товшино уу:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Хандалтын товчлуурын тусламжтай ашиглах онцлогуудыг сонгоно уу"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Дууны түвшний товчийн товчлолоор ашиглах онцлогуудыг сонгоно уу"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g>-г унтраалаа"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Товчлолуудыг засах"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Болсон"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Дэлгэцийн түгжээ тохируулах"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Дэлгэцийн түгжээ тохируулах"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Хаалттай орон зайгаа ашиглах бол уг төхөөрөмжид дэлгэцийн түгжээ тохируулна уу"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Апп боломжгүй байна"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> яг одоо боломжгүй байна."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> боломжгүй байна"</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 30403cf0984f..f9b70ff950f1 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"स्क्रीन लॉक सेट करा"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"स्क्रीन लॉक सेट करा"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"तुमची खाजगी स्पेस वापरण्यास, या डिव्हाइसवर स्क्रीन लॉक सेट करा"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"ॲप उपलब्ध नाही"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> आता उपलब्ध नाही."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> उपलब्ध नाही"</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index e17c62bb168e..b30d48de03ae 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Tetapkan kunci skrin"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Tetapkan kunci skrin"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Tetapkan kunci skrin pada peranti untuk menggunakan ruang privasi"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Apl tidak tersedia"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak tersedia sekarang."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> tidak tersedia"</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index 85fb0e9e27d7..b78e2cbacee9 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"ဖန်သားပြင်လော့ခ် သတ်မှတ်ပါ"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"ဖန်သားပြင်လော့ခ် သတ်မှတ်ရန်"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"သင့်သီးသန့်နေရာသုံးရန် ဤစက်၌ ဖန်သားပြင်လော့ခ် သတ်မှတ်ပါ"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"အက်ပ်ကို မရနိုင်ပါ"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကို ယခု မရနိုင်ပါ။"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> မရနိုင်ပါ"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 8feb6e915577..8002e9085897 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"En app dekker forespørselen om tillatelse, så svaret ditt kan ikke bekreftes."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Trykk på en funksjon for å begynne å bruke den:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Velg funksjonene du vil bruke med Tilgjengelighet-knappen"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Velg funksjonene du vil bruke med volumtastsnarveien"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> er slått av"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Endre snarveier"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Ferdig"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Angi en skjermlås"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Angi skjermlås"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"For å bruke det private området, angi en skjermlås på enheten"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Appen er ikke tilgjengelig"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ikke tilgjengelig for øyeblikket."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> er utilgjengelig"</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 36e3254135eb..784cce45346d 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -1216,10 +1216,10 @@ <string name="rating_label" msgid="1837085249662154601">"{rating,plural, =1{{max} मा एक तारा}other{{max} मा # तारा}}"</string> <string name="in_progress" msgid="2149208189184319441">"जारी छ"</string> <string name="whichApplication" msgid="5432266899591255759">"प्रयोग गरेर कारबाही पुरा गर्नुहोस्"</string> - <string name="whichApplicationNamed" msgid="6969946041713975681">"निम्न एपको प्रयोग गरी कारबाही पुरा गर्नुहोस्: %1$s"</string> + <string name="whichApplicationNamed" msgid="6969946041713975681">"%1$s प्रयोग गरी यो कार्य पूरा गर्नुहोस्"</string> <string name="whichApplicationLabel" msgid="7852182961472531728">"पूर्ण कारबाही"</string> <string name="whichViewApplication" msgid="5733194231473132945">"निम्नबाट खोल्नुहोस्"</string> - <string name="whichViewApplicationNamed" msgid="415164730629690105">"निम्न एपमा खोल्नुहोस्: %1$s"</string> + <string name="whichViewApplicationNamed" msgid="415164730629690105">"%1$s मार्फत खोल्नुहोस्"</string> <string name="whichViewApplicationLabel" msgid="7367556735684742409">"खोल्नुहोस्"</string> <string name="whichOpenHostLinksWith" msgid="7645631470199397485">"निम्नमार्फत <xliff:g id="HOST">%1$s</xliff:g> का लिंकहरू खोल्नुहोस्"</string> <string name="whichOpenLinksWith" msgid="1120936181362907258">"निम्नमार्फत लिंकहरू खोल्नुहोस्"</string> @@ -1227,7 +1227,7 @@ <string name="whichOpenHostLinksWithApp" msgid="2401668560768463004">"<xliff:g id="APPLICATION">%2$s</xliff:g> मार्फत <xliff:g id="HOST">%1$s</xliff:g> का लिंकहरू खोल्नुहोस्"</string> <string name="whichGiveAccessToApplicationLabel" msgid="7805857277166106236">"पहुँच दिनुहोस्"</string> <string name="whichEditApplication" msgid="6191568491456092812">"सँग सम्पादन गर्नुहोस्"</string> - <string name="whichEditApplicationNamed" msgid="8096494987978521514">"%1$s सँग सम्पादन गर्नुहोस्"</string> + <string name="whichEditApplicationNamed" msgid="8096494987978521514">"%1$s प्रयोग गरी सम्पादन गर्नुहोस्"</string> <string name="whichEditApplicationLabel" msgid="1463288652070140285">"सम्पादन गर्नुहोस्"</string> <string name="whichSendApplication" msgid="4143847974460792029">"सेयर गर्नुहोस्"</string> <string name="whichSendApplicationNamed" msgid="4470386782693183461">"%1$s सँग सेयर गर्नुहोस्"</string> @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"स्क्रिन लक सेटअप गर्नुहोस्"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"स्क्रिन लक सेटअप गर्नुहोस्"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"निजी स्पेस प्रयोग गर्न यो डिभाइसमा स्क्रिन लक सेटअप गर्नुहोस्"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"एप उपलब्ध छैन"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> अहिले उपलब्ध छैन।"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> उपलब्ध छैन"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 18773f6c1473..6180b1bf54e4 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Schermvergrendeling instellen"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Schermvergrendeling instellen"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Als je je privégedeelte wilt gebruiken, stel je een schermvergrendeling op dit apparaat in"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"App is niet beschikbaar"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is momenteel niet beschikbaar."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> niet beschikbaar"</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 45b6e9ac8e75..e6e20fa4cd40 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ଏକ ଆପ ଅନୁମତି ଅନୁରୋଧକୁ ଅସ୍ପଷ୍ଟ କରୁଛି ତେଣୁ ଆପଣଙ୍କ ଉତ୍ତରକୁ ଯାଞ୍ଚ କରାଯାଇପାରିବ ନାହିଁ।"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ଏକ ଫିଚର୍ ବ୍ୟବହାର କରିବା ଆରମ୍ଭ କରିବାକୁ ଏହାକୁ ଟାପ୍ କରନ୍ତୁ:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ଆକ୍ସେସିବିଲିଟୀ ବଟନ୍ ସହିତ ବ୍ୟବହାର କରିବାକୁ ଫିଚରଗୁଡ଼ିକ ବାଛନ୍ତୁ"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"ଭଲ୍ୟୁମ କୀ ସର୍ଟକଟ ସହିତ ବ୍ୟବହାର କରିବାକୁ ଫିଚରଗୁଡ଼ିକ ବାଛନ୍ତୁ"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ବନ୍ଦ ହୋଇଯାଇଛି"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ସର୍ଟକଟଗୁଡ଼ିକୁ ଏଡିଟ କରନ୍ତୁ"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ହୋଇଗଲା"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"ଏକ ସ୍କ୍ରିନ ଲକ ସେଟ କରନ୍ତୁ"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"ସ୍କ୍ରିନ ଲକ ସେଟ କରନ୍ତୁ"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"ଆପଣଙ୍କ ପ୍ରାଇଭେଟ ସ୍ପେସ ବ୍ୟବହାର କରିବାକୁ ଏହି ଡିଭାଇସରେ ଏକ ସ୍କ୍ରିନ ଲକ ସେଟ କରନ୍ତୁ"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"ଆପ୍ ଉପଲବ୍ଧ ନାହିଁ"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବର୍ତ୍ତମାନ ଉପଲବ୍ଧ ନାହିଁ।"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ଉପଲବ୍ଧ ନାହିଁ"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index c6d0b9fa1d9b..8afb7312ff19 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ਕੋਈ ਐਪ ਇਜਾਜ਼ਤ ਸੰਬੰਧੀ ਬੇਨਤੀ ਨੂੰ ਅਸਪਸ਼ਟ ਕਰ ਰਹੀ ਹੈ, ਇਸ ਲਈ ਤੁਹਾਡੇ ਜਵਾਬ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ਕਿਸੇ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਵਰਤਣਾ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਉਸ \'ਤੇ ਟੈਪ ਕਰੋ:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਨਾਲ ਵਰਤਣ ਲਈ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚੁਣੋ"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"ਅਵਾਜ਼ ਕੁੰਜੀਆਂ ਦੇ ਸ਼ਾਰਟਕੱਟ ਨਾਲ ਵਰਤਣ ਲਈ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚੁਣੋ"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ਨੂੰ ਬੰਦ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ਸ਼ਾਰਟਕੱਟਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ਹੋ ਗਿਆ"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"ਸਕ੍ਰੀਨ ਲਾਕ ਸੈੱਟ ਕਰੋ"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"ਸਕ੍ਰੀਨ ਲਾਕ ਸੈੱਟ ਕਰੋ"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"ਆਪਣੀ ਪ੍ਰਾਈਵੇਟ ਸਪੇਸ ਵਰਤਣ ਲਈ, ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਕ੍ਰੀਨ ਲਾਕ ਸੈੱਟ ਕਰੋ"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"ਐਪ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਐਪ ਇਸ ਵੇਲੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 0ae3bbf5c496..14320ffe59ea 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -1748,8 +1748,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacja zasłania prośbę o uprawnienia, więc nie można zweryfikować Twojej odpowiedzi."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Wybierz funkcję, aby zacząć z niej korzystać:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Wybierz funkcje, których chcesz używać z przyciskiem ułatwień dostępu"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Wybierz funkcje, do których chcesz używać skrótu z przyciskami głośności"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usługa <xliff:g id="SERVICE_NAME">%s</xliff:g> została wyłączona"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edytuj skróty"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string> @@ -2013,6 +2012,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Ustaw blokadę ekranu"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Ustaw blokadę ekranu"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Aby korzystać z przestrzeni prywatnej, ustaw na tym urządzeniu blokadę ekranu"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Aplikacja jest niedostępna"</string> <string name="app_blocked_message" msgid="542972921087873023">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> jest obecnie niedostępna."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> – brak dostępu"</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index e025d19879d7..e8e125c37a1f 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -1747,8 +1747,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Um app está ocultando a solicitação de permissão e impedindo a verificação da sua resposta."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toque em um recurso para começar a usá-lo:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escolha recursos para usar com o botão de acessibilidade"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Escolha recursos para usar com o atalho das teclas de volume"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"O <xliff:g id="SERVICE_NAME">%s</xliff:g> foi desativado"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string> @@ -2012,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Defina um bloqueio de tela"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Definir bloqueio de tela"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Para usar o espaço privado, defina um bloqueio de tela neste dispositivo"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"O app não está disponível"</string> <string name="app_blocked_message" msgid="542972921087873023">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível no momento."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> indisponível"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 28c130c42fe4..910c5cf03f42 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -2011,6 +2011,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Defina um bloqueio de ecrã"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Definir bloqueio de ecrã"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Defina um bloqueio para usar o espaço privado"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"Para eliminar o espaço privado, defina um bloqueio de ecrã neste dispositivo"</string> <string name="app_blocked_title" msgid="7353262160455028160">"A app não está disponível"</string> <string name="app_blocked_message" msgid="542972921087873023">"De momento, a app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> indisponível"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index e025d19879d7..e8e125c37a1f 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -1747,8 +1747,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Um app está ocultando a solicitação de permissão e impedindo a verificação da sua resposta."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toque em um recurso para começar a usá-lo:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escolha recursos para usar com o botão de acessibilidade"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Escolha recursos para usar com o atalho das teclas de volume"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"O <xliff:g id="SERVICE_NAME">%s</xliff:g> foi desativado"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string> @@ -2012,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Defina um bloqueio de tela"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Definir bloqueio de tela"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Para usar o espaço privado, defina um bloqueio de tela neste dispositivo"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"O app não está disponível"</string> <string name="app_blocked_message" msgid="542972921087873023">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível no momento."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> indisponível"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 7e5e7c0d900a..85f859240b7f 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -1747,8 +1747,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"O aplicație blochează solicitarea de permisiune, așa că răspunsul nu se poate verifica."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Atinge o funcție ca să începi să o folosești:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Alege funcțiile pe care să le folosești cu butonul de accesibilitate"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Alege funcțiile pentru comanda rapidă a butoanelor de volum"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> a fost dezactivat"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editează comenzile rapide"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gata"</string> @@ -2012,6 +2011,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Setează o blocare a ecranului"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Setează blocarea ecranului"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Ca să folosești spațiul privat, setează blocarea ecranului pe acest dispozitiv"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"Ca să ștergi spațiul privat, setează o blocare a ecranului pe acest dispozitiv"</string> <string name="app_blocked_title" msgid="7353262160455028160">"Aplicația nu este disponibilă"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu este disponibilă momentan."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nu este disponibilă"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 3c374ef5de28..29b9d171618b 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -2012,6 +2012,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Настройте блокировку экрана"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Настроить блокировку экрана"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Чтобы использовать частное пространство, настройте блокировку экрана на этом устройстве."</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Приложение недоступно"</string> <string name="app_blocked_message" msgid="542972921087873023">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" сейчас недоступно."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"Недоступно: <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index af835d92bf71..acd6d432d9ad 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -1057,7 +1057,7 @@ <string name="lockscreen_access_pattern_cell_added_verbose" msgid="2931364927622563465">"<xliff:g id="CELL_INDEX">%1$s</xliff:g> කොටුව එකතු කරන ලදි"</string> <string name="lockscreen_access_pattern_detected" msgid="3931150554035194012">"රටාව සම්පූර්ණයි"</string> <string name="lockscreen_access_pattern_area" msgid="1288780416685002841">"රටා ප්රදේශය."</string> - <string name="keyguard_accessibility_widget_changed" msgid="7298011259508200234">"%1$s. %3$d න් %2$d විජටය."</string> + <string name="keyguard_accessibility_widget_changed" msgid="7298011259508200234">"%%1$s. %%3$d න් %%2$d විජටය."</string> <string name="keyguard_accessibility_add_widget" msgid="8245795023551343672">"විජටය එක් කරන්න."</string> <string name="keyguard_accessibility_widget_empty_slot" msgid="544239307077644480">"හිස්"</string> <string name="keyguard_accessibility_unlock_area_expanded" msgid="7768634718706488951">"අගුළු අරින ප්රදේශය විදහා ඇත."</string> @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"යෙදුමක් අවසර ඉල්ලීම අඳුරු කරන බැවින්, ඔබේ ප්රතිචාරය සත්යාපනය කළ නොහැක."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"එය භාවිත කිරීම ආරම්භ කිරීමට විශේෂාංගයක් තට්ටු කරන්න:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ප්රවේශ්යතා බොත්තම සමග භාවිත කිරීමට විශේෂාංග තෝරා ගන්න"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"හඬ පරිමා යතුරු කෙටිමග සමග භාවිත කිරීමට විශේෂාංග තෝරා ගන්න"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ක්රියාවිරහිත කර ඇත"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"කෙටිමං සංස්කරණ කරන්න"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"නිමයි"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"තිර අගුලක් සකසන්න"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"තිර අගුල සකසන්න"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"ඔබේ රහසිගත අවකාශය භාවිතා කිරීමට, මෙම උපාංගයේ තිර අගුලක් සකසන්න"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"යෙදුම ලබා ගත නොහැකිය"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> මේ දැන් ලබා ගත නොහැකිය."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> නොතිබේ"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index 7185bcdb0de6..07b44f903875 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -2012,6 +2012,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Nastavte zámku obrazovky"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Nastaviť zámku obrazovky"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Ak chcete používať súkromný priestor, nastavte v tomto zariadení zámku obrazovky"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Aplikácia nie je dostupná"</string> <string name="app_blocked_message" msgid="542972921087873023">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> nie je teraz dostupná."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nie je k dispozícii"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index e67bf9c910a3..f3b0da43f0bf 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -2012,6 +2012,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Nastavitev zaklepanja zaslona"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Nastavite zaklepanje zaslona"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Če želite uporabljati zasebni prostor, v tej napravi nastavite zaklepanje zaslona"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija ni na voljo"</string> <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno ni na voljo."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"»<xliff:g id="ACTIVITY">%1$s</xliff:g>« ni na voljo"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index d8fe10944e2e..badb90de2187 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Një aplikacion po fsheh kërkesën për leje, prandaj përgjigja jote nuk mund të verifikohet."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Trokit te një veçori për të filluar ta përdorësh atë:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Zgjidh veçoritë që do të përdorësh me butonin e qasshmërisë"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Zgjidh veçoritë që do të përdorësh me shkurtoren e tasteve të volumit"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> është çaktivizuar"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redakto shkurtoret"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"U krye"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Cakto një kyçje ekrani"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Cakto kyçjen e ekranit"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Për të përdorur hapësirën private, cakto një kyçje ekrani në këtë pajisje"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Aplikacioni nuk ofrohet"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk ofrohet për momentin."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nuk ofrohet"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index f5988c282e36..d38dd12465e1 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -2011,6 +2011,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Подесите откључавање екрана"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Подеси откључавање екрана"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Да бисте користили приватни простор, подесите откључавање екрана на овом уређају"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Апликација није доступна"</string> <string name="app_blocked_message" msgid="542972921087873023">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> тренутно није доступна."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> – није доступно"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 9bde6afc80f8..9b7f3a123004 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"En app döljer behörighetsbegäran så det går inte att verifiera svaret."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tryck på funktioner som du vill aktivera:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Välj vilka funktioner du vill använda med hjälp av tillgänglighetsknappen"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Välj funktioner att använda med hjälp av volymknappskortkommandot"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> har inaktiverats"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redigera genvägar"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klar"</string> @@ -2011,6 +2010,8 @@ <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> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <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> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index c286eeb48d2c..e1123af31b16 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Programu inazuia ombi la ruhusa kwa hivyo jibu lako haliwezi kuthibitishwa."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Gusa kipengele ili uanze kukitumia:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Chagua vipengele vya kutumia na kitufe cha zana za ufikivu"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Chagua vipengele vya kutumia kupitia njia ya mkato ya vitufe vya sauti"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Huduma ya <xliff:g id="SERVICE_NAME">%s</xliff:g> imezimwa"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kubadilisha njia za mkato"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Nimemaliza"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Weka mbinu ya kufunga skrini"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Weka mbinu ya kufunga skrini"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Ili utumie sehemu ya faragha, weka mbinu ya kufunga skrini kwenye kifaa hiki"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Programu haipatikani"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> haipatikani hivi sasa."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> haipatikani"</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 626205e42483..f167eb798ced 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"திரைப் பூட்டை அமையுங்கள்"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"திரைப் பூட்டை அமை"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"ரகசிய இடத்தைப் பயன்படுத்த, சாதனத்தில் திரைப் பூட்டை அமையுங்கள்"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"இந்த ஆப்ஸ் இப்போது கிடைப்பதில்லை"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் இப்போது கிடைப்பதில்லை."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> இல்லை"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index db19868b37dd..1f8a2f7dfcc9 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -2010,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"స్క్రీన్ లాక్ను సెట్ చేయండి"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"స్క్రీన్ లాక్ను సెట్ చేయండి"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"మీ ప్రైవేట్ స్పేస్ను ఉపయోగించడానికి, ఈ పరికరంలో స్క్రీన్ లాక్ సెట్ చేయండి"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"ప్రైవేట్ స్పేస్ను తొలగించడానికి, ఈ పరికరంలో స్క్రీన్ లాక్ను సెట్ చేయండి"</string> <string name="app_blocked_title" msgid="7353262160455028160">"యాప్ అందుబాటులో లేదు"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ప్రస్తుతం అందుబాటులో లేదు."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> అందుబాటులో లేదు"</string> @@ -2152,7 +2153,7 @@ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"సరే"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ఆఫ్ చేయండి"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"మరింత తెలుసుకోండి"</string> - <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12లో Android అనుకూల నోటిఫికేషన్లను, మెరుగైన నోటిఫికేషన్లు రీప్లేస్ చేశాయి. ఈ ఫీచర్, సూచించిన చర్యలను, రిప్లయిలను చూపించి, మీ నోటిఫికేషన్లను ఆర్గనైజ్ చేస్తుంది.\n\nకాంటాక్ట్ పేర్లు, మెసేజ్లు లాంటి వ్యక్తిగత సమాచారంతో పాటు నోటిఫికేషన్ కంటెంట్ను మెరుగైన నోటిఫికేషన్లు యాక్సెస్ చేస్తాయి. ఫోన్ కాల్స్కు సమాధానమివ్వడం, \'అంతరాయం కలిగించవద్దు\' ఆప్షన్ను కంట్రోల్ చేయడం వంటి నోటిఫికేషన్లను విస్మరించడం లేదా వాటికి ప్రతిస్పందించడం కూడా ఈ ఫీచర్ చేయగలదు."</string> + <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12లో \'మెరుగైన నోటిఫికేషన్లు\', \'Android అనుకూల నోటిఫికేషన్ల\'ను రీప్లేస్ చేశాయి. చేయాల్సిన పనులను, రిప్లయిలను ఈ ఫీచర్ మీకు చూపిస్తుంది. అలాగే మీ నోటిఫికేషన్లను ఆర్గనైజ్ చేస్తుంది. \n\nనోటిఫికేషన్ కంటెంట్ను \'మెరుగైన నోటిఫికేషన్లు\' ఫీచర్ యాక్సెస్ చేయగలదు. కాంటాక్ట్ పేర్లు, మెసేజ్ల వంటి వ్యక్తిగత సమాచారం కూడా ఈ కంటెంట్లో ఉంటుంది. ఈ ఫీచర్, నోటిఫికేషన్లను విస్మరించగలదు (డిస్మిస్ చేయగలదు) లేదా వాటికి ప్రతిస్పందించగలదు (రెస్పాండ్ కాగలదు). ఫోన్ కాల్స్కు సమాధానమివ్వడం, \'అంతరాయం కలిగించవద్దు\' ఆప్షన్ను కంట్రోల్ చేయడం లాంటి పనులు కూడా ఇందులో ఉంటాయి."</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"రొటీన్ మోడ్ సమాచార నోటిఫికేషన్"</string> <string name="dynamic_mode_notification_title" msgid="1388718452788985481">"బ్యాటరీ సేవర్ ఆన్ చేయబడింది"</string> <string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"బ్యాటరీ జీవితకాలాన్ని పొడిగించడానికి బ్యాటరీ వినియోగాన్ని తగ్గించడం"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index b34cf59a2bb8..cc716ea90d14 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"ตั้งล็อกหน้าจอ"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"ตั้งล็อกหน้าจอ"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"หากต้องการใช้พื้นที่ส่วนตัว ให้ตั้งการล็อกหน้าจอในอุปกรณ์นี้"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"แอปไม่พร้อมใช้งาน"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ไม่พร้อมใช้งานในขณะนี้"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ไม่พร้อมใช้งาน"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index b976f204e395..89391208cfa6 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -2010,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Magtakda ng lock ng screen"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Itakda ang lock ng screen"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Para gamitin ang iyong pribadong space, magtakda ng lock ng screen sa device na ito."</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Hindi available ang app"</string> <string name="app_blocked_message" msgid="542972921087873023">"Hindi available sa ngayon ang <xliff:g id="APP_NAME">%1$s</xliff:g>."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"Hindi available ang <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index a015a8f6cca3..85fea5cb44b6 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Bir uygulama, izin isteğini gizlediğinden yanıtınız doğrulanamıyor."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Kullanmaya başlamak için bir özelliğe dokunun:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Erişilebilirlik düğmesiyle kullanılacak özellikleri seçin"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Ses seviyesi tuşları kısayoluyla kullanılacak özellikleri seçin"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kapatıldı"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kısayolları düzenle"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Bitti"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Ekran kilidi ayarlayın"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Ekran kilidi ayarla"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Özel alanı kullanmak için cihazda ekran kilidi ayarlayın"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Uygulama kullanılamıyor"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulaması şu anda kullanılamıyor."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> kullanılamıyor"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index e41d3ce1b925..614925f125c4 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -1748,8 +1748,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Інший додаток перекриває запит на доступ, тому вашу відповідь не вдається підтвердити."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Натисніть функцію, щоб почати використовувати її:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Виберіть функції для кнопки спеціальних можливостей"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Виберіть функції для швидких дій клавішами гучності"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Сервіс <xliff:g id="SERVICE_NAME">%s</xliff:g> вимкнено"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Змінити"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string> @@ -2013,6 +2012,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Налаштуйте блокування екрана"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Налаштувати блокування екрана"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Для доступу до приватного простору налаштуйте блокування екрана"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Додаток недоступний"</string> <string name="app_blocked_message" msgid="542972921087873023">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> зараз недоступний."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"Недоступно: <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index fcfff0faa88c..660068d969ec 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -2010,6 +2010,7 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"اسکرین لاک سیٹ کریں"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"اسکرین لاک سیٹ کریں"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"اپنی نجی اسپیس استعمال کرنے کیلئے، اس آلہ پر اسکرین لاک سیٹ کریں"</string> + <string name="private_space_set_up_screen_lock_for_reset" msgid="7817091386408432097">"پرائیویٹ اسپیس استعمال کرنے کیلئے، اس آلہ پر اسکرین لاک سیٹ کریں"</string> <string name="app_blocked_title" msgid="7353262160455028160">"ایپ دستیاب نہیں ہے"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ابھی دستیاب نہیں ہے۔"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> دستیاب نہیں ہے"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index e9bc805e303a..7bd6175fb172 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Ilova ruxsat olish talabini berkitmoqda, shu sababdan javobingizni tasdiqlash imkonsiz."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Kerakli funksiyani tanlang"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Qulayliklar tugmasi bilan foydalanish uchun funksiyalarni tanlang"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Tovush tugmasi bilan ishga tushiriladigan funksiyalarni tanlang"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> faolsizlantirildi"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Tezkor tugmalarni tahrirlash"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Ekran qulfini sozlash"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Ekran qulfini sozlash"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Maxfiy makon ishlatish uchun bu qurilma ekran qulfini sozlang"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Ilova ishlamayapti"</string> <string name="app_blocked_message" msgid="542972921087873023">"Ayni vaqtda <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi ishlamayapti."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> kanali ish faoliyatida emas"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 510edab26fb4..f084c37cc8b3 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Một ứng dụng đang che khuất yêu cầu quyền này nên chúng tôi không thể xác minh phản hồi của bạn."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Nhấn vào một tính năng để bắt đầu sử dụng:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Chọn các tính năng để dùng với nút hỗ trợ tiếp cận"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Chọn các tính năng để dùng với lối tắt cho phím âm lượng"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> đã bị tắt"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Chỉnh sửa phím tắt"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Xong"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Đặt phương thức khoá màn hình"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Đặt phương thức khoá màn hình"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Để dùng không gian riêng tư, hãy thiết lập một phương thức khoá màn hình trên thiết bị này"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Ứng dụng này không dùng được"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> hiện không dùng được."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"Không hỗ trợ <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index bcb54dcac578..a1c36ab8fa74 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"应用遮挡了权限请求,因此我们无法验证您的回复。"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"点按相应功能即可开始使用:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"选择可通过“无障碍”按钮使用的功能"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"选择可通过音量键快捷方式使用的功能"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"已关闭<xliff:g id="SERVICE_NAME">%s</xliff:g>"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"修改快捷方式"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"设置一种屏锁方式"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"设置屏锁方式"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"若要使用私密空间,请在此设备上设置屏锁方式"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"应用无法使用"</string> <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g>目前无法使用。"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>不可用"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 875eec021f7b..6a5fea7b827b 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"有應用程式阻擋權限要求,因此系統無法驗證你的回應。"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"輕按即可開始使用所需功能:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"選擇要配搭無障礙功能按鈕使用的功能"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"選擇要用音量鍵捷徑的功能"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> 已關閉"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"編輯捷徑"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"設定螢幕鎖定"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"設定螢幕鎖定"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"如要使用私人空間,請在此裝置上設定螢幕鎖定功能"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"無法使用應用程式"</string> <string name="app_blocked_message" msgid="542972921087873023">"目前無法使用「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"無法使用「<xliff:g id="ACTIVITY">%1$s</xliff:g>」"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index efa4c519ee19..bb64ab5be046 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"應用程式遮擋了權限要求,因此系統無法驗證你的回覆。"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"輕觸即可開始使用所需功能:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"選擇要搭配無障礙工具按鈕使用的功能"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"選擇要搭配音量鍵捷徑使用的功能"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"「<xliff:g id="SERVICE_NAME">%s</xliff:g>」已關閉"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"編輯捷徑"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"設定螢幕鎖定功能"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"設定螢幕鎖定功能"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"如要使用私人空間,請在這部裝置設定螢幕鎖定功能"</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"應用程式無法使用"</string> <string name="app_blocked_message" msgid="542972921087873023">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」目前無法使用。"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"無法存取「<xliff:g id="ACTIVITY">%1$s</xliff:g>」"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 67a43611b2f3..0524c0921c91 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -1746,8 +1746,7 @@ <string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"I-app ifihla isicelo semvume ngakho impendulo yakho ayikwazi ukuqinisekiswa."</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Thepha isici ukuqala ukusisebenzisa:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Khetha izici ongazisebenzisa nenkinobho yokufinyeleleka"</string> - <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) --> - <skip /> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="2245540598834891500">"Khetha izakhi ongazisebenzisa nesinqamuleli sokhiye bevolumu"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"I-<xliff:g id="SERVICE_NAME">%s</xliff:g> ivaliwe"</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Hlela izinqamuleli"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Kwenziwe"</string> @@ -2011,6 +2010,8 @@ <string name="set_up_screen_lock_title" msgid="8346083801616474030">"Setha ukukhiya isikrini"</string> <string name="set_up_screen_lock_action_label" msgid="2687634803649209367">"Setha ukukhiya isikrini"</string> <string name="private_space_set_up_screen_lock_message" msgid="1109956797005149814">"Ukuze usebenzise isikhala esigodliwe, setha ukukhiya kwesikrini kule divayisi."</string> + <!-- no translation found for private_space_set_up_screen_lock_for_reset (7817091386408432097) --> + <skip /> <string name="app_blocked_title" msgid="7353262160455028160">"Uhlelo lokusebenza alutholakali"</string> <string name="app_blocked_message" msgid="542972921087873023">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayitholakali khona manje."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"okungatholakali <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index d95309c7bdb6..421b7d2c041d 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -7096,6 +7096,10 @@ <!-- Maximum number of active tasks on a given Desktop Windowing session. Set to 0 for unlimited. --> <integer name="config_maxDesktopWindowingActiveTasks">0</integer> + <!-- Whether a display enters desktop mode by default when the windowing mode of the display's + root TaskDisplayArea is set to WINDOWING_MODE_FREEFORM. --> + <bool name="config_enterDesktopByDefaultOnFreeformDisplay">false</bool> + <!-- Frame rate compatibility value for Wallpaper FRAME_RATE_COMPATIBILITY_MIN (102) is used by default for lower power consumption --> <integer name="config_wallpaperFrameRateCompatibility">102</integer> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index dc99634ddabc..579dc91d2ca1 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1509,7 +1509,7 @@ please see styles_device_defaults.xml. </style> <!-- @hide --> - <style name="PointerIconVectorStyleFillYellow"> + <style name="PointerIconVectorStyleFillRed"> <item name="pointerIconVectorFill">#F55E57</item> <item name="pointerIconVectorFillInverse">#F55E57</item> </style> @@ -1527,6 +1527,12 @@ please see styles_device_defaults.xml. </style> <!-- @hide --> + <style name="PointerIconVectorStyleFillPurple"> + <item name="pointerIconVectorFill">#AD72FF</item> + <item name="pointerIconVectorFillInverse">#AD72FF</item> + </style> + + <!-- @hide --> <style name="PointerIconVectorStyleStrokeWhite"> <item name="pointerIconVectorStroke">@color/white</item> <item name="pointerIconVectorStrokeInverse">@color/black</item> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index b80947d9f6e7..039665982482 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1705,9 +1705,10 @@ <java-symbol type="style" name="VectorPointer" /> <java-symbol type="style" name="PointerIconVectorStyleFillBlack" /> <java-symbol type="style" name="PointerIconVectorStyleFillGreen" /> - <java-symbol type="style" name="PointerIconVectorStyleFillYellow" /> + <java-symbol type="style" name="PointerIconVectorStyleFillRed" /> <java-symbol type="style" name="PointerIconVectorStyleFillPink" /> <java-symbol type="style" name="PointerIconVectorStyleFillBlue" /> + <java-symbol type="style" name="PointerIconVectorStyleFillPurple" /> <java-symbol type="attr" name="pointerIconVectorFill" /> <java-symbol type="style" name="PointerIconVectorStyleStrokeWhite" /> <java-symbol type="style" name="PointerIconVectorStyleStrokeBlack" /> @@ -5542,6 +5543,10 @@ <!-- Maximum number of active tasks on a given Desktop Windowing session. Set to 0 for unlimited. --> <java-symbol type="integer" name="config_maxDesktopWindowingActiveTasks"/> + <!-- Whether a display enters desktop mode by default when the windowing mode of the display's + root TaskDisplayArea is set to WINDOWING_MODE_FREEFORM. --> + <java-symbol type="bool" name="config_enterDesktopByDefaultOnFreeformDisplay" /> + <!-- Frame rate compatibility value for Wallpaper --> <java-symbol type="integer" name="config_wallpaperFrameRateCompatibility" /> diff --git a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java index 77e8a404a0ff..fe54aa8d87f0 100644 --- a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java +++ b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java @@ -30,31 +30,30 @@ import java.util.concurrent.TimeUnit; public class BfsccTestAppCmdService extends Service { private IBfsccTestAppCmdService.Stub mBinder = new IBfsccTestAppCmdService.Stub() { - private final LinkedBlockingQueue<IBinder.IFrozenStateChangeCallback.State> mNotifications = + private final LinkedBlockingQueue<Integer> mNotifications = new LinkedBlockingQueue<>(); @Override public void listenTo(IBinder binder) throws RemoteException { binder.addFrozenStateChangeCallback( - (IBinder who, IBinder.IFrozenStateChangeCallback.State state) - -> mNotifications.offer(state)); + (IBinder who, int state) -> mNotifications.offer(state)); } @Override public boolean[] waitAndConsumeNotifications() { List<Boolean> results = new ArrayList<>(); try { - IBinder.IFrozenStateChangeCallback.State state = - mNotifications.poll(5, TimeUnit.SECONDS); + Integer state = mNotifications.poll(5, TimeUnit.SECONDS); if (state != null) { - results.add(state == IBinder.IFrozenStateChangeCallback.State.FROZEN); + results.add( + state.intValue() == IBinder.FrozenStateChangeCallback.STATE_FROZEN); } } catch (InterruptedException e) { return null; } while (mNotifications.size() > 0) { - results.add(mNotifications.poll() - == IBinder.IFrozenStateChangeCallback.State.FROZEN); + results.add(mNotifications.poll().intValue() + == IBinder.FrozenStateChangeCallback.STATE_FROZEN); } boolean[] convertedResults = new boolean[results.size()]; for (int i = 0; i < results.size(); i++) { diff --git a/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java b/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java index ee2e7e06081e..195a18a5f521 100644 --- a/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java +++ b/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java @@ -52,7 +52,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; /** - * Tests functionality of {@link android.os.IBinder.IFrozenStateChangeCallback}. + * Tests functionality of {@link android.os.IBinder.FrozenStateChangeCallback}. */ @RunWith(AndroidJUnit4.class) @IgnoreUnderRavenwood(blockedBy = ActivityManager.class) @@ -157,7 +157,7 @@ public class BinderFrozenStateChangeNotificationTest { @Test public void onStateChangeNotCalledAfterCallbackRemoved() throws Exception { final LinkedBlockingQueue<Boolean> results = new LinkedBlockingQueue<>(); - IBinder.IFrozenStateChangeCallback callback; + IBinder.FrozenStateChangeCallback callback; if ((callback = createCallback(mBfsccTestAppCmdService.asBinder(), results)) == null) { return; } @@ -171,7 +171,7 @@ public class BinderFrozenStateChangeNotificationTest { public void multipleCallbacks() throws Exception { final LinkedBlockingQueue<Boolean> results1 = new LinkedBlockingQueue<>(); final LinkedBlockingQueue<Boolean> results2 = new LinkedBlockingQueue<>(); - IBinder.IFrozenStateChangeCallback callback1; + IBinder.FrozenStateChangeCallback callback1; if ((callback1 = createCallback(mBfsccTestAppCmdService.asBinder(), results1)) == null) { return; } @@ -197,8 +197,8 @@ public class BinderFrozenStateChangeNotificationTest { public void onStateChangeCalledWithTheRightBinder() throws Exception { final IBinder binder = mBfsccTestAppCmdService.asBinder(); final LinkedBlockingQueue<IBinder> results = new LinkedBlockingQueue<>(); - IBinder.IFrozenStateChangeCallback callback = - (IBinder who, IBinder.IFrozenStateChangeCallback.State state) -> results.offer(who); + IBinder.FrozenStateChangeCallback callback = + (IBinder who, int state) -> results.offer(who); try { binder.addFrozenStateChangeCallback(callback); } catch (UnsupportedOperationException e) { @@ -221,12 +221,12 @@ public class BinderFrozenStateChangeNotificationTest { } } - private IBinder.IFrozenStateChangeCallback createCallback(IBinder binder, Queue<Boolean> queue) + private IBinder.FrozenStateChangeCallback createCallback(IBinder binder, Queue<Boolean> queue) throws RemoteException { try { - final IBinder.IFrozenStateChangeCallback callback = - (IBinder who, IBinder.IFrozenStateChangeCallback.State state) -> - queue.offer(state == IBinder.IFrozenStateChangeCallback.State.FROZEN); + final IBinder.FrozenStateChangeCallback callback = + (IBinder who, int state) -> + queue.offer(state == IBinder.FrozenStateChangeCallback.STATE_FROZEN); binder.addFrozenStateChangeCallback(callback); return callback; } catch (UnsupportedOperationException e) { diff --git a/core/tests/coretests/src/android/window/flags/DesktopModeFlagsTest.java b/core/tests/coretests/src/android/window/flags/DesktopModeFlagsTest.java index 32345e606229..dd406955785b 100644 --- a/core/tests/coretests/src/android/window/flags/DesktopModeFlagsTest.java +++ b/core/tests/coretests/src/android/window/flags/DesktopModeFlagsTest.java @@ -16,7 +16,7 @@ package android.window.flags; -import static android.window.flags.DesktopModeFlags.DESKTOP_WINDOWING_MODE; +import static android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODE; import static com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE; import static com.android.window.flags.Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS; @@ -75,7 +75,7 @@ public class DesktopModeFlagsTest { public void isEnabled_devOptionFlagDisabled_overrideOff_featureFlagOn_returnsTrue() { setOverride(OVERRIDE_OFF_SETTING); // In absence of dev options, follow flag - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isTrue(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isTrue(); } @@ -84,7 +84,7 @@ public class DesktopModeFlagsTest { public void isEnabled_devOptionFlagDisabled_overrideOn_featureFlagOff_returnsFalse() { setOverride(OVERRIDE_ON_SETTING); - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isFalse(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isFalse(); } @Test @@ -93,7 +93,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_UNSET_SETTING); // For overridableFlag, for unset overrides, follow flag - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isTrue(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isTrue(); } @Test @@ -103,7 +103,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_UNSET_SETTING); // For overridableFlag, for unset overrides, follow flag - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isFalse(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isFalse(); } @Test @@ -112,7 +112,7 @@ public class DesktopModeFlagsTest { setOverride(null); // For overridableFlag, in absence of overrides, follow flag - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isTrue(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isTrue(); } @Test @@ -122,7 +122,7 @@ public class DesktopModeFlagsTest { setOverride(null); // For overridableFlag, in absence of overrides, follow flag - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isFalse(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isFalse(); } @Test @@ -131,7 +131,7 @@ public class DesktopModeFlagsTest { setOverride(-2); // For overridableFlag, for unrecognized overrides, follow flag - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isTrue(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isTrue(); } @Test @@ -141,7 +141,7 @@ public class DesktopModeFlagsTest { setOverride(-2); // For overridableFlag, for unrecognizable overrides, follow flag - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isFalse(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isFalse(); } @Test @@ -150,7 +150,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_OFF_SETTING); // For overridableFlag, follow override if they exist - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isFalse(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isFalse(); } @Test @@ -160,7 +160,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_ON_SETTING); // For overridableFlag, follow override if they exist - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isTrue(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isTrue(); } @Test @@ -169,12 +169,12 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_OFF_SETTING); // For overridableFlag, follow override if they exist - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isFalse(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isFalse(); setOverride(OVERRIDE_ON_SETTING); // Keep overrides constant through the process - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isFalse(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isFalse(); } @Test @@ -184,12 +184,12 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_ON_SETTING); // For overridableFlag, follow override if they exist - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isTrue(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isTrue(); setOverride(OVERRIDE_OFF_SETTING); // Keep overrides constant through the process - assertThat(DESKTOP_WINDOWING_MODE.isEnabled(mContext)).isTrue(); + assertThat(ENABLE_DESKTOP_WINDOWING_MODE.isEnabled()).isTrue(); } @Test @@ -199,7 +199,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_UNSET_SETTING); // For unset overrides, follow flag - assertThat(DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)).isTrue(); + assertThat(DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()).isTrue(); } @Test @@ -208,7 +208,7 @@ public class DesktopModeFlagsTest { public void isEnabled_dwFlagOn_overrideUnset_featureFlagOff_returnsFalse() { setOverride(OVERRIDE_UNSET_SETTING); // For unset overrides, follow flag - assertThat(DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)).isFalse(); + assertThat(DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()).isFalse(); } @Test @@ -221,7 +221,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_ON_SETTING); // When toggle override matches its default state (dw flag), don't override flags - assertThat(DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)).isTrue(); + assertThat(DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()).isTrue(); } @Test @@ -231,7 +231,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_ON_SETTING); // When toggle override matches its default state (dw flag), don't override flags - assertThat(DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)).isFalse(); + assertThat(DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()).isFalse(); } @Test @@ -244,7 +244,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_OFF_SETTING); // Follow override if they exist, and is not equal to default toggle state (dw flag) - assertThat(DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)).isTrue(); + assertThat(DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()).isTrue(); } @Test @@ -254,7 +254,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_OFF_SETTING); // Follow override if they exist, and is not equal to default toggle state (dw flag) - assertThat(DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)).isFalse(); + assertThat(DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()).isFalse(); } @Test @@ -267,7 +267,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_UNSET_SETTING); // For unset overrides, follow flag - assertThat(DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)).isTrue(); + assertThat(DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()).isTrue(); } @Test @@ -280,7 +280,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_UNSET_SETTING); // For unset overrides, follow flag - assertThat(DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)).isFalse(); + assertThat(DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()).isFalse(); } @Test @@ -293,7 +293,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_ON_SETTING); // Follow override if they exist, and is not equal to default toggle state (dw flag) - assertThat(DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)).isTrue(); + assertThat(DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()).isTrue(); } @Test @@ -306,7 +306,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_ON_SETTING); // Follow override if they exist, and is not equal to default toggle state (dw flag) - assertThat(DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)).isFalse(); + assertThat(DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()).isFalse(); } @Test @@ -319,7 +319,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_OFF_SETTING); // When toggle override matches its default state (dw flag), don't override flags - assertThat(DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)).isTrue(); + assertThat(DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()).isTrue(); } @Test @@ -332,7 +332,7 @@ public class DesktopModeFlagsTest { setOverride(OVERRIDE_OFF_SETTING); // When toggle override matches its default state (dw flag), don't override flags - assertThat(DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(mContext)).isFalse(); + assertThat(DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()).isFalse(); } private void setOverride(Integer setting) { diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java index 5af272c8bead..d6b2a782bc0c 100644 --- a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java +++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java @@ -117,6 +117,7 @@ public class InteractionJankMonitorTest { // Simulate a trace session and see if begin / end are invoked. assertThat(monitor.begin(mSurfaceControl, mActivity.getApplicationContext(), + mActivity.getMainThreadHandler(), Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue(); verify(tracker).begin(); assertThat(monitor.end(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue(); diff --git a/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java b/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java index 397cdcf6acdd..67de25eede42 100644 --- a/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java @@ -125,12 +125,12 @@ public class BinderDeathDispatcherTest { } @Override - public void addFrozenStateChangeCallback(IFrozenStateChangeCallback callback) + public void addFrozenStateChangeCallback(FrozenStateChangeCallback callback) throws RemoteException { } @Override - public boolean removeFrozenStateChangeCallback(IFrozenStateChangeCallback callback) { + public boolean removeFrozenStateChangeCallback(FrozenStateChangeCallback callback) { return false; } diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java index c52f700ef4f6..90723b2f1493 100644 --- a/graphics/java/android/graphics/BLASTBufferQueue.java +++ b/graphics/java/android/graphics/BLASTBufferQueue.java @@ -17,6 +17,7 @@ package android.graphics; import android.annotation.NonNull; +import android.os.IBinder; import android.view.Surface; import android.view.SurfaceControl; @@ -47,6 +48,7 @@ public final class BLASTBufferQueue { long frameNumber); private static native void nativeSetTransactionHangCallback(long ptr, TransactionHangCallback callback); + private static native void nativeSetApplyToken(long ptr, IBinder applyToken); public interface TransactionHangCallback { void onTransactionHang(String reason); @@ -204,4 +206,8 @@ public final class BLASTBufferQueue { public void setTransactionHangCallback(TransactionHangCallback hangCallback) { nativeSetTransactionHangCallback(mNativeObject, hangCallback); } + + public void setApplyToken(IBinder applyToken) { + nativeSetApplyToken(mNativeObject, applyToken); + } } diff --git a/graphics/java/android/graphics/Gainmap.java b/graphics/java/android/graphics/Gainmap.java index 0a6fb8424094..63ca3b8313ce 100644 --- a/graphics/java/android/graphics/Gainmap.java +++ b/graphics/java/android/graphics/Gainmap.java @@ -18,7 +18,9 @@ package android.graphics; import android.annotation.FlaggedApi; import android.annotation.FloatRange; +import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; @@ -26,6 +28,9 @@ import com.android.graphics.hwui.flags.Flags; import libcore.util.NativeAllocationRegistry; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Gainmap represents a mechanism for augmenting an SDR image to produce an HDR one with variable * display adjustment capability. It is a combination of a set of metadata describing how to apply @@ -83,6 +88,27 @@ import libcore.util.NativeAllocationRegistry; */ public final class Gainmap implements Parcelable { + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"GAINMAP_DIRECTION_"}, + value = {GAINMAP_DIRECTION_SDR_TO_HDR, + GAINMAP_DIRECTION_HDR_TO_SDR}) + public @interface GainmapDirection {} + + /** + * The gainmap will be applied as if the base image were SDR, and fully applying the gainmap + * results in an HDR image. + */ + @FlaggedApi(Flags.FLAG_ISO_GAINMAP_APIS) + public static final int GAINMAP_DIRECTION_SDR_TO_HDR = 0; + + /** + * The gainmap will be applied as if the base image were HDR, and fully applying the gainmap + * results in an SDR image. + */ + @FlaggedApi(Flags.FLAG_ISO_GAINMAP_APIS) + public static final int GAINMAP_DIRECTION_HDR_TO_SDR = 1; + // Use a Holder to allow static initialization of Gainmap in the boot image. private static class NoImagePreloadHolder { public static final NativeAllocationRegistry sRegistry = @@ -252,8 +278,9 @@ public final class Gainmap implements Parcelable { } /** - * Sets the hdr/sdr ratio at which point the gainmap is fully applied. - * @param max The hdr/sdr ratio at which the gainmap is fully applied. Must be >= 1.0f + * Sets the hdr/sdr ratio at which point applying the gainmap results in an HDR rendition. + * @param max The hdr/sdr ratio at which point applying the gainmap results in an HDR rendition. + * Must be >= 1.0f */ public void setDisplayRatioForFullHdr(@FloatRange(from = 1.0f) float max) { if (!Float.isFinite(max) || max < 1f) { @@ -264,7 +291,7 @@ public final class Gainmap implements Parcelable { } /** - * Gets the hdr/sdr ratio at which point the gainmap is fully applied. + * Gets the hdr/sdr ratio at which point applying the gainmap results in an HDR rendition */ @NonNull public float getDisplayRatioForFullHdr() { @@ -272,8 +299,9 @@ public final class Gainmap implements Parcelable { } /** - * Sets the hdr/sdr ratio below which only the SDR image is displayed. - * @param min The minimum hdr/sdr ratio at which to begin applying the gainmap. Must be >= 1.0f + * Sets the hdr/sdr ratio below which applying the gainmap results in an SDR rendition. + * @param min The minimum hdr/sdr ratio at which point applying the gainmap results in an SDR + * rendition. Must be >= 1.0f */ public void setMinDisplayRatioForHdrTransition(@FloatRange(from = 1.0f) float min) { if (!Float.isFinite(min) || min < 1f) { @@ -284,7 +312,7 @@ public final class Gainmap implements Parcelable { } /** - * Gets the hdr/sdr ratio below which only the SDR image is displayed. + * Gets the hdr/sdr ratio below which applying the gainmap results in an SDR rendition. */ @NonNull public float getMinDisplayRatioForHdrTransition() { @@ -292,6 +320,55 @@ public final class Gainmap implements Parcelable { } /** + * Sets the colorspace that the gainmap math should be applied in. + * Only the primaries are what is relevant for applying the gainmap. The transfer and range + * characteritics are ignored. + * + * If the supplied ColorSpace is null, then applying the gainmap will be done using the color + * gamut of the base image. + */ + @FlaggedApi(Flags.FLAG_ISO_GAINMAP_APIS) + public void setAlternativeImagePrimaries(@Nullable ColorSpace colorSpace) { + long colorSpaceInstance = colorSpace == null ? 0 : colorSpace.getNativeInstance(); + nSetAlternativeColorSpace(mNativePtr, colorSpaceInstance); + } + + /** + * Gets the colorspace that the gainmap math should be applied in. + * Only the primaries are what is relevant for applying the gainmap. The transfer and range + * characteritics are ignored. + * + * If the returned ColorSpace is null, then applying the gainmap will be done using the color + * gamut of the base image. + */ + @FlaggedApi(Flags.FLAG_ISO_GAINMAP_APIS) + @Nullable + public ColorSpace getAlternativeImagePrimaries() { + return nGetAlternativeColorSpace(mNativePtr); + } + + /** + * Sets the direction that the gainmap math should be applied in. + */ + @FlaggedApi(Flags.FLAG_ISO_GAINMAP_APIS) + public void setGainmapDirection(@GainmapDirection int direction) { + if (direction != GAINMAP_DIRECTION_SDR_TO_HDR + && direction != GAINMAP_DIRECTION_HDR_TO_SDR) { + throw new IllegalArgumentException("Invalid gainmap direction: " + direction); + } + nSetDirection(mNativePtr, direction); + } + + /** + * Gets the direction that the gainmap math should be applied in. + */ + @FlaggedApi(Flags.FLAG_ISO_GAINMAP_APIS) + public @GainmapDirection int getGainmapDirection() { + return nGetDirection(mNativePtr); + } + + + /** * No special parcel contents. */ @Override @@ -361,6 +438,10 @@ public final class Gainmap implements Parcelable { private static native void nSetDisplayRatioSdr(long ptr, float min); private static native float nGetDisplayRatioSdr(long ptr); + private static native void nSetAlternativeColorSpace(long ptr, long colorSpacePtr); + private static native ColorSpace nGetAlternativeColorSpace(long ptr); + private static native void nSetDirection(long ptr, int direction); + private static native int nGetDirection(long ptr); private static native void nWriteGainmapToParcel(long ptr, Parcel dest); private static native void nReadGainmapFromParcel(long ptr, Parcel src); } diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_dialog_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_dialog_background.xml index e7c89d1f9c76..f37fb8dbe118 100644 --- a/libs/WindowManager/Shell/res/drawable/letterbox_education_dialog_background.xml +++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_dialog_background.xml @@ -17,6 +17,6 @@ <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/colorSurface"/> + <solid android:color="?androidprv:attr/materialColorSurfaceContainerHigh"/> <corners android:radius="@dimen/letterbox_education_dialog_corner_radius"/> </shape>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml index 72ebef625ffc..3fdd059ca982 100644 --- a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml +++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml @@ -32,7 +32,7 @@ </item> <item> <shape android:shape="rectangle"> - <solid android:color="?androidprv:attr/colorAccentPrimaryVariant"/> + <solid android:color="?androidprv:attr/materialColorPrimary"/> <corners android:radius="@dimen/letterbox_education_dialog_button_radius"/> <padding android:left="@dimen/letterbox_education_dialog_horizontal_padding" android:top="@dimen/letterbox_education_dialog_vertical_padding" diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml index 4a1e7485ed19..67929dfc5f71 100644 --- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml +++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml @@ -18,10 +18,13 @@ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:width="@dimen/letterbox_education_dialog_title_icon_width" android:height="@dimen/letterbox_education_dialog_title_icon_height" - android:viewportWidth="45" - android:viewportHeight="44"> - - <path - android:fillColor="?androidprv:attr/colorAccentPrimaryVariant" - android:pathData="M11 40H19C19 42.2 17.2 44 15 44C12.8 44 11 42.2 11 40ZM7 38L23 38V34L7 34L7 38ZM30 19C30 26.64 24.68 30.72 22.46 32L7.54 32C5.32 30.72 0 26.64 0 19C0 10.72 6.72 4 15 4C23.28 4 30 10.72 30 19ZM26 19C26 12.94 21.06 8 15 8C8.94 8 4 12.94 4 19C4 23.94 6.98 26.78 8.7 28L21.3 28C23.02 26.78 26 23.94 26 19ZM39.74 14.74L37 16L39.74 17.26L41 20L42.26 17.26L45 16L42.26 14.74L41 12L39.74 14.74ZM35 12L36.88 7.88L41 6L36.88 4.12L35 0L33.12 4.12L29 6L33.12 7.88L35 12Z" /> + android:viewportWidth="32" + android:viewportHeight="32"> + <group> + <clip-path + android:pathData="M0,0h32v32h-32z"/> + <path + android:pathData="M5.867,22.667C4.489,21.844 3.389,20.733 2.567,19.333C1.744,17.933 1.333,16.378 1.333,14.667C1.333,12.067 2.233,9.867 4.033,8.067C5.856,6.244 8.067,5.333 10.667,5.333C13.267,5.333 15.467,6.244 17.267,8.067C19.089,9.867 20,12.067 20,14.667C20,16.378 19.589,17.933 18.767,19.333C17.944,20.733 16.844,21.844 15.467,22.667H5.867ZM6.667,20H14.667C15.511,19.356 16.167,18.578 16.633,17.667C17.1,16.733 17.333,15.733 17.333,14.667C17.333,12.822 16.678,11.256 15.367,9.967C14.078,8.656 12.511,8 10.667,8C8.822,8 7.244,8.656 5.933,9.967C4.644,11.256 4,12.822 4,14.667C4,15.733 4.233,16.733 4.7,17.667C5.167,18.578 5.822,19.356 6.667,20ZM7.2,26.667C6.822,26.667 6.5,26.544 6.233,26.3C5.989,26.033 5.867,25.711 5.867,25.333C5.867,24.956 5.989,24.644 6.233,24.4C6.5,24.133 6.822,24 7.2,24H14.133C14.511,24 14.822,24.133 15.067,24.4C15.333,24.644 15.467,24.956 15.467,25.333C15.467,25.711 15.333,26.033 15.067,26.3C14.822,26.544 14.511,26.667 14.133,26.667H7.2ZM10.667,30.667C9.933,30.667 9.3,30.411 8.767,29.9C8.256,29.367 8,28.733 8,28H13.333C13.333,28.733 13.067,29.367 12.533,29.9C12.022,30.411 11.4,30.667 10.667,30.667ZM24.667,13.367C24.667,11.7 24.078,10.278 22.9,9.1C21.722,7.922 20.3,7.333 18.633,7.333C20.3,7.333 21.722,6.756 22.9,5.6C24.078,4.422 24.667,3 24.667,1.333C24.667,3 25.244,4.422 26.4,5.6C27.578,6.756 29,7.333 30.667,7.333C29,7.333 27.578,7.922 26.4,9.1C25.244,10.278 24.667,11.7 24.667,13.367Z" + android:fillColor="?androidprv:attr/materialColorPrimary"/> + </group> </vector>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml index 22a8f39ca687..29e58a12f5a6 100644 --- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml +++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml @@ -15,16 +15,16 @@ ~ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="@dimen/letterbox_education_dialog_icon_width" - android:height="@dimen/letterbox_education_dialog_icon_height" - android:viewportWidth="40" + android:width="32dp" + android:height="32dp" + android:viewportWidth="32" android:viewportHeight="32"> <path + android:pathData="M4,4C2.527,4 1.333,5.194 1.333,6.667V25.333C1.333,26.806 2.527,28 4,28H28C29.472,28 30.666,26.806 30.666,25.333V6.667C30.666,5.194 29.472,4 28,4H4ZM28,6.667H4V25.333H28V6.667Z" android:fillColor="@color/letterbox_education_text_secondary" - android:fillType="evenOdd" - android:pathData="M4 0C1.79086 0 0 1.79086 0 4V28C0 30.2091 1.79086 32 4 32H36C38.2091 32 40 30.2091 40 28V4C40 1.79086 38.2091 0 36 0H4ZM36 4H4V28H36V4Z" /> + android:fillType="evenOdd" /> <path - android:fillColor="@color/letterbox_education_text_secondary" - android:pathData="M19.98 8L17.16 10.82L20.32 14L12 14V18H20.32L17.14 21.18L19.98 24L28 16.02L19.98 8Z" /> + android:pathData="M17.32,10.667L15.44,12.547L17.546,14.667L9.333,14.667L9.333,17.333H17.546L15.426,19.453L17.32,21.333L22.666,16.013L17.32,10.667Z" + android:fillColor="@color/letterbox_education_text_secondary" /> </vector> diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml index 15e65f716b20..6a766d37fcdb 100644 --- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml +++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml @@ -17,10 +17,10 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="@dimen/letterbox_education_dialog_icon_width" android:height="@dimen/letterbox_education_dialog_icon_height" - android:viewportWidth="40" - android:viewportHeight="32"> + android:viewportWidth="28" + android:viewportHeight="22"> <path android:fillColor="@color/letterbox_education_text_secondary" - android:pathData="M40 28L40 4C40 1.8 38.2 -7.86805e-08 36 -1.74846e-07L26 -6.11959e-07C23.8 -7.08124e-07 22 1.8 22 4L22 28C22 30.2 23.8 32 26 32L36 32C38.2 32 40 30.2 40 28ZM14 28L4 28L4 4L14 4L14 28ZM18 28L18 4C18 1.8 16.2 -1.04033e-06 14 -1.1365e-06L4 -1.57361e-06C1.8 -1.66978e-06 -7.86805e-08 1.8 -1.74846e-07 4L-1.22392e-06 28C-1.32008e-06 30.2 1.8 32 4 32L14 32C16.2 32 18 30.2 18 28Z" /> + android:pathData="M27.333,19L27.333,3C27.333,1.533 26.133,0.333 24.666,0.333L18,0.333C16.533,0.333 15.333,1.533 15.333,3L15.333,19C15.333,20.467 16.533,21.667 18,21.667L24.666,21.667C26.133,21.667 27.333,20.467 27.333,19ZM10,19L3.333,19L3.333,3L10,3L10,19ZM12.666,19L12.666,3C12.666,1.533 11.466,0.333 10,0.333L3.333,0.333C1.866,0.333 0.666,1.533 0.666,3L0.666,19C0.666,20.467 1.866,21.667 3.333,21.667L10,21.667C11.466,21.667 12.666,20.467 12.666,19Z" /> </vector>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml index 1f125148775d..4207482260ba 100644 --- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml +++ b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml @@ -32,7 +32,7 @@ </item> <item> <shape android:shape="rectangle"> - <solid android:color="?androidprv:attr/colorAccentPrimaryVariant"/> + <solid android:color="?androidprv:attr/materialColorPrimary"/> <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/> <padding android:left="@dimen/letterbox_restart_dialog_horizontal_padding" android:top="@dimen/letterbox_restart_dialog_vertical_padding" diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dialog_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dialog_background.xml index e3c18a2db66f..72cfeefceffb 100644 --- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dialog_background.xml +++ b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dialog_background.xml @@ -17,6 +17,6 @@ <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/colorSurface"/> + <solid android:color="?androidprv:attr/materialColorSurfaceContainerHigh"/> <corners android:radius="@dimen/letterbox_restart_dialog_corner_radius"/> </shape>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml index 3aa0981e45aa..816b35063b00 100644 --- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml +++ b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml @@ -32,9 +32,9 @@ </item> <item> <shape android:shape="rectangle"> - <stroke android:color="?androidprv:attr/colorAccentPrimaryVariant" + <stroke android:color="?androidprv:attr/materialColorOutlineVariant" android:width="1dp"/> - <solid android:color="?androidprv:attr/colorSurface"/> + <solid android:color="?androidprv:attr/materialColorSurfaceContainerHigh"/> <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/> <padding android:left="@dimen/letterbox_restart_dialog_horizontal_padding" android:top="@dimen/letterbox_restart_dialog_vertical_padding" diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_header_ic_arrows.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_header_ic_arrows.xml index 5053971a17d3..f13d26c7f89e 100644 --- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_header_ic_arrows.xml +++ b/libs/WindowManager/Shell/res/drawable/letterbox_restart_header_ic_arrows.xml @@ -18,15 +18,13 @@ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:width="@dimen/letterbox_restart_dialog_title_icon_width" android:height="@dimen/letterbox_restart_dialog_title_icon_height" - android:viewportWidth="45" - android:viewportHeight="44"> - <group - android:scaleX="0.8" - android:scaleY="0.8" - android:translateX="8" - android:translateY="8"> + android:viewportWidth="32" + android:viewportHeight="32"> + <group> + <clip-path + android:pathData="M0,0h32v32h-32z"/> <path - android:pathData="M0,36V24.5H3V30.85L10.4,23.45L12.55,25.6L5.15,33H11.5V36H0ZM24.5,36V33H30.85L23.5,25.65L25.65,23.5L33,30.85V24.5H36V36H24.5ZM10.35,12.5L3,5.15V11.5H0V0H11.5V3H5.15L12.5,10.35L10.35,12.5ZM25.65,12.5L23.5,10.35L30.85,3H24.5V0H36V11.5H33V5.15L25.65,12.5Z" - android:fillColor="?androidprv:attr/colorAccentPrimaryVariant"/> + android:pathData="M8.533,25.333H10.667C11.044,25.333 11.356,25.467 11.6,25.733C11.867,25.978 12,26.289 12,26.667C12,27.044 11.867,27.367 11.6,27.633C11.356,27.878 11.044,28 10.667,28H5.333C4.956,28 4.633,27.878 4.367,27.633C4.122,27.367 4,27.044 4,26.667V21.333C4,20.956 4.122,20.644 4.367,20.4C4.633,20.133 4.956,20 5.333,20C5.711,20 6.022,20.133 6.267,20.4C6.533,20.644 6.667,20.956 6.667,21.333V23.467L9.867,20.267C10.111,20.022 10.422,19.9 10.8,19.9C11.178,19.9 11.489,20.022 11.733,20.267C11.978,20.511 12.1,20.822 12.1,21.2C12.1,21.578 11.978,21.889 11.733,22.133L8.533,25.333ZM23.467,25.333L20.267,22.133C20.022,21.889 19.9,21.578 19.9,21.2C19.9,20.822 20.022,20.511 20.267,20.267C20.511,20.022 20.822,19.9 21.2,19.9C21.578,19.9 21.889,20.022 22.133,20.267L25.333,23.467V21.333C25.333,20.956 25.456,20.644 25.7,20.4C25.967,20.133 26.289,20 26.667,20C27.044,20 27.356,20.133 27.6,20.4C27.867,20.644 28,20.956 28,21.333V26.667C28,27.044 27.867,27.367 27.6,27.633C27.356,27.878 27.044,28 26.667,28H21.333C20.956,28 20.633,27.878 20.367,27.633C20.122,27.367 20,27.044 20,26.667C20,26.289 20.122,25.978 20.367,25.733C20.633,25.467 20.956,25.333 21.333,25.333H23.467ZM6.667,8.533V10.667C6.667,11.044 6.533,11.367 6.267,11.633C6.022,11.878 5.711,12 5.333,12C4.956,12 4.633,11.878 4.367,11.633C4.122,11.367 4,11.044 4,10.667V5.333C4,4.956 4.122,4.644 4.367,4.4C4.633,4.133 4.956,4 5.333,4H10.667C11.044,4 11.356,4.133 11.6,4.4C11.867,4.644 12,4.956 12,5.333C12,5.711 11.867,6.033 11.6,6.3C11.356,6.544 11.044,6.667 10.667,6.667H8.533L11.733,9.867C11.978,10.111 12.1,10.422 12.1,10.8C12.1,11.178 11.978,11.489 11.733,11.733C11.489,11.978 11.178,12.1 10.8,12.1C10.422,12.1 10.111,11.978 9.867,11.733L6.667,8.533ZM25.333,8.533L22.133,11.733C21.889,11.978 21.578,12.1 21.2,12.1C20.822,12.1 20.511,11.978 20.267,11.733C20.022,11.489 19.9,11.178 19.9,10.8C19.9,10.422 20.022,10.111 20.267,9.867L23.467,6.667H21.333C20.956,6.667 20.633,6.544 20.367,6.3C20.122,6.033 20,5.711 20,5.333C20,4.956 20.122,4.644 20.367,4.4C20.633,4.133 20.956,4 21.333,4H26.667C27.044,4 27.356,4.133 27.6,4.4C27.867,4.644 28,4.956 28,5.333V10.667C28,11.044 27.867,11.367 27.6,11.633C27.356,11.878 27.044,12 26.667,12C26.289,12 25.967,11.878 25.7,11.633C25.456,11.367 25.333,11.044 25.333,10.667V8.533Z" + android:fillColor="?androidprv:attr/materialColorPrimary"/> </group> </vector>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml index c77a4fdcfa79..bda087b143d0 100644 --- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml +++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml @@ -24,10 +24,10 @@ <ImageView android:id="@+id/letterbox_education_dialog_action_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_width="32dp" + android:layout_height="32dp" android:layout_gravity="center" - android:layout_marginBottom="20dp"/> + android:layout_marginBottom="12dp"/> <TextView android:fontFamily="@*android:string/config_bodyFontFamily" @@ -37,7 +37,7 @@ android:layout_height="wrap_content" android:lineSpacingExtra="4sp" android:textAlignment="center" - android:textColor="?android:attr/textColorSecondary" + android:textColor="?androidprv:attr/materialColorOnSurface" android:textSize="14sp"/> </LinearLayout>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml index 4d5256777018..488123ad7b0c 100644 --- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml +++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml @@ -45,19 +45,16 @@ 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" - android:paddingTop="32dp" - android:paddingBottom="32dp" - android:paddingLeft="56dp" - android:paddingRight="56dp"> + android:orientation="vertical"> <ImageView android:layout_width="@dimen/letterbox_education_dialog_title_icon_width" android:layout_height="@dimen/letterbox_education_dialog_title_icon_height" - android:layout_marginBottom="17dp" + android:layout_marginBottom="16dp" android:src="@drawable/letterbox_education_ic_light_bulb"/> <TextView @@ -67,9 +64,8 @@ android:lineSpacingExtra="4sp" android:text="@string/letterbox_education_dialog_title" android:textAlignment="center" - android:textColor="?android:attr/textColorPrimary" - android:fontFamily="@*android:string/config_bodyFontFamilyMedium" - android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Headline" + android:textColor="?androidprv:attr/materialColorOnSurface" + android:fontFamily="@*android:string/config_headlineFontFamily" android:textSize="24sp"/> <LinearLayout @@ -77,7 +73,8 @@ android:layout_height="wrap_content" android:gravity="top" android:orientation="horizontal" - android:paddingTop="48dp"> + android:layout_marginHorizontal="18dp" + android:layout_marginVertical="@dimen/letterbox_education_dialog_margin"> <com.android.wm.shell.compatui.LetterboxEduDialogActionLayout android:layout_width="wrap_content" @@ -101,15 +98,13 @@ android:lineHeight="20dp" android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Small" android:id="@+id/letterbox_education_dialog_dismiss_button" - android:textStyle="bold" android:layout_width="match_parent" android:layout_height="56dp" - android:layout_marginTop="40dp" android:textSize="14sp" android:background= "@drawable/letterbox_education_dismiss_button_background_ripple" android:text="@string/letterbox_education_got_it" - android:textColor="?android:attr/textColorPrimaryInverse" + android:textColor="?androidprv:attr/materialColorOnPrimary" android:textAlignment="center" android:contentDescription="@string/letterbox_education_got_it"/> diff --git a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml index 7f1aac3551b6..045b975a854e 100644 --- a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml +++ b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml @@ -70,26 +70,27 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/letterbox_restart_dialog_description" - android:textAlignment="center"/> + android:gravity="start"/> <LinearLayout android:id="@+id/letterbox_restart_dialog_checkbox_container" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingVertical="14dp" + android:paddingVertical="16dp" android:orientation="horizontal" android:layout_gravity="center_vertical" - android:layout_marginVertical="18dp"> + android:layout_marginVertical="16dp"> <CheckBox android:id="@+id/letterbox_restart_dialog_checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginStart="12dp" android:button="@drawable/letterbox_restart_checkbox_button"/> <TextView android:textAppearance="@style/RestartDialogCheckboxText" - android:layout_marginStart="12dp" + android:layout_marginStart="20dp" android:id="@+id/letterbox_restart_dialog_checkbox_description" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -101,16 +102,19 @@ <FrameLayout android:minHeight="@dimen/letterbox_restart_dialog_button_height" android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="wrap_content" + style="?android:attr/buttonBarButtonStyle" + android:layout_gravity="end"> <Button android:textAppearance="@style/RestartDialogDismissButton" android:id="@+id/letterbox_restart_dialog_dismiss_button" + style="?android:attr/buttonBarButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginRight="8dp" android:minWidth="@dimen/letterbox_restart_dialog_button_width" android:minHeight="@dimen/letterbox_restart_dialog_button_height" - android:layout_gravity="start" android:background= "@drawable/letterbox_restart_dismiss_button_background_ripple" android:text="@string/letterbox_restart_cancel" @@ -119,11 +123,11 @@ <Button android:textAppearance="@style/RestartDialogConfirmButton" android:id="@+id/letterbox_restart_dialog_restart_button" + style="?android:attr/buttonBarButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:minWidth="@dimen/letterbox_restart_dialog_button_width" android:minHeight="@dimen/letterbox_restart_dialog_button_height" - android:layout_gravity="end" android:background= "@drawable/letterbox_restart_button_background_ripple" android:text="@string/letterbox_restart_restart" diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml index 8644780dba03..0dd0a99dd9ae 100644 --- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml +++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml @@ -73,8 +73,7 @@ <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"contraer <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string> <string name="bubbles_app_settings" msgid="3617224938701566416">"Configuración de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string> <string name="bubble_dismiss_text" msgid="8816558050659478158">"Descartar burbuja"</string> - <!-- no translation found for bubble_fullscreen_text (1006758103218086231) --> - <skip /> + <string name="bubble_fullscreen_text" msgid="1006758103218086231">"Mover a pantalla completa"</string> <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"No mostrar la conversación en burbuja"</string> <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat con burbujas"</string> <string name="bubbles_user_education_description" msgid="4215862563054175407">"Las conversaciones nuevas aparecen como elementos flotantes o burbujas. Presiona para abrir la burbuja. Arrástrala para moverla."</string> diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml index 9718bf19fcc3..6df154d9233d 100644 --- a/libs/WindowManager/Shell/res/values-es/strings.xml +++ b/libs/WindowManager/Shell/res/values-es/strings.xml @@ -73,8 +73,7 @@ <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"contraer <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string> <string name="bubbles_app_settings" msgid="3617224938701566416">"Ajustes de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string> <string name="bubble_dismiss_text" msgid="8816558050659478158">"Cerrar burbuja"</string> - <!-- no translation found for bubble_fullscreen_text (1006758103218086231) --> - <skip /> + <string name="bubble_fullscreen_text" msgid="1006758103218086231">"Cambiar a pantalla completa"</string> <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"No mostrar conversación en burbuja"</string> <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatea con burbujas"</string> <string name="bubbles_user_education_description" msgid="4215862563054175407">"Las conversaciones nuevas aparecen como iconos flotantes llamados \"burbujas\". Toca una burbuja para abrirla. Arrástrala para moverla."</string> diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml index 63b5994cd707..92f579db10b5 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings.xml @@ -73,8 +73,7 @@ <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"Réduire <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string> <string name="bubbles_app_settings" msgid="3617224938701566416">"Paramètres <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string> <string name="bubble_dismiss_text" msgid="8816558050659478158">"Fermer la bulle"</string> - <!-- no translation found for bubble_fullscreen_text (1006758103218086231) --> - <skip /> + <string name="bubble_fullscreen_text" msgid="1006758103218086231">"Passer en plein écran"</string> <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ne pas afficher la conversation dans une bulle"</string> <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatter en utilisant des bulles"</string> <string name="bubbles_user_education_description" msgid="4215862563054175407">"Les nouvelles conversations s\'affichent sous forme d\'icônes flottantes ou de bulles. Appuyez sur la bulle pour l\'ouvrir. Faites-la glisser pour la déplacer."</string> diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index 3ba6873617f6..5f9c492bf055 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -73,8 +73,7 @@ <string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"comprimi <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string> <string name="bubbles_app_settings" msgid="3617224938701566416">"Impostazioni <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string> <string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignora bolla"</string> - <!-- no translation found for bubble_fullscreen_text (1006758103218086231) --> - <skip /> + <string name="bubble_fullscreen_text" msgid="1006758103218086231">"Passa a schermo intero"</string> <string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Non mettere la conversazione nella bolla"</string> <string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatta utilizzando le bolle"</string> <string name="bubbles_user_education_description" msgid="4215862563054175407">"Le nuove conversazioni vengono mostrate come icone mobili o bolle. Tocca per aprire la bolla. Trascinala per spostarla."</string> diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml index cf18da6e7463..b7aa1581a5c1 100644 --- a/libs/WindowManager/Shell/res/values/colors.xml +++ b/libs/WindowManager/Shell/res/values/colors.xml @@ -16,7 +16,8 @@ * limitations under the License. */ --> -<resources> +<resources + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <color name="docked_divider_handle">#ffffff</color> <color name="split_divider_background">@color/taskbar_background_dark</color> <drawable name="forced_resizable_background">#59000000</drawable> @@ -42,7 +43,7 @@ <color name="compat_controls_text">@android:color/system_neutral1_50</color> <!-- Letterbox Education --> - <color name="letterbox_education_text_secondary">@android:color/system_neutral2_200</color> + <color name="letterbox_education_text_secondary">?androidprv:attr/materialColorSecondary</color> <!-- Letterbox Dialog --> <color name="letterbox_dialog_background">@android:color/system_neutral1_900</color> diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml index c76c47041ebf..3d8718332199 100644 --- a/libs/WindowManager/Shell/res/values/dimen.xml +++ b/libs/WindowManager/Shell/res/values/dimen.xml @@ -304,31 +304,31 @@ <dimen name="letterbox_education_dialog_corner_radius">28dp</dimen> <!-- The width of the top icon in the letterbox education dialog. --> - <dimen name="letterbox_education_dialog_title_icon_width">45dp</dimen> + <dimen name="letterbox_education_dialog_title_icon_width">32dp</dimen> <!-- The height of the top icon in the letterbox education dialog. --> - <dimen name="letterbox_education_dialog_title_icon_height">44dp</dimen> + <dimen name="letterbox_education_dialog_title_icon_height">32dp</dimen> <!-- The width of an icon in the letterbox education dialog. --> - <dimen name="letterbox_education_dialog_icon_width">40dp</dimen> + <dimen name="letterbox_education_dialog_icon_width">28dp</dimen> <!-- The height of an icon in the letterbox education dialog. --> - <dimen name="letterbox_education_dialog_icon_height">32dp</dimen> + <dimen name="letterbox_education_dialog_icon_height">22dp</dimen> <!-- The fixed width of the dialog if there is enough space in the parent. --> - <dimen name="letterbox_education_dialog_width">472dp</dimen> + <dimen name="letterbox_education_dialog_width">364dp</dimen> <!-- The margin between the dialog container and its parent. --> - <dimen name="letterbox_education_dialog_margin">16dp</dimen> + <dimen name="letterbox_education_dialog_margin">24dp</dimen> <!-- The width of each action container in the letterbox education dialog --> - <dimen name="letterbox_education_dialog_action_width">140dp</dimen> + <dimen name="letterbox_education_dialog_action_width">124dp</dimen> <!-- The space between two actions in the letterbox education dialog --> - <dimen name="letterbox_education_dialog_space_between_actions">24dp</dimen> + <dimen name="letterbox_education_dialog_space_between_actions">32dp</dimen> <!-- The corner radius of the buttons in the letterbox education dialog --> - <dimen name="letterbox_education_dialog_button_radius">12dp</dimen> + <dimen name="letterbox_education_dialog_button_radius">28dp</dimen> <!-- The horizontal padding for the buttons in the letterbox education dialog --> <dimen name="letterbox_education_dialog_horizontal_padding">16dp</dimen> @@ -367,7 +367,7 @@ <dimen name="letterbox_restart_dialog_button_width">82dp</dimen> <!-- The width of the buttons in the restart dialog --> - <dimen name="letterbox_restart_dialog_button_height">36dp</dimen> + <dimen name="letterbox_restart_dialog_button_height">40dp</dimen> <!-- The corner radius of the buttons in the restart dialog --> <dimen name="letterbox_restart_dialog_button_radius">18dp</dimen> diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml index 13c0e6646002..d061ae1ef1a7 100644 --- a/libs/WindowManager/Shell/res/values/styles.xml +++ b/libs/WindowManager/Shell/res/values/styles.xml @@ -82,7 +82,7 @@ <item name="android:textColor">@color/tv_pip_edu_text</item> </style> - <style name="LetterboxDialog" parent="@android:style/Theme.Holo"> + <style name="LetterboxDialog" parent="@android:style/Theme.DeviceDefault.Dialog.Alert"> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> <item name="android:background">@color/letterbox_dialog_background</item> @@ -90,7 +90,7 @@ <style name="RestartDialogTitleText"> <item name="android:textSize">24sp</item> - <item name="android:textColor">?android:attr/textColorPrimary</item> + <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item> <item name="android:lineSpacingExtra">8sp</item> <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> </style> @@ -102,23 +102,23 @@ <style name="RestartDialogBodyText" parent="RestartDialogBodyStyle"> <item name="android:letterSpacing">0.02</item> - <item name="android:textColor">?android:attr/textColorSecondary</item> + <item name="android:textColor">?androidprv:attr/materialColorOnSurfaceVariant</item> <item name="android:lineSpacingExtra">6sp</item> </style> <style name="RestartDialogCheckboxText" parent="RestartDialogBodyStyle"> - <item name="android:textColor">?android:attr/textColorPrimary</item> + <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item> <item name="android:lineSpacingExtra">6sp</item> </style> <style name="RestartDialogDismissButton" parent="RestartDialogBodyStyle"> <item name="android:lineSpacingExtra">2sp</item> - <item name="android:textColor">?android:attr/textColorPrimary</item> + <item name="android:textColor">?androidprv:attr/materialColorPrimary</item> </style> <style name="RestartDialogConfirmButton" parent="RestartDialogBodyStyle"> <item name="android:lineSpacingExtra">2sp</item> - <item name="android:textColor">?android:attr/textColorPrimaryInverse</item> + <item name="android:textColor">?androidprv:attr/materialColorOnPrimary</item> </style> <style name="ReachabilityEduHandLayout" parent="Theme.AppCompat.Light"> diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/TransitionUtil.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/TransitionUtil.java index 9027bf34a58e..88878c6adcf2 100644 --- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/TransitionUtil.java +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/TransitionUtil.java @@ -40,6 +40,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.ActivityManager; +import android.app.TaskInfo; import android.app.WindowConfiguration; import android.graphics.Rect; import android.util.ArrayMap; @@ -339,6 +340,52 @@ public class TransitionUtil { return target; } + /** + * Creates a new RemoteAnimationTarget from the provided change and leash + */ + public static RemoteAnimationTarget newSyntheticTarget(ActivityManager.RunningTaskInfo taskInfo, + SurfaceControl leash, @TransitionInfo.TransitionMode int mode, int order, + boolean isTranslucent) { + int taskId; + boolean isNotInRecents; + WindowConfiguration windowConfiguration; + + if (taskInfo != null) { + taskId = taskInfo.taskId; + isNotInRecents = !taskInfo.isRunning; + windowConfiguration = taskInfo.configuration.windowConfiguration; + } else { + taskId = INVALID_TASK_ID; + isNotInRecents = true; + windowConfiguration = new WindowConfiguration(); + } + + Rect localBounds = new Rect(); + RemoteAnimationTarget target = new RemoteAnimationTarget( + taskId, + newModeToLegacyMode(mode), + // TODO: once we can properly sync transactions across process, + // then get rid of this leash. + leash, + isTranslucent, + null, + // TODO(shell-transitions): we need to send content insets? evaluate how its used. + new Rect(0, 0, 0, 0), + order, + null, + localBounds, + new Rect(), + windowConfiguration, + isNotInRecents, + null, + new Rect(), + taskInfo, + false, + INVALID_WINDOW_TYPE + ); + return target; + } + private static RemoteAnimationTarget getDividerTarget(TransitionInfo.Change change, SurfaceControl leash) { return new RemoteAnimationTarget(-1 /* taskId */, newModeToLegacyMode(change.getMode()), diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java index 341ca0eb6bed..dd86a1a0edbb 100644 --- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeStatus.java @@ -90,6 +90,19 @@ public class DesktopModeStatus { /** The maximum override density allowed for tasks inside the desktop. */ private static final int DESKTOP_DENSITY_MAX = 1000; + /** The number of [WindowDecorViewHost] instances to warm up on system start. */ + private static final int WINDOW_DECOR_PRE_WARM_SIZE = 2; + + /** + * Sysprop declaring whether to enters desktop mode by default when the windowing mode of the + * display's root TaskDisplayArea is set to WINDOWING_MODE_FREEFORM. + * + * <p>If it is not defined, then {@code R.integer.config_enterDesktopByDefaultOnFreeformDisplay} + * is used. + */ + public static final String ENTER_DESKTOP_BY_DEFAULT_ON_FREEFORM_DISPLAY_SYS_PROP = + "persist.wm.debug.enter_desktop_by_default_on_freeform_display"; + /** * Sysprop declaring the maximum number of Tasks to show in Desktop Mode at any one time. * @@ -102,6 +115,14 @@ public class DesktopModeStatus { private static final String MAX_TASK_LIMIT_SYS_PROP = "persist.wm.debug.desktop_max_task_limit"; /** + * Sysprop declaring the number of [WindowDecorViewHost] instances to warm up on system start. + * + * <p>If it is not defined, then [WINDOW_DECOR_PRE_WARM_SIZE] is used. + */ + private static final String WINDOW_DECOR_PRE_WARM_SIZE_SYS_PROP = + "persist.wm.debug.desktop_window_decor_pre_warm_size"; + + /** * Return {@code true} if veiled resizing is active. If false, fluid resizing is used. */ public static boolean isVeiledResizeEnabled() { @@ -141,6 +162,12 @@ public class DesktopModeStatus { context.getResources().getInteger(R.integer.config_maxDesktopWindowingActiveTasks)); } + /** The number of [WindowDecorViewHost] instances to warm up on system start. */ + public static int getWindowDecorPreWarmSize() { + return SystemProperties.getInt(WINDOW_DECOR_PRE_WARM_SIZE_SYS_PROP, + WINDOW_DECOR_PRE_WARM_SIZE); + } + /** * Return {@code true} if the current device supports desktop mode. */ @@ -206,6 +233,19 @@ public class DesktopModeStatus { return !enforceDeviceRestrictions() || isDesktopModeSupported(context); } + /** + * Return {@code true} if a display should enter desktop mode by default when the windowing mode + * of the display's root [TaskDisplayArea] is set to WINDOWING_MODE_FREEFORM. + */ + public static boolean enterDesktopByDefaultOnFreeformDisplay(@NonNull Context context) { + if (!Flags.enterDesktopByDefaultOnFreeformDisplays()) { + return false; + } + return SystemProperties.getBoolean(ENTER_DESKTOP_BY_DEFAULT_ON_FREEFORM_DISPLAY_SYS_PROP, + context.getResources().getBoolean( + R.bool.config_enterDesktopByDefaultOnFreeformDisplay)); + } + /** Dumps DesktopModeStatus flags and configs. */ public static void dump(PrintWriter pw, String prefix, Context context) { String innerPrefix = prefix + " "; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index 452d12a242c0..7e6f43458ba6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -46,7 +46,6 @@ import android.util.Log; import android.util.SparseArray; import android.view.SurfaceControl; import android.window.ITaskOrganizerController; -import android.window.ScreenCapture; import android.window.StartingWindowInfo; import android.window.StartingWindowRemovalInfo; import android.window.TaskAppearedInfo; @@ -55,7 +54,6 @@ import android.window.TaskOrganizer; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.ProtoLog; import com.android.internal.util.FrameworkStatsLog; -import com.android.wm.shell.common.ScreenshotUtils; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.compatui.CompatUIController; import com.android.wm.shell.compatui.api.CompatUIHandler; @@ -74,7 +72,6 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.function.Consumer; /** * Unified task organizer for all components in the shell. @@ -561,19 +558,6 @@ public class ShellTaskOrganizer extends TaskOrganizer { mRecentTasks.ifPresent(recentTasks -> recentTasks.onTaskAdded(info.getTaskInfo())); } - /** - * Take a screenshot of a task. - */ - public void screenshotTask(RunningTaskInfo taskInfo, Rect crop, - Consumer<ScreenCapture.ScreenshotHardwareBuffer> consumer) { - final TaskAppearedInfo info = mTasks.get(taskInfo.taskId); - if (info == null) { - return; - } - ScreenshotUtils.captureLayer(info.getLeash(), crop, consumer); - } - - @Override public void onTaskInfoChanged(RunningTaskInfo taskInfo) { synchronized (mLock) { 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 f478b4446cbe..3e5adf395cdd 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 @@ -117,6 +117,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont */ private static final long MAX_ANIMATION_DURATION = 2000; private final LatencyTracker mLatencyTracker; + @ShellMainThread private final Handler mHandler; /** True when a back gesture is ongoing */ private boolean mBackGestureStarted = false; @@ -218,7 +219,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont @NonNull BackAnimationBackground backAnimationBackground, ShellBackAnimationRegistry shellBackAnimationRegistry, ShellCommandHandler shellCommandHandler, - Transitions transitions) { + Transitions transitions, + @ShellMainThread Handler handler) { this( shellInit, shellController, @@ -230,7 +232,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont backAnimationBackground, shellBackAnimationRegistry, shellCommandHandler, - transitions); + transitions, + handler); } @VisibleForTesting @@ -245,7 +248,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont @NonNull BackAnimationBackground backAnimationBackground, ShellBackAnimationRegistry shellBackAnimationRegistry, ShellCommandHandler shellCommandHandler, - Transitions transitions) { + Transitions transitions, + @NonNull @ShellMainThread Handler handler) { mShellController = shellController; mShellExecutor = shellExecutor; mActivityTaskManager = activityTaskManager; @@ -263,6 +267,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont mTransitions = transitions; mBackTransitionHandler = new BackTransitionHandler(); mTransitions.addHandler(mBackTransitionHandler); + mHandler = handler; updateTouchableArea(); } @@ -399,7 +404,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } } - private static class IBackAnimationImpl extends IBackAnimation.Stub + private class IBackAnimationImpl extends IBackAnimation.Stub implements ExternalInterfaceBinder { private BackAnimationController mController; @@ -417,7 +422,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont callback, runner, controller.mContext, - CUJ_PREDICTIVE_BACK_HOME))); + CUJ_PREDICTIVE_BACK_HOME, + mHandler))); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java index e24df0bdc05d..9ca9b730fb06 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java @@ -20,6 +20,7 @@ import static android.view.WindowManager.TRANSIT_OLD_UNSET; import android.annotation.NonNull; import android.content.Context; +import android.os.Handler; import android.os.RemoteException; import android.util.Log; import android.view.IRemoteAnimationFinishedCallback; @@ -31,6 +32,7 @@ import android.window.IOnBackInvokedCallback; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.jank.Cuj.CujType; import com.android.internal.jank.InteractionJankMonitor; +import com.android.wm.shell.shared.annotations.ShellMainThread; /** * Used to register the animation callback and runner, it will trigger result if gesture was finish @@ -45,6 +47,8 @@ public class BackAnimationRunner { private final IRemoteAnimationRunner mRunner; private final @CujType int mCujType; private final Context mContext; + @ShellMainThread + private final Handler mHandler; // Whether we are waiting to receive onAnimationStart private boolean mWaitingAnimation; @@ -56,18 +60,35 @@ public class BackAnimationRunner { @NonNull IOnBackInvokedCallback callback, @NonNull IRemoteAnimationRunner runner, @NonNull Context context, - @CujType int cujType) { + @CujType int cujType, + @ShellMainThread Handler handler) { mCallback = callback; mRunner = runner; mCujType = cujType; mContext = context; + mHandler = handler; } public BackAnimationRunner( @NonNull IOnBackInvokedCallback callback, @NonNull IRemoteAnimationRunner runner, - @NonNull Context context) { - this(callback, runner, context, NO_CUJ); + @NonNull Context context, + @ShellMainThread Handler handler + ) { + this(callback, runner, context, NO_CUJ, handler); + } + + /** + * @deprecated Use {@link BackAnimationRunner} constructor providing an handler for the ui + * thread of the animation. + */ + @Deprecated + public BackAnimationRunner( + @NonNull IOnBackInvokedCallback callback, + @NonNull IRemoteAnimationRunner runner, + @NonNull Context context + ) { + this(callback, runner, context, NO_CUJ, context.getMainThreadHandler()); } /** Returns the registered animation runner */ @@ -100,7 +121,7 @@ public class BackAnimationRunner { mWaitingAnimation = false; if (shouldMonitorCUJ(apps)) { interactionJankMonitor.begin( - apps[0].leash, mContext, mCujType); + apps[0].leash, mContext, mHandler, mCujType); } try { getRunner().onAnimationStart(TRANSIT_OLD_UNSET, apps, wallpapers, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt index 32e809a23a91..37339307f5b0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt @@ -26,6 +26,7 @@ import android.graphics.Matrix import android.graphics.PointF import android.graphics.Rect import android.graphics.RectF +import android.os.Handler import android.os.RemoteException import android.util.TimeUtils import android.view.Choreographer @@ -53,6 +54,7 @@ import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup import com.android.wm.shell.shared.animation.Interpolators +import com.android.wm.shell.shared.annotations.ShellMainThread import kotlin.math.abs import kotlin.math.max import kotlin.math.min @@ -61,7 +63,8 @@ abstract class CrossActivityBackAnimation( private val context: Context, private val background: BackAnimationBackground, private val rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, - protected val transaction: SurfaceControl.Transaction + protected val transaction: SurfaceControl.Transaction, + @ShellMainThread handler: Handler, ) : ShellBackAnimation() { protected val startClosingRect = RectF() @@ -80,7 +83,13 @@ abstract class CrossActivityBackAnimation( private var statusbarHeight = SystemBarUtils.getStatusBarHeight(context) private val backAnimationRunner = - BackAnimationRunner(Callback(), Runner(), context, Cuj.CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY) + BackAnimationRunner( + Callback(), + Runner(), + context, + Cuj.CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY, + handler, + ) private val initialTouchPos = PointF() private val transformMatrix = Matrix() private val tmpFloat9 = FloatArray(9) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java index 3fccecab4319..7a569799ab84 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java @@ -34,6 +34,7 @@ import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; +import android.os.Handler; import android.os.RemoteException; import android.view.Choreographer; import android.view.IRemoteAnimationFinishedCallback; @@ -52,6 +53,7 @@ import com.android.internal.policy.SystemBarUtils; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.R; import com.android.wm.shell.shared.animation.Interpolators; +import com.android.wm.shell.shared.annotations.ShellMainThread; import javax.inject.Inject; @@ -113,9 +115,10 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { private float mVerticalMargin; @Inject - public CrossTaskBackAnimation(Context context, BackAnimationBackground background) { + public CrossTaskBackAnimation(Context context, BackAnimationBackground background, + @ShellMainThread Handler handler) { mBackAnimationRunner = new BackAnimationRunner( - new Callback(), new Runner(), context, CUJ_PREDICTIVE_BACK_CROSS_TASK); + new Callback(), new Runner(), context, CUJ_PREDICTIVE_BACK_CROSS_TASK, handler); mBackground = background; mContext = context; loadResources(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomCrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomCrossActivityBackAnimation.kt index b02f97bf7784..2f7666b21882 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomCrossActivityBackAnimation.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomCrossActivityBackAnimation.kt @@ -18,6 +18,7 @@ package com.android.wm.shell.back import android.content.Context import android.graphics.Rect import android.graphics.RectF +import android.os.Handler import android.util.MathUtils import android.view.SurfaceControl import android.view.animation.Animation @@ -30,6 +31,7 @@ import com.android.internal.policy.TransitionAnimation import com.android.internal.protolog.ProtoLog import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup +import com.android.wm.shell.shared.annotations.ShellMainThread import javax.inject.Inject import kotlin.math.max import kotlin.math.min @@ -40,13 +42,15 @@ class CustomCrossActivityBackAnimation( background: BackAnimationBackground, rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, transaction: SurfaceControl.Transaction, - private val customAnimationLoader: CustomAnimationLoader + private val customAnimationLoader: CustomAnimationLoader, + @ShellMainThread handler: Handler, ) : CrossActivityBackAnimation( context, background, rootTaskDisplayAreaOrganizer, - transaction + transaction, + handler ) { private var enterAnimation: Animation? = null @@ -59,7 +63,8 @@ class CustomCrossActivityBackAnimation( constructor( context: Context, background: BackAnimationBackground, - rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer + rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, + @ShellMainThread handler: Handler, ) : this( context, background, @@ -67,7 +72,8 @@ class CustomCrossActivityBackAnimation( SurfaceControl.Transaction(), CustomAnimationLoader( TransitionAnimation(context, false /* debug */, "CustomCrossActivityBackAnimation") - ) + ), + handler, ) override fun preparePreCommitClosingRectMovement(swipeEdge: Int) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt index 66d8a5f2eeb9..eecd7694009d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/DefaultCrossActivityBackAnimation.kt @@ -16,11 +16,13 @@ package com.android.wm.shell.back import android.content.Context +import android.os.Handler import android.view.SurfaceControl import android.window.BackEvent import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.shared.animation.Interpolators +import com.android.wm.shell.shared.annotations.ShellMainThread import javax.inject.Inject import kotlin.math.max @@ -30,13 +32,15 @@ class DefaultCrossActivityBackAnimation constructor( context: Context, background: BackAnimationBackground, - rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer + rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer, + @ShellMainThread handler: Handler, ) : CrossActivityBackAnimation( context, background, rootTaskDisplayAreaOrganizer, - SurfaceControl.Transaction() + SurfaceControl.Transaction(), + handler ) { private val postCommitInterpolator = Interpolators.EMPHASIZED 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 b8aa1b189f7e..4b55fd0f5527 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 @@ -48,6 +48,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Point; import android.graphics.Rect; +import android.os.Handler; import android.view.Display; import android.view.InsetsSourceControl; import android.view.InsetsState; @@ -75,6 +76,7 @@ import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.common.split.DividerSnapAlgorithm.SnapTarget; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.animation.Interpolators; +import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.shared.split.SplitScreenConstants.PersistentSnapPosition; import com.android.wm.shell.shared.split.SplitScreenConstants.SnapPosition; import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition; @@ -116,6 +118,8 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange new PathInterpolator(0.2f, 0f, 0f, 1f); private static final Interpolator GROW_INTERPOLATOR = new PathInterpolator(0.45f, 0f, 0.5f, 1f); + @ShellMainThread + private final Handler mHandler; private int mDividerWindowWidth; private int mDividerInsets; @@ -166,7 +170,8 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange SplitLayoutHandler splitLayoutHandler, SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks, DisplayController displayController, DisplayImeController displayImeController, - ShellTaskOrganizer taskOrganizer, int parallaxType) { + ShellTaskOrganizer taskOrganizer, int parallaxType, @ShellMainThread Handler handler) { + mHandler = handler; mContext = context.createConfigurationContext(configuration); mOrientation = configuration.orientation; mRotation = configuration.windowConfiguration.getRotation(); @@ -598,7 +603,8 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } void onStartDragging() { - mInteractionJankMonitor.begin(getDividerLeash(), mContext, CUJ_SPLIT_SCREEN_RESIZE); + mInteractionJankMonitor.begin(getDividerLeash(), mContext, mHandler, + CUJ_SPLIT_SCREEN_RESIZE); } void onDraggingCancelled() { @@ -756,7 +762,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange @Override public void onAnimationStart(Animator animation) { mInteractionJankMonitor.begin(getDividerLeash(), - mContext, CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER); + mContext, mHandler, CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER); } @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 4adea233b734..722fe1f59388 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 @@ -444,7 +444,9 @@ public abstract class WMShellBaseModule { BackAnimationBackground backAnimationBackground, Optional<ShellBackAnimationRegistry> shellBackAnimationRegistry, ShellCommandHandler shellCommandHandler, - Transitions transitions) { + Transitions transitions, + @ShellMainThread Handler handler + ) { if (BackAnimationController.IS_ENABLED) { return shellBackAnimationRegistry.map( (animations) -> @@ -457,7 +459,8 @@ public abstract class WMShellBaseModule { backAnimationBackground, animations, shellCommandHandler, - transitions)); + transitions, + handler)); } return Optional.empty(); } 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 8c7dcf295319..b47adb43c2a6 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 @@ -116,6 +116,8 @@ import com.android.wm.shell.windowdecor.CaptionWindowDecorViewModel; import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel; import com.android.wm.shell.windowdecor.WindowDecorViewModel; import com.android.wm.shell.windowdecor.viewhost.DefaultWindowDecorViewHostSupplier; +import com.android.wm.shell.windowdecor.viewhost.PooledWindowDecorViewHostSupplier; +import com.android.wm.shell.windowdecor.viewhost.ReusableWindowDecorViewHost; import com.android.wm.shell.windowdecor.viewhost.WindowDecorViewHostSupplier; import dagger.Binds; @@ -353,7 +355,8 @@ public abstract class WMShellModule { @ShellMainThread ShellExecutor mainExecutor, @ShellAnimationThread ShellExecutor animExecutor, @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository, - InteractionJankMonitor interactionJankMonitor) { + InteractionJankMonitor interactionJankMonitor, + @ShellMainThread Handler handler) { return new FreeformTaskTransitionHandler( shellInit, transitions, @@ -363,7 +366,8 @@ public abstract class WMShellModule { mainExecutor, animExecutor, desktopModeTaskRepository, - interactionJankMonitor); + interactionJankMonitor, + handler); } @WMSingleton @@ -380,8 +384,19 @@ public abstract class WMShellModule { @WMSingleton @Provides static WindowDecorViewHostSupplier provideWindowDecorViewHostSupplier( - @ShellMainThread @NonNull CoroutineScope mainScope) { - return new DefaultWindowDecorViewHostSupplier(mainScope); + @NonNull Context context, + @ShellMainThread @NonNull CoroutineScope mainScope, + @NonNull ShellInit shellInit) { + if (DesktopModeStatus.canEnterDesktopMode(context) + && Flags.enableDesktopWindowingScvhCache()) { + final int maxPoolSize = DesktopModeStatus.getMaxTaskLimit(context); + final int preWarmSize = DesktopModeStatus.getWindowDecorPreWarmSize(); + return new PooledWindowDecorViewHostSupplier( + context, mainScope, shellInit, + ReusableWindowDecorViewHost.DefaultFactory.INSTANCE, maxPoolSize, preWarmSize); + } else { + return new DefaultWindowDecorViewHostSupplier(mainScope); + } } // @@ -474,10 +489,11 @@ public abstract class WMShellModule { @Provides static RecentsTransitionHandler provideRecentsTransitionHandler( ShellInit shellInit, + ShellTaskOrganizer shellTaskOrganizer, Transitions transitions, Optional<RecentTasksController> recentTasksController, HomeTransitionObserver homeTransitionObserver) { - return new RecentsTransitionHandler(shellInit, transitions, + return new RecentsTransitionHandler(shellInit, shellTaskOrganizer, transitions, recentTasksController.orElse(null), homeTransitionObserver); } @@ -603,6 +619,7 @@ public abstract class WMShellModule { RecentsTransitionHandler recentsTransitionHandler, MultiInstanceHelper multiInstanceHelper, @ShellMainThread ShellExecutor mainExecutor, + @ShellMainThread Handler mainHandler, Optional<DesktopTasksLimiter> desktopTasksLimiter, Optional<RecentTasksController> recentTasksController, InteractionJankMonitor interactionJankMonitor) { @@ -615,7 +632,7 @@ public abstract class WMShellModule { dragToDesktopTransitionHandler, desktopModeTaskRepository, desktopModeLoggerTransitionObserver, launchAdjacentController, recentsTransitionHandler, multiInstanceHelper, mainExecutor, desktopTasksLimiter, - recentTasksController.orElse(null), interactionJankMonitor); + recentTasksController.orElse(null), interactionJankMonitor, mainHandler); } @WMSingleton @@ -625,7 +642,8 @@ public abstract class WMShellModule { Transitions transitions, @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository, ShellTaskOrganizer shellTaskOrganizer, - InteractionJankMonitor interactionJankMonitor) { + InteractionJankMonitor interactionJankMonitor, + @ShellMainThread Handler handler) { int maxTaskLimit = DesktopModeStatus.getMaxTaskLimit(context); if (!DesktopModeStatus.canEnterDesktopMode(context) || !ENABLE_DESKTOP_WINDOWING_TASK_LIMIT.isEnabled(context) @@ -639,7 +657,8 @@ public abstract class WMShellModule { shellTaskOrganizer, maxTaskLimit, interactionJankMonitor, - context) + context, + handler) ); } @@ -686,9 +705,10 @@ public abstract class WMShellModule { static ExitDesktopTaskTransitionHandler provideExitDesktopTaskTransitionHandler( Transitions transitions, Context context, - InteractionJankMonitor interactionJankMonitor) { + InteractionJankMonitor interactionJankMonitor, + @ShellMainThread Handler handler) { return new ExitDesktopTaskTransitionHandler( - transitions, context, interactionJankMonitor); + transitions, context, interactionJankMonitor, handler); } @WMSingleton diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip1Module.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip1Module.java index 037fbb235bd4..3a4764d45f2c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip1Module.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip1Module.java @@ -101,7 +101,8 @@ public abstract class Pip1Module { DisplayInsetsController displayInsetsController, TabletopModeController pipTabletopController, Optional<OneHandedController> oneHandedController, - @ShellMainThread ShellExecutor mainExecutor) { + @ShellMainThread ShellExecutor mainExecutor, + @ShellMainThread Handler handler) { return Optional.ofNullable(PipController.create( context, shellInit, shellCommandHandler, shellController, displayController, pipAnimationController, pipAppOpsListener, @@ -111,7 +112,7 @@ public abstract class Pip1Module { pipTransitionState, pipTouchHandler, pipTransitionController, windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder, displayInsetsController, pipTabletopController, oneHandedController, - mainExecutor)); + mainExecutor, handler)); } // Handler is used by Icon.loadDrawableAsync diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt index c8ffe28da79c..bd6172226cf2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt @@ -162,7 +162,7 @@ fun maximizeSizeGivenAspectRatio( fun calculateAspectRatio(taskInfo: RunningTaskInfo): Float { val appLetterboxWidth = taskInfo.appCompatTaskInfo.topActivityLetterboxAppWidth val appLetterboxHeight = taskInfo.appCompatTaskInfo.topActivityLetterboxAppHeight - if (taskInfo.appCompatTaskInfo.isTopActivityLetterboxed) { + if (taskInfo.appCompatTaskInfo.isTopActivityLetterboxed || !taskInfo.canChangeAspectRatio) { return maxOf(appLetterboxWidth, appLetterboxHeight) / minOf(appLetterboxWidth, appLetterboxHeight).toFloat() } 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 7e9625361efc..853284a58904 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 @@ -35,6 +35,7 @@ import android.graphics.PointF import android.graphics.Rect import android.graphics.Region import android.os.Binder +import android.os.Handler import android.os.IBinder import android.os.SystemProperties import android.util.Size @@ -136,7 +137,8 @@ class DesktopTasksController( @ShellMainThread private val mainExecutor: ShellExecutor, private val desktopTasksLimiter: Optional<DesktopTasksLimiter>, private val recentTasksController: RecentTasksController?, - private val interactionJankMonitor: InteractionJankMonitor + private val interactionJankMonitor: InteractionJankMonitor, + @ShellMainThread private val handler: Handler, ) : RemoteCallable<DesktopTasksController>, Transitions.TransitionHandler, @@ -303,6 +305,15 @@ class DesktopTasksController( private fun getSplitFocusedTask(task1: RunningTaskInfo, task2: RunningTaskInfo) = if (task1.taskId == task2.parentTaskId) task2 else task1 + private fun isFreeformDisplay(displayId: Int): Boolean { + val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId) + requireNotNull(tdaInfo) { + "This method can only be called with the ID of a display having non-null DisplayArea." + } + val tdaWindowingMode = tdaInfo.configuration.windowConfiguration.windowingMode + return tdaWindowingMode == WINDOWING_MODE_FREEFORM + } + /** Moves task to desktop mode if task is running, else launches it in desktop mode. */ fun moveTaskToDesktop( taskId: Int, @@ -378,7 +389,7 @@ class DesktopTasksController( taskSurface: SurfaceControl, ) { logV("startDragToDesktop taskId=%d", taskInfo.taskId) - interactionJankMonitor.begin(taskSurface, context, + interactionJankMonitor.begin(taskSurface, context, handler, CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_HOLD) dragToDesktopTransitionHandler.startDragToDesktopTransition( taskInfo.taskId, @@ -782,7 +793,7 @@ class DesktopTasksController( releaseVisualIndicator() if (!taskInfo.isResizeable && DesktopModeFlags.DISABLE_SNAP_RESIZE.isEnabled(context)) { interactionJankMonitor.begin( - taskSurface, context, CUJ_DESKTOP_MODE_SNAP_RESIZE, "drag_non_resizable" + taskSurface, context, handler, CUJ_DESKTOP_MODE_SNAP_RESIZE, "drag_non_resizable" ) // reposition non-resizable app back to its original position before being dragged @@ -795,7 +806,7 @@ class DesktopTasksController( ) } else { interactionJankMonitor.begin( - taskSurface, context, CUJ_DESKTOP_MODE_SNAP_RESIZE, "drag_resizable" + taskSurface, context, handler, CUJ_DESKTOP_MODE_SNAP_RESIZE, "drag_resizable" ) snapToHalfScreen(taskInfo, taskSurface, currentDragBounds, position) } @@ -1220,7 +1231,9 @@ class DesktopTasksController( transition: IBinder ): WindowContainerTransaction? { logV("handleFullscreenTaskLaunch") - if (isDesktopModeShowing(task.displayId)) { + val forceEnterDesktop = DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(context) && + isFreeformDisplay(task.displayId) + if (isDesktopModeShowing(task.displayId) || forceEnterDesktop) { logD("Switch fullscreen task to freeform on transition: taskId=%d", task.taskId) return WindowContainerTransaction().also { wct -> addMoveToDesktopChanges(wct, task) @@ -1593,7 +1606,7 @@ class DesktopTasksController( when (indicatorType) { IndicatorType.TO_DESKTOP_INDICATOR -> { // Start a new jank interaction for the drag release to desktop window animation. - interactionJankMonitor.begin(taskSurface, context, + interactionJankMonitor.begin(taskSurface, context, handler, CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_RELEASE, "to_desktop") finalizeDragToDesktop(taskInfo) } 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 597637d3fbfc..dae37f4926f5 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 @@ -18,6 +18,7 @@ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo import android.content.Context +import android.os.Handler import android.os.IBinder import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_TO_BACK @@ -29,6 +30,7 @@ import com.android.internal.jank.InteractionJankMonitor import com.android.internal.protolog.ProtoLog import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup +import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.transition.Transitions import com.android.wm.shell.transition.Transitions.TransitionObserver @@ -45,7 +47,8 @@ class DesktopTasksLimiter ( private val shellTaskOrganizer: ShellTaskOrganizer, private val maxTasksLimit: Int, private val interactionJankMonitor: InteractionJankMonitor, - private val context: Context + private val context: Context, + @ShellMainThread private val handler: Handler, ) { private val minimizeTransitionObserver = MinimizeTransitionObserver() @VisibleForTesting @@ -125,7 +128,7 @@ class DesktopTasksLimiter ( if (mActiveTaskDetails != null && mActiveTaskDetails.transitionInfo != null) { // Begin minimize window CUJ instrumentation. interactionJankMonitor.begin( - mActiveTaskDetails.transitionInfo?.rootLeash, context, + mActiveTaskDetails.transitionInfo?.rootLeash, context, handler, CUJ_DESKTOP_MODE_MINIMIZE_WINDOW ) } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java index e87be520cc91..dedd44f3950a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandler.java @@ -29,6 +29,7 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Point; import android.graphics.Rect; +import android.os.Handler; import android.os.IBinder; import android.util.DisplayMetrics; import android.view.SurfaceControl; @@ -44,6 +45,7 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.jank.Cuj; import com.android.internal.jank.InteractionJankMonitor; +import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource; import com.android.wm.shell.transition.Transitions; @@ -63,6 +65,8 @@ public class ExitDesktopTaskTransitionHandler implements Transitions.TransitionH private final Context mContext; private final Transitions mTransitions; private final InteractionJankMonitor mInteractionJankMonitor; + @ShellMainThread + private final Handler mHandler; private final List<IBinder> mPendingTransitionTokens = new ArrayList<>(); private Consumer<SurfaceControl.Transaction> mOnAnimationFinishedCallback; private final Supplier<SurfaceControl.Transaction> mTransactionSupplier; @@ -71,20 +75,24 @@ public class ExitDesktopTaskTransitionHandler implements Transitions.TransitionH public ExitDesktopTaskTransitionHandler( Transitions transitions, Context context, - InteractionJankMonitor interactionJankMonitor - ) { - this(transitions, SurfaceControl.Transaction::new, context, interactionJankMonitor); + InteractionJankMonitor interactionJankMonitor, + @ShellMainThread Handler handler + ) { + this(transitions, SurfaceControl.Transaction::new, context, interactionJankMonitor, + handler); } private ExitDesktopTaskTransitionHandler( Transitions transitions, Supplier<SurfaceControl.Transaction> supplier, Context context, - InteractionJankMonitor interactionJankMonitor) { + InteractionJankMonitor interactionJankMonitor, + @ShellMainThread Handler handler) { mTransitions = transitions; mTransactionSupplier = supplier; mContext = context; mInteractionJankMonitor = interactionJankMonitor; + mHandler = handler; } /** @@ -154,7 +162,7 @@ public class ExitDesktopTaskTransitionHandler implements Transitions.TransitionH final SurfaceControl sc = change.getLeash(); final Rect endBounds = change.getEndAbsBounds(); mInteractionJankMonitor - .begin(sc, mContext, Cuj.CUJ_DESKTOP_MODE_EXIT_MODE); + .begin(sc, mContext, mHandler, Cuj.CUJ_DESKTOP_MODE_EXIT_MODE); // Hide the first (fullscreen) frame because the animation will start from the freeform // size. startT.hide(sc) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java index 832e2d2bc77b..517e20910f6d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java @@ -28,6 +28,7 @@ import android.app.ActivityManager; import android.app.WindowConfiguration; import android.content.Context; import android.graphics.Rect; +import android.os.Handler; import android.os.IBinder; import android.util.ArrayMap; import android.view.SurfaceControl; @@ -43,6 +44,7 @@ import com.android.internal.jank.InteractionJankMonitor; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; +import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.windowdecor.WindowDecorViewModel; @@ -65,6 +67,8 @@ public class FreeformTaskTransitionHandler private final InteractionJankMonitor mInteractionJankMonitor; private final ShellExecutor mMainExecutor; private final ShellExecutor mAnimExecutor; + @ShellMainThread + private final Handler mHandler; private final List<IBinder> mPendingTransitionTokens = new ArrayList<>(); @@ -79,7 +83,8 @@ public class FreeformTaskTransitionHandler ShellExecutor mainExecutor, ShellExecutor animExecutor, DesktopModeTaskRepository desktopModeTaskRepository, - InteractionJankMonitor interactionJankMonitor) { + InteractionJankMonitor interactionJankMonitor, + @ShellMainThread Handler handler) { mTransitions = transitions; mContext = context; mWindowDecorViewModel = windowDecorViewModel; @@ -88,6 +93,7 @@ public class FreeformTaskTransitionHandler mInteractionJankMonitor = interactionJankMonitor; mMainExecutor = mainExecutor; mAnimExecutor = animExecutor; + mHandler = handler; if (Transitions.ENABLE_SHELL_TRANSITIONS) { shellInit.addInitCallback(this::onInit, this); } @@ -267,7 +273,7 @@ public class FreeformTaskTransitionHandler change.getTaskInfo().displayId) == 1) { // Starting the jank trace if closing the last window in desktop mode. mInteractionJankMonitor.begin( - sc, mContext, CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE); + sc, mContext, mHandler, CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE); } animator.addListener( new AnimatorListenerAdapter() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java index 1827923aad90..15472ebc149b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java @@ -55,6 +55,7 @@ import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TaskStackListenerCallback; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.shared.annotations.ExternalThread; +import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.sysui.ConfigurationChangeListener; import com.android.wm.shell.sysui.KeyguardChangeListener; import com.android.wm.shell.sysui.ShellCommandHandler; @@ -203,7 +204,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>, DisplayController displayController, DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener, InteractionJankMonitor jankMonitor, UiEventLogger uiEventLogger, - ShellExecutor mainExecutor, Handler mainHandler) { + ShellExecutor mainExecutor, @ShellMainThread Handler mainHandler) { OneHandedSettingsUtil settingsUtil = new OneHandedSettingsUtil(); OneHandedAccessibilityUtil accessibilityUtil = new OneHandedAccessibilityUtil(context); OneHandedTimeoutHandler timeoutHandler = new OneHandedTimeoutHandler(mainExecutor); @@ -217,7 +218,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>, mainExecutor); OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer( context, displayLayout, settingsUtil, animationController, tutorialHandler, - jankMonitor, mainExecutor); + jankMonitor, mainExecutor, mainHandler); OneHandedUiEventLogger oneHandedUiEventsLogger = new OneHandedUiEventLogger(uiEventLogger); return new OneHandedController(context, shellInit, shellCommandHandler, shellController, displayController, organizer, touchHandler, tutorialHandler, settingsUtil, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java index d157ca837608..95e633d0b5ec 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java @@ -23,6 +23,7 @@ import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSI import android.content.Context; import android.graphics.Rect; +import android.os.Handler; import android.os.SystemProperties; import android.text.TextUtils; import android.util.ArrayMap; @@ -42,6 +43,7 @@ import com.android.internal.jank.InteractionJankMonitor; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.shared.annotations.ShellMainThread; import java.io.PrintWriter; import java.util.ArrayList; @@ -70,6 +72,8 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { private final OneHandedSettingsUtil mOneHandedSettingsUtil; private final InteractionJankMonitor mJankMonitor; private final Context mContext; + @ShellMainThread + private final Handler mHandler; private boolean mIsReady; private float mLastVisualOffset = 0; @@ -136,9 +140,11 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { OneHandedAnimationController animationController, OneHandedTutorialHandler tutorialHandler, InteractionJankMonitor jankMonitor, - ShellExecutor mainExecutor) { + ShellExecutor mainExecutor, + @ShellMainThread Handler handler) { super(mainExecutor); mContext = context; + mHandler = handler; setDisplayLayout(displayLayout); mOneHandedSettingsUtil = oneHandedSettingsUtil; mAnimationController = animationController; @@ -333,7 +339,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { getDisplayAreaTokenMap().entrySet().iterator().next(); final InteractionJankMonitor.Configuration.Builder builder = InteractionJankMonitor.Configuration.Builder.withSurface( - cujType, mContext, firstEntry.getValue()); + cujType, mContext, firstEntry.getValue(), mHandler); if (!TextUtils.isEmpty(tag)) { builder.setTag(tag); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index deb7691f2d4d..af6844262771 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -44,6 +44,7 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; +import android.os.Handler; import android.os.RemoteException; import android.os.SystemProperties; import android.util.Pair; @@ -93,6 +94,7 @@ import com.android.wm.shell.pip.PipTaskOrganizer; import com.android.wm.shell.pip.PipTransitionController; import com.android.wm.shell.pip.PipTransitionState; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.sysui.ConfigurationChangeListener; import com.android.wm.shell.sysui.KeyguardChangeListener; import com.android.wm.shell.sysui.ShellCommandHandler; @@ -146,6 +148,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb private Optional<OneHandedController> mOneHandedController; private final ShellCommandHandler mShellCommandHandler; private final ShellController mShellController; + @ShellMainThread + private final Handler mHandler; protected final PipImpl mImpl; private final Rect mTmpInsetBounds = new Rect(); @@ -405,7 +409,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb DisplayInsetsController displayInsetsController, TabletopModeController pipTabletopController, Optional<OneHandedController> oneHandedController, - ShellExecutor mainExecutor) { + ShellExecutor mainExecutor, + Handler handler) { if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: Device doesn't support Pip feature", TAG); @@ -418,7 +423,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb pipDisplayLayoutState, pipMotionHelper, pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState, pipTouchHandler, pipTransitionController, windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder, - displayInsetsController, pipTabletopController, oneHandedController, mainExecutor) + displayInsetsController, pipTabletopController, oneHandedController, mainExecutor, + handler) .mImpl; } @@ -446,11 +452,13 @@ public class PipController implements PipTransitionController.PipTransitionCallb DisplayInsetsController displayInsetsController, TabletopModeController tabletopModeController, Optional<OneHandedController> oneHandedController, - ShellExecutor mainExecutor + ShellExecutor mainExecutor, + @ShellMainThread Handler handler ) { mContext = context; mShellCommandHandler = shellCommandHandler; mShellController = shellController; + mHandler = handler; mImpl = new PipImpl(); mWindowManagerShellWrapper = windowManagerShellWrapper; mDisplayController = displayController; @@ -1047,7 +1055,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb // Begin InteractionJankMonitor with PIP transition CUJs final InteractionJankMonitor.Configuration.Builder builder = InteractionJankMonitor.Configuration.Builder.withSurface( - CUJ_PIP_TRANSITION, mContext, mPipTaskOrganizer.getSurfaceControl()) + CUJ_PIP_TRANSITION, mContext, mPipTaskOrganizer.getSurfaceControl(), + mHandler) .setTag(getTransitionTag(direction)) .setTimeout(2000); InteractionJankMonitor.getInstance().begin(builder); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java index c660000e4f61..8077aeebf27f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java @@ -20,9 +20,12 @@ import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS; import static android.view.WindowManager.TRANSIT_CHANGE; +import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED; +import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_PIP; import static android.view.WindowManager.TRANSIT_SLEEP; import static android.view.WindowManager.TRANSIT_TO_FRONT; @@ -41,6 +44,7 @@ import android.app.PendingIntent; import android.content.Intent; import android.graphics.Color; import android.graphics.Rect; +import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; @@ -64,6 +68,7 @@ import androidx.annotation.NonNull; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.IResultReceiver; import com.android.internal.protolog.ProtoLog; +import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.protolog.ShellProtoLogGroup; @@ -79,10 +84,15 @@ import java.util.function.Consumer; * Handles the Recents (overview) animation. Only one of these can run at a time. A recents * transition must be created via {@link #startRecentsTransition}. Anything else will be ignored. */ -public class RecentsTransitionHandler implements Transitions.TransitionHandler { +public class RecentsTransitionHandler implements Transitions.TransitionHandler, + Transitions.TransitionObserver { private static final String TAG = "RecentsTransitionHandler"; + // A placeholder for a synthetic transition that isn't backed by a true system transition + public static final IBinder SYNTHETIC_TRANSITION = new Binder(); + private final Transitions mTransitions; + private final ShellTaskOrganizer mShellTaskOrganizer; private final ShellExecutor mExecutor; @Nullable private final RecentTasksController mRecentTasksController; @@ -99,19 +109,26 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { private final HomeTransitionObserver mHomeTransitionObserver; private @Nullable Color mBackgroundColor; - public RecentsTransitionHandler(ShellInit shellInit, Transitions transitions, + public RecentsTransitionHandler( + @NonNull ShellInit shellInit, + @NonNull ShellTaskOrganizer shellTaskOrganizer, + @NonNull Transitions transitions, @Nullable RecentTasksController recentTasksController, - HomeTransitionObserver homeTransitionObserver) { + @NonNull HomeTransitionObserver homeTransitionObserver) { + mShellTaskOrganizer = shellTaskOrganizer; mTransitions = transitions; mExecutor = transitions.getMainExecutor(); mRecentTasksController = recentTasksController; mHomeTransitionObserver = homeTransitionObserver; if (!Transitions.ENABLE_SHELL_TRANSITIONS) return; if (recentTasksController == null) return; - shellInit.addInitCallback(() -> { - recentTasksController.setTransitionHandler(this); - transitions.addHandler(this); - }, this); + shellInit.addInitCallback(this::onInit, this); + } + + private void onInit() { + mRecentTasksController.setTransitionHandler(this); + mTransitions.addHandler(this); + mTransitions.registerObserver(this); } /** Register a mixer handler. {@see RecentsMixedHandler}*/ @@ -138,17 +155,59 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { mBackgroundColor = color; } + /** + * Starts a new real/synthetic recents transition. + */ @VisibleForTesting public IBinder startRecentsTransition(PendingIntent intent, Intent fillIn, Bundle options, IApplicationThread appThread, IRecentsAnimationRunner listener) { + // only care about latest one. + mAnimApp = appThread; + + // TODO(b/366021931): Formalize this later + final boolean isSyntheticRequest = options.containsKey("is_synthetic_recents_transition"); + if (isSyntheticRequest) { + return startSyntheticRecentsTransition(listener); + } else { + return startRealRecentsTransition(intent, fillIn, options, listener); + } + } + + /** + * Starts a synthetic recents transition that is not backed by a real WM transition. + */ + private IBinder startSyntheticRecentsTransition(@NonNull IRecentsAnimationRunner listener) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, + "RecentsTransitionHandler.startRecentsTransition(synthetic)"); + final RecentsController lastController = getLastController(); + if (lastController != null) { + lastController.cancel(lastController.isSyntheticTransition() + ? "existing_running_synthetic_transition" + : "existing_running_transition"); + return null; + } + + // Create a new synthetic transition and start it immediately + final RecentsController controller = new RecentsController(listener); + controller.startSyntheticTransition(); + mControllers.add(controller); + return SYNTHETIC_TRANSITION; + } + + /** + * Starts a real WM-backed recents transition. + */ + private IBinder startRealRecentsTransition(PendingIntent intent, Intent fillIn, Bundle options, + IRecentsAnimationRunner listener) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "RecentsTransitionHandler.startRecentsTransition"); - // only care about latest one. - mAnimApp = appThread; - WindowContainerTransaction wct = new WindowContainerTransaction(); + final WindowContainerTransaction wct = new WindowContainerTransaction(); wct.sendPendingIntent(intent, fillIn, options); - final RecentsController controller = new RecentsController(listener); + + // Find the mixed handler which should handle this request (if we are in a state where a + // mixed handler is needed). This is slightly convoluted because starting the transition + // requires the handler, but the mixed handler also needs a reference to the transition. RecentsMixedHandler mixer = null; Consumer<IBinder> setTransitionForMixer = null; for (int i = 0; i < mMixers.size(); ++i) { @@ -160,12 +219,11 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { } final IBinder transition = mTransitions.startTransition(TRANSIT_TO_FRONT, wct, mixer == null ? this : mixer); - for (int i = 0; i < mStateListeners.size(); i++) { - mStateListeners.get(i).onTransitionStarted(transition); - } if (mixer != null) { setTransitionForMixer.accept(transition); } + + final RecentsController controller = new RecentsController(listener); if (transition != null) { controller.setTransition(transition); mControllers.add(controller); @@ -187,11 +245,28 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { return null; } - private int findController(IBinder transition) { + /** + * Returns if there is currently a pending or active recents transition. + */ + @Nullable + private RecentsController getLastController() { + return !mControllers.isEmpty() ? mControllers.getLast() : null; + } + + /** + * Finds an existing controller for the provided {@param transition}, or {@code null} if none + * exists. + */ + @Nullable + @VisibleForTesting + RecentsController findController(@NonNull IBinder transition) { for (int i = mControllers.size() - 1; i >= 0; --i) { - if (mControllers.get(i).mTransition == transition) return i; + final RecentsController controller = mControllers.get(i); + if (controller.mTransition == transition) { + return controller; + } } - return -1; + return null; } @Override @@ -199,13 +274,12 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { SurfaceControl.Transaction startTransaction, SurfaceControl.Transaction finishTransaction, Transitions.TransitionFinishCallback finishCallback) { - final int controllerIdx = findController(transition); - if (controllerIdx < 0) { + final RecentsController controller = findController(transition); + if (controller == null) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "RecentsTransitionHandler.startAnimation: no controller found"); return false; } - final RecentsController controller = mControllers.get(controllerIdx); final IApplicationThread animApp = mAnimApp; mAnimApp = null; if (!controller.start(info, startTransaction, finishTransaction, finishCallback)) { @@ -221,13 +295,12 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { public void mergeAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t, IBinder mergeTarget, Transitions.TransitionFinishCallback finishCallback) { - final int targetIdx = findController(mergeTarget); - if (targetIdx < 0) { + final RecentsController controller = findController(mergeTarget); + if (controller == null) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "RecentsTransitionHandler.mergeAnimation: no controller found"); return; } - final RecentsController controller = mControllers.get(targetIdx); controller.merge(info, t, finishCallback); } @@ -244,8 +317,21 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { } } + @Override + public void onTransitionReady(@NonNull IBinder transition, @NonNull TransitionInfo info, + @NonNull SurfaceControl.Transaction startTransaction, + @NonNull SurfaceControl.Transaction finishTransaction) { + RecentsController controller = findController(SYNTHETIC_TRANSITION); + if (controller != null) { + // Cancel the existing synthetic transition if there is one + controller.cancel("incoming_transition"); + } + } + /** There is only one of these and it gets reset on finish. */ - private class RecentsController extends IRecentsAnimationController.Stub { + @VisibleForTesting + class RecentsController extends IRecentsAnimationController.Stub { + private final int mInstanceId; private IRecentsAnimationRunner mListener; @@ -307,7 +393,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { mDeathHandler = () -> { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "[%d] RecentsController.DeathRecipient: binder died", mInstanceId); - finish(mWillFinishToHome, false /* leaveHint */, null /* finishCb */); + finishInner(mWillFinishToHome, false /* leaveHint */, null /* finishCb */, + "deathRecipient"); }; try { mListener.asBinder().linkToDeath(mDeathHandler, 0 /* flags */); @@ -317,6 +404,9 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { } } + /** + * Sets the started transition for this instance of the recents transition. + */ void setTransition(IBinder transition) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "[%d] RecentsController.setTransition: id=%s", mInstanceId, transition); @@ -330,6 +420,10 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { } void cancel(boolean toHome, boolean withScreenshots, String reason) { + if (cancelSyntheticTransition(reason)) { + return; + } + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "[%d] RecentsController.cancel: toHome=%b reason=%s", mInstanceId, toHome, reason); @@ -341,7 +435,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { } } if (mFinishCB != null) { - finishInner(toHome, false /* userLeave */, null /* finishCb */); + finishInner(toHome, false /* userLeave */, null /* finishCb */, "cancel"); } else { cleanUp(); } @@ -436,6 +530,91 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { } } + /** + * Starts a new transition that is not backed by a system transition. + */ + void startSyntheticTransition() { + mTransition = SYNTHETIC_TRANSITION; + + // TODO(b/366021931): Update mechanism for pulling the home task, for now add home as + // both opening and closing since there's some pre-existing + // dependencies on having a closing task + final ActivityManager.RunningTaskInfo homeTask = + mShellTaskOrganizer.getRunningTasks(DEFAULT_DISPLAY).stream() + .filter(task -> task.getActivityType() == ACTIVITY_TYPE_HOME) + .findFirst() + .get(); + final RemoteAnimationTarget openingTarget = TransitionUtil.newSyntheticTarget( + homeTask, mShellTaskOrganizer.getHomeTaskOverlayContainer(), TRANSIT_OPEN, + 0, true /* isTranslucent */); + final RemoteAnimationTarget closingTarget = TransitionUtil.newSyntheticTarget( + homeTask, mShellTaskOrganizer.getHomeTaskOverlayContainer(), TRANSIT_CLOSE, + 0, true /* isTranslucent */); + final ArrayList<RemoteAnimationTarget> apps = new ArrayList<>(); + apps.add(openingTarget); + apps.add(closingTarget); + try { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, + "[%d] RecentsController.start: calling onAnimationStart with %d apps", + mInstanceId, apps.size()); + mListener.onAnimationStart(this, + apps.toArray(new RemoteAnimationTarget[apps.size()]), + new RemoteAnimationTarget[0], + new Rect(0, 0, 0, 0), new Rect(), new Bundle()); + for (int i = 0; i < mStateListeners.size(); i++) { + mStateListeners.get(i).onAnimationStateChanged(true); + } + } catch (RemoteException e) { + Slog.e(TAG, "Error starting recents animation", e); + cancel("startSynthetricTransition() failed"); + } + } + + /** + * Returns whether this transition is backed by a real system transition or not. + */ + boolean isSyntheticTransition() { + return mTransition == SYNTHETIC_TRANSITION; + } + + /** + * Called when a synthetic transition is canceled. + */ + boolean cancelSyntheticTransition(String reason) { + if (!isSyntheticTransition()) { + return false; + } + + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, + "[%d] RecentsController.cancelSyntheticTransition reason=%s", + mInstanceId, reason); + try { + // TODO(b/366021931): Notify the correct tasks once we build actual targets, and + // clean up leashes accordingly + mListener.onAnimationCanceled(new int[0], new TaskSnapshot[0]); + } catch (RemoteException e) { + Slog.e(TAG, "Error canceling previous recents animation", e); + } + cleanUp(); + return true; + } + + /** + * Called when a synthetic transition is finished. + * @return + */ + boolean finishSyntheticTransition() { + if (!isSyntheticTransition()) { + return false; + } + + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, + "[%d] RecentsController.finishSyntheticTransition", mInstanceId); + // TODO(b/366021931): Clean up leashes accordingly + cleanUp(); + return true; + } + boolean start(TransitionInfo info, SurfaceControl.Transaction t, SurfaceControl.Transaction finishT, Transitions.TransitionFinishCallback finishCB) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, @@ -662,7 +841,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { // Set the callback once again so we can finish correctly. mFinishCB = finishCB; finishInner(true /* toHome */, false /* userLeave */, - null /* finishCb */); + null /* finishCb */, "takeOverAnimation"); }, updatedStates); }); } @@ -810,7 +989,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { sendCancelWithSnapshots(); mExecutor.executeDelayed( () -> finishInner(true /* toHome */, false /* userLeaveHint */, - null /* finishCb */), 0); + null /* finishCb */, "merge"), 0); return; } if (recentsOpening != null) { @@ -1005,7 +1184,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { return; } final int displayId = mInfo.getRootCount() > 0 ? mInfo.getRoot(0).getDisplayId() - : Display.DEFAULT_DISPLAY; + : DEFAULT_DISPLAY; // transient launches don't receive focus automatically. Since we are taking over // the gesture now, take focus explicitly. // This also moves recents back to top if the user gestured before a switch @@ -1038,11 +1217,16 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler { @Override @SuppressLint("NewApi") public void finish(boolean toHome, boolean sendUserLeaveHint, IResultReceiver finishCb) { - mExecutor.execute(() -> finishInner(toHome, sendUserLeaveHint, finishCb)); + mExecutor.execute(() -> finishInner(toHome, sendUserLeaveHint, finishCb, + "requested")); } private void finishInner(boolean toHome, boolean sendUserLeaveHint, - IResultReceiver runnerFinishCb) { + IResultReceiver runnerFinishCb, String reason) { + if (finishSyntheticTransition()) { + return; + } + if (mFinishCB == null) { Slog.e(TAG, "Duplicate call to finish"); return; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionStateListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionStateListener.java index e8733ebd8f03..95874c8193c9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionStateListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionStateListener.java @@ -24,7 +24,4 @@ public interface RecentsTransitionStateListener { /** Notifies whether the recents animation is running. */ default void onAnimationStateChanged(boolean running) { } - - /** Notifies that a recents shell transition has started. */ - default void onTransitionStarted(IBinder transition) {} } 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 4ba84eeb2e6d..5a905cfd317f 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 @@ -1654,7 +1654,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext, mRootTaskInfo.configuration, this, mParentContainerCallbacks, mDisplayController, mDisplayImeController, mTaskOrganizer, - PARALLAX_ALIGN_CENTER /* parallaxType */); + PARALLAX_ALIGN_CENTER /* parallaxType */, mMainHandler); mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSplitLayout); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java index 6013a1ea1d9d..dec28fefd789 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java @@ -16,7 +16,7 @@ package com.android.wm.shell.transition; -import static com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary; +import static com.android.systemui.shared.Flags.returnAnimationFrameworkLongLived; import android.annotation.NonNull; import android.annotation.Nullable; @@ -257,7 +257,7 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { @Override public Transitions.TransitionHandler getHandlerForTakeover( @NonNull IBinder transition, @NonNull TransitionInfo info) { - if (!returnAnimationFrameworkLibrary()) { + if (!returnAnimationFrameworkLongLived()) { return null; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java index aba8b61af306..d03832d3e85e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java @@ -38,7 +38,7 @@ import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; import static android.window.TransitionInfo.FLAG_NO_ANIMATION; import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT; -import static com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary; +import static com.android.systemui.shared.Flags.returnAnimationFrameworkLongLived; import static com.android.window.flags.Flags.ensureWallpaperInTransitions; import static com.android.window.flags.Flags.migratePredictiveBackTransition; import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_SHELL_TRANSITIONS; @@ -1252,7 +1252,7 @@ public class Transitions implements RemoteCallable<Transitions>, @Nullable public TransitionHandler getHandlerForTakeover( @NonNull IBinder transition, @NonNull TransitionInfo info) { - if (!returnAnimationFrameworkLibrary()) { + if (!returnAnimationFrameworkLongLived()) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "Trying to get a handler for takeover but the flag is disabled"); return null; @@ -1501,16 +1501,16 @@ public class Transitions implements RemoteCallable<Transitions>, * transition animation. The Transition system will apply it when * finishCallback is called by the transition handler. */ - void onTransitionReady(@NonNull IBinder transition, @NonNull TransitionInfo info, + default void onTransitionReady(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, - @NonNull SurfaceControl.Transaction finishTransaction); + @NonNull SurfaceControl.Transaction finishTransaction) {} /** * Called when the transition is starting to play. It isn't called for merged transitions. * * @param transition the unique token of this transition */ - void onTransitionStarting(@NonNull IBinder transition); + default void onTransitionStarting(@NonNull IBinder transition) {} /** * Called when a transition is merged into another transition. There won't be any following @@ -1519,7 +1519,7 @@ public class Transitions implements RemoteCallable<Transitions>, * @param merged the unique token of the transition that's merged to another one * @param playing the unique token of the transition that accepts the merge */ - void onTransitionMerged(@NonNull IBinder merged, @NonNull IBinder playing); + default void onTransitionMerged(@NonNull IBinder merged, @NonNull IBinder playing) {} /** * Called when the transition is finished. This isn't called for merged transitions. @@ -1527,7 +1527,7 @@ public class Transitions implements RemoteCallable<Transitions>, * @param transition the unique token of this transition * @param aborted {@code true} if this transition is aborted; {@code false} otherwise. */ - void onTransitionFinished(@NonNull IBinder transition, boolean aborted); + default void onTransitionFinished(@NonNull IBinder transition, boolean aborted) {} } @BinderThread 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 b14283f878a3..02c818ffa906 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 @@ -111,6 +111,7 @@ import com.android.wm.shell.desktopmode.DesktopTasksLimiter; import com.android.wm.shell.desktopmode.DesktopWallpaperActivity; import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; import com.android.wm.shell.shared.annotations.ShellBackgroundThread; +import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.shared.desktopmode.DesktopModeFlags; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource; @@ -154,7 +155,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { private final ShellTaskOrganizer mTaskOrganizer; private final ShellController mShellController; private final Context mContext; - private final Handler mMainHandler; + private final @ShellMainThread Handler mMainHandler; private final @ShellBackgroundThread ShellExecutor mBgExecutor; private final Choreographer mMainChoreographer; private final DisplayController mDisplayController; @@ -214,7 +215,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { public DesktopModeWindowDecorViewModel( Context context, ShellExecutor shellExecutor, - Handler mainHandler, + @ShellMainThread Handler mainHandler, Choreographer mainChoreographer, @ShellBackgroundThread ShellExecutor bgExecutor, ShellInit shellInit, @@ -270,7 +271,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { DesktopModeWindowDecorViewModel( Context context, ShellExecutor shellExecutor, - Handler mainHandler, + @ShellMainThread Handler mainHandler, Choreographer mainChoreographer, @ShellBackgroundThread ShellExecutor bgExecutor, ShellInit shellInit, @@ -495,7 +496,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { return; } mInteractionJankMonitor.begin( - decoration.mTaskSurface, mContext, Cuj.CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW, source); + decoration.mTaskSurface, mContext, mMainHandler, + Cuj.CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW, source); mDesktopTasksController.toggleDesktopTaskSize(decoration.mTaskInfo); decoration.closeHandleMenu(); decoration.closeMaximizeMenu(); @@ -512,7 +514,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { Toast.makeText(mContext, R.string.desktop_mode_non_resizable_snap_text, Toast.LENGTH_SHORT).show(); } else { - mInteractionJankMonitor.begin(decoration.mTaskSurface, mContext, + mInteractionJankMonitor.begin(decoration.mTaskSurface, mContext, mMainHandler, Cuj.CUJ_DESKTOP_MODE_SNAP_RESIZE, "maximize_menu_resizable"); mDesktopTasksController.snapToHalfScreen( decoration.mTaskInfo, @@ -548,7 +550,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { return; } final WindowContainerTransaction wct = new WindowContainerTransaction(); - mInteractionJankMonitor.begin(decoration.mTaskSurface, mContext, + mInteractionJankMonitor.begin(decoration.mTaskSurface, mContext, mMainHandler, CUJ_DESKTOP_MODE_ENTER_MODE_APP_HANDLE_MENU); // App sometimes draws before the insets from WindowDecoration#relayout have // been added, so they must be added here @@ -860,6 +862,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { handleCaptionThroughStatusBar(e, decoration); final boolean wasDragging = mIsDragging; updateDragStatus(e.getActionMasked()); + final boolean upOrCancel = e.getActionMasked() == ACTION_UP + || e.getActionMasked() == ACTION_CANCEL; + if (wasDragging && upOrCancel) { + // When finishing a drag the event will be consumed, which means the pressed + // state of the App Handle must be manually reset to scale its drawable back to + // its original shape. This is necessary for drag gestures of the Handle that + // result in a cancellation (dragging back to the top). + v.setPressed(false); + } // Only prevent onClick from receiving this event if it's a drag. return wasDragging; } @@ -1378,7 +1389,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mDragStartListener, mTransitions, mInteractionJankMonitor, - mTransactionFactory); + mTransactionFactory, + mMainHandler); windowDecoration.setTaskDragResizer(taskPositioner); final DesktopModeTouchEventListener touchEventListener = @@ -1602,7 +1614,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { DragPositioningCallbackUtility.DragStartListener dragStartListener, Transitions transitions, InteractionJankMonitor interactionJankMonitor, - Supplier<SurfaceControl.Transaction> transactionFactory) { + Supplier<SurfaceControl.Transaction> transactionFactory, + Handler handler) { final TaskPositioner taskPositioner = DesktopModeStatus.isVeiledResizeEnabled() ? new VeiledResizeTaskPositioner( taskOrganizer, @@ -1610,7 +1623,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { displayController, dragStartListener, transitions, - interactionJankMonitor) + interactionJankMonitor, + handler) : new FluidResizeTaskPositioner( taskOrganizer, transitions, 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 55da78e74ba2..16036bee75b3 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 @@ -24,6 +24,8 @@ import static android.view.InsetsSource.FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_UP; +import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION; +import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS; import static com.android.launcher3.icons.BaseIconFactory.MODE_DEFAULT; import static com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource.APP_HANDLE_MENU_BUTTON; @@ -548,7 +550,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mResult.mRootView, mOnCaptionTouchListener, mOnCaptionButtonClickListener, - mWindowManagerWrapper + mWindowManagerWrapper, + mHandler ); } else if (mRelayoutParams.mLayoutResId == R.layout.desktop_mode_app_header) { @@ -603,13 +606,13 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin // their custom content. relayoutParams.mInputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_SPY; } else { - if (Flags.enableCaptionCompatInsetForceConsumption()) { + if (ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isEnabled()) { // Force-consume the caption bar insets when the app tries to hide the caption. // This improves app compatibility of immersive apps. relayoutParams.mInsetSourceFlags |= FLAG_FORCE_CONSUMING; } } - if (Flags.enableCaptionCompatInsetForceConsumptionAlways()) { + if (ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS.isEnabled()) { // Always force-consume the caption bar insets for maximum app compatibility, // including non-immersive apps that just don't handle caption insets properly. relayoutParams.mInsetSourceFlags |= FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR; @@ -752,9 +755,12 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin final ActivityInfo activityInfo = pm.getActivityInfo(baseActivity, 0 /* flags */); final IconProvider provider = new IconProvider(mContext); final Drawable appIconDrawable = provider.getIcon(activityInfo); + final Drawable badgedAppIconDrawable = pm.getUserBadgedIcon(appIconDrawable, + UserHandle.of(mTaskInfo.userId)); final BaseIconFactory headerIconFactory = createIconFactory(mContext, R.dimen.desktop_mode_caption_icon_radius); - mAppIconBitmap = headerIconFactory.createScaledBitmap(appIconDrawable, MODE_DEFAULT); + mAppIconBitmap = headerIconFactory.createIconBitmap(badgedAppIconDrawable, + 1f /* scale */); final BaseIconFactory resizeVeilIconFactory = createIconFactory(mContext, R.dimen.desktop_mode_resize_veil_icon_size); 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 599815530f63..6f3f41191485 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 @@ -24,6 +24,7 @@ import static com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_RESIZE_WINDOW; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; +import android.os.Handler; import android.os.IBinder; import android.view.Surface; import android.view.SurfaceControl; @@ -37,6 +38,7 @@ import androidx.annotation.Nullable; import com.android.internal.jank.InteractionJankMonitor; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.transition.Transitions; import java.util.function.Supplier; @@ -63,14 +65,17 @@ public class VeiledResizeTaskPositioner implements TaskPositioner, Transitions.T private int mCtrlType; private boolean mIsResizingOrAnimatingResize; @Surface.Rotation private int mRotation; + @ShellMainThread + private final Handler mHandler; public VeiledResizeTaskPositioner(ShellTaskOrganizer taskOrganizer, DesktopModeWindowDecoration windowDecoration, DisplayController displayController, DragPositioningCallbackUtility.DragStartListener dragStartListener, - Transitions transitions, InteractionJankMonitor interactionJankMonitor) { + Transitions transitions, InteractionJankMonitor interactionJankMonitor, + @ShellMainThread Handler handler) { this(taskOrganizer, windowDecoration, displayController, dragStartListener, - SurfaceControl.Transaction::new, transitions, interactionJankMonitor); + SurfaceControl.Transaction::new, transitions, interactionJankMonitor, handler); } public VeiledResizeTaskPositioner(ShellTaskOrganizer taskOrganizer, @@ -78,7 +83,7 @@ public class VeiledResizeTaskPositioner implements TaskPositioner, Transitions.T DisplayController displayController, DragPositioningCallbackUtility.DragStartListener dragStartListener, Supplier<SurfaceControl.Transaction> supplier, Transitions transitions, - InteractionJankMonitor interactionJankMonitor) { + InteractionJankMonitor interactionJankMonitor, @ShellMainThread Handler handler) { mDesktopWindowDecoration = windowDecoration; mTaskOrganizer = taskOrganizer; mDisplayController = displayController; @@ -86,6 +91,7 @@ public class VeiledResizeTaskPositioner implements TaskPositioner, Transitions.T mTransactionSupplier = supplier; mTransitions = transitions; mInteractionJankMonitor = interactionJankMonitor; + mHandler = handler; } @Override @@ -97,7 +103,7 @@ public class VeiledResizeTaskPositioner implements TaskPositioner, Transitions.T if (isResizing()) { // Capture CUJ for re-sizing window in DW mode. mInteractionJankMonitor.begin(mDesktopWindowDecoration.mTaskSurface, - mDesktopWindowDecoration.mContext, CUJ_DESKTOP_MODE_RESIZE_WINDOW); + mDesktopWindowDecoration.mContext, mHandler, CUJ_DESKTOP_MODE_RESIZE_WINDOW); if (!mDesktopWindowDecoration.mTaskInfo.isFocused) { WindowContainerTransaction wct = new WindowContainerTransaction(); wct.reorder(mDesktopWindowDecoration.mTaskInfo.token, true); @@ -131,7 +137,7 @@ public class VeiledResizeTaskPositioner implements TaskPositioner, Transitions.T } else if (mCtrlType == CTRL_TYPE_UNDEFINED) { // Begin window drag CUJ instrumentation only when drag position moves. mInteractionJankMonitor.begin(mDesktopWindowDecoration.mTaskSurface, - mDesktopWindowDecoration.mContext, CUJ_DESKTOP_MODE_DRAG_WINDOW); + mDesktopWindowDecoration.mContext, mHandler, CUJ_DESKTOP_MODE_DRAG_WINDOW); final SurfaceControl.Transaction t = mTransactionSupplier.get(); DragPositioningCallbackUtility.setPositionOnDrag(mDesktopWindowDecoration, mRepositionTaskBounds, mTaskBoundsAtDragStart, mRepositionStartPoint, t, x, y); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt index 1c11a8dfbbb4..9c7d644afb7e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt @@ -22,6 +22,7 @@ import android.content.res.ColorStateList import android.graphics.Color import android.graphics.Point import android.hardware.input.InputManager +import android.os.Handler import android.view.MotionEvent.ACTION_DOWN import android.view.SurfaceControl import android.view.View @@ -44,7 +45,8 @@ internal class AppHandleViewHolder( rootView: View, onCaptionTouchListener: View.OnTouchListener, onCaptionButtonClickListener: OnClickListener, - private val windowManagerWrapper: WindowManagerWrapper + private val windowManagerWrapper: WindowManagerWrapper, + private val handler: Handler ) : WindowDecorationViewHolder(rootView) { companion object { @@ -54,6 +56,7 @@ internal class AppHandleViewHolder( private val captionView: View = rootView.requireViewById(R.id.desktop_mode_caption) private val captionHandle: ImageButton = rootView.requireViewById(R.id.caption_handle) private val inputManager = context.getSystemService(InputManager::class.java) + private var statusBarInputLayerExists = false // An invisible View that takes up the same coordinates as captionHandle but is layered // above the status bar. The purpose of this View is to receive input intended for @@ -78,14 +81,18 @@ internal class AppHandleViewHolder( // If handle is not in status bar region(i.e., bottom stage in vertical split), // do not create an input layer if (position.y >= SystemBarUtils.getStatusBarHeight(context)) return - if (!isCaptionVisible && hasStatusBarInputLayer() ) { + if (!isCaptionVisible && statusBarInputLayerExists) { disposeStatusBarInputLayer() return } - if (hasStatusBarInputLayer()) { - updateStatusBarInputLayer(position) + // Input layer view creation / modification takes a significant amount of time; + // post them so we don't hold up DesktopModeWindowDecoration#relayout. + if (statusBarInputLayerExists) { + handler.post { updateStatusBarInputLayer(position) } } else { - createStatusBarInputLayer(position, width, height) + // Input layer is created on a delay; prevent multiple from being created. + statusBarInputLayerExists = true + handler.post { createStatusBarInputLayer(position, width, height) } } } @@ -103,9 +110,10 @@ internal class AppHandleViewHolder( if (!Flags.enableHandleInputFix()) return statusBarInputLayer = AdditionalSystemViewContainer(context, windowManagerWrapper, taskInfo.taskId, handlePosition.x, handlePosition.y, handleWidth, handleHeight, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + ) val view = statusBarInputLayer?.view ?: error("Unable to find statusBarInputLayer View") - val lp = statusBarInputLayer?.lp ?: error("Unable to find statusBarInputLayer" + + val lp = statusBarInputLayer?.lp ?: error("Unable to find statusBarInputLayer " + "LayoutParams") lp.title = "Handle Input Layer of task " + taskInfo.taskId lp.setTrustedOverlay() @@ -130,12 +138,11 @@ internal class AppHandleViewHolder( } private fun updateStatusBarInputLayer(globalPosition: Point) { - statusBarInputLayer?.setPosition(SurfaceControl.Transaction(), globalPosition.x.toFloat(), - globalPosition.y.toFloat()) ?: return - } - - private fun hasStatusBarInputLayer(): Boolean { - return statusBarInputLayer != null + statusBarInputLayer?.setPosition( + SurfaceControl.Transaction(), + globalPosition.x.toFloat(), + globalPosition.y.toFloat() + ) ?: return } /** @@ -143,8 +150,11 @@ internal class AppHandleViewHolder( * is not visible. */ fun disposeStatusBarInputLayer() { - statusBarInputLayer?.releaseView() - statusBarInputLayer = null + statusBarInputLayerExists = false + handler.post { + statusBarInputLayer?.releaseView() + statusBarInputLayer = null + } } private fun getCaptionHandleBarColor(taskInfo: RunningTaskInfo): Int { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/DefaultWindowDecorViewHost.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/DefaultWindowDecorViewHost.kt index 139e6790b744..5156e47cfd13 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/DefaultWindowDecorViewHost.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/DefaultWindowDecorViewHost.kt @@ -19,51 +19,33 @@ import android.content.Context import android.content.res.Configuration import android.view.Display import android.view.SurfaceControl -import android.view.SurfaceControlViewHost import android.view.View import android.view.WindowManager -import android.view.WindowlessWindowManager import androidx.tracing.Trace import com.android.internal.annotations.VisibleForTesting import com.android.wm.shell.shared.annotations.ShellMainThread import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.launch -typealias SurfaceControlViewHostFactory = - (Context, Display, WindowlessWindowManager, String) -> SurfaceControlViewHost /** - * A default implementation of [WindowDecorViewHost] backed by a [SurfaceControlViewHost]. + * A default implementation of [WindowDecorViewHost] backed by a [SurfaceControlViewHostAdapter]. * - * It does not support swapping the root view added to the VRI of the [SurfaceControlViewHost], and - * any attempts to do will throw, which means that once a [View] is added using [updateView] or - * [updateViewAsync], only its properties and binding may be changed, its children views may be - * added, removed or changed and its [WindowManager.LayoutParams] may be changed. - * It also supports asynchronously updating the view hierarchy using [updateViewAsync], in which + * It supports asynchronously updating the view hierarchy using [updateViewAsync], in which * case the update work will be posted on the [ShellMainThread] with no delay. */ class DefaultWindowDecorViewHost( - private val context: Context, + context: Context, @ShellMainThread private val mainScope: CoroutineScope, - private val display: Display, - private val surfaceControlViewHostFactory: SurfaceControlViewHostFactory = { c, d, wwm, s -> - SurfaceControlViewHost(c, d, wwm, s) - } + display: Display, + @VisibleForTesting val viewHostAdapter: SurfaceControlViewHostAdapter = + SurfaceControlViewHostAdapter(context, display) ) : WindowDecorViewHost { - private val rootSurface: SurfaceControl = SurfaceControl.Builder() - .setName("DefaultWindowDecorViewHost surface") - .setContainerLayer() - .setCallsite("DefaultWindowDecorViewHost#init") - .build() - - private var wwm: WindowlessWindowManager? = null - @VisibleForTesting - var viewHost: SurfaceControlViewHost? = null private var currentUpdateJob: Job? = null override val surfaceControl: SurfaceControl - get() = rootSurface + get() = viewHostAdapter.rootSurface override fun updateView( view: View, @@ -92,8 +74,7 @@ class DefaultWindowDecorViewHost( override fun release(t: SurfaceControl.Transaction) { clearCurrentUpdateJob() - viewHost?.release() - t.remove(rootSurface) + viewHostAdapter.release(t) } private fun updateViewHost( @@ -102,45 +83,15 @@ class DefaultWindowDecorViewHost( configuration: Configuration, onDrawTransaction: SurfaceControl.Transaction? ) { - Trace.beginSection("DefaultWindowDecorViewHost#updateViewHost") - if (wwm == null) { - wwm = WindowlessWindowManager(configuration, rootSurface, null) - } - requireWindowlessWindowManager().setConfiguration(configuration) - if (viewHost == null) { - viewHost = surfaceControlViewHostFactory.invoke( - context, - display, - requireWindowlessWindowManager(), - "DefaultWindowDecorViewHost#updateViewHost" - ) - } + viewHostAdapter.prepareViewHost(configuration) onDrawTransaction?.let { - requireViewHost().rootSurfaceControl.applyTransactionOnDraw(it) - } - if (requireViewHost().view == null) { - Trace.beginSection("DefaultWindowDecorViewHost#updateViewHost-setView") - requireViewHost().setView(view, attrs) - Trace.endSection() - } else { - check(requireViewHost().view == view) { "Changing view is not allowed" } - Trace.beginSection("DefaultWindowDecorViewHost#updateViewHost-relayout") - requireViewHost().relayout(attrs) - Trace.endSection() + viewHostAdapter.applyTransactionOnDraw(it) } - Trace.endSection() + viewHostAdapter.updateView(view, attrs) } private fun clearCurrentUpdateJob() { currentUpdateJob?.cancel() currentUpdateJob = null } - - private fun requireWindowlessWindowManager(): WindowlessWindowManager { - return wwm ?: error("Expected non-null windowless window manager") - } - - private fun requireViewHost(): SurfaceControlViewHost { - return viewHost ?: error("Expected non-null view host") - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/PooledWindowDecorViewHostSupplier.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/PooledWindowDecorViewHostSupplier.kt new file mode 100644 index 000000000000..b04188fa82a8 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/PooledWindowDecorViewHostSupplier.kt @@ -0,0 +1,105 @@ +/* + * 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.windowdecor.viewhost + +import android.content.Context +import android.os.Trace +import android.util.Pools +import android.view.Display +import android.view.SurfaceControl +import com.android.wm.shell.shared.annotations.ShellMainThread +import com.android.wm.shell.sysui.ShellInit +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * A [WindowDecorViewHostSupplier] backed by a pool to allow recycling view hosts which may be + * expensive to recreate for each new/updated window decoration. + * + * Callers can obtain [ReusableWindowDecorViewHost] using [acquire], which will return a pooled + * object if available, or create a new instance and return it if needed. When done using a + * [ReusableWindowDecorViewHost], it must be released using [release] to allow it to be sent back + * into the pool and reused later on. + * + * This class also supports pre-warming [ReusableWindowDecorViewHost] instances, which will be put + * into the pool immediately after creation. + */ +class PooledWindowDecorViewHostSupplier( + private val context: Context, + @ShellMainThread private val mainScope: CoroutineScope, + shellInit: ShellInit, + private val viewHostFactory: ReusableWindowDecorViewHost.Factory = + ReusableWindowDecorViewHost.DefaultFactory, + maxPoolSize: Int, + private val preWarmSize: Int, +) : WindowDecorViewHostSupplier<ReusableWindowDecorViewHost> { + + private val pool: Pools.Pool<ReusableWindowDecorViewHost> = Pools.SynchronizedPool(maxPoolSize) + private var nextDecorViewHostId = 0 + + init { + require(preWarmSize <= maxPoolSize) { "Pre-warm size should not exceed pool size" } + shellInit.addInitCallback(this::onShellInit, this) + } + + private fun onShellInit() { + if (preWarmSize <= 0) { + return + } + preWarmViewHosts(preWarmSize) + } + + private fun preWarmViewHosts(preWarmSize: Int) { + mainScope.launch { + // Applying isn't needed, as the surface was never actually shown. + val t = SurfaceControl.Transaction() + repeat(preWarmSize) { + val warmedViewHost = create(context, context.display).apply { + warmUp() + } + // Put the warmed view host in the pool by releasing it. + release(warmedViewHost, t) + } + } + } + + override fun acquire(context: Context, display: Display): ReusableWindowDecorViewHost { + val reusedDecorViewHost = pool.acquire() + if (reusedDecorViewHost != null) { + return reusedDecorViewHost + } + Trace.beginSection("WindowDecorViewHostPool#acquire-new") + val newDecorViewHost = create(context, display) + Trace.endSection() + return newDecorViewHost + } + + override fun release(viewHost: ReusableWindowDecorViewHost, t: SurfaceControl.Transaction) { + val cached = pool.release(viewHost) + if (!cached) { + viewHost.release(t) + } + } + + private fun create(context: Context, display: Display): ReusableWindowDecorViewHost { + return viewHostFactory.create( + context, + mainScope, + display, + nextDecorViewHostId++ + ) + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/ReusableWindowDecorViewHost.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/ReusableWindowDecorViewHost.kt new file mode 100644 index 000000000000..64536d1a7897 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/ReusableWindowDecorViewHost.kt @@ -0,0 +1,161 @@ +/* + * 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.windowdecor.viewhost + +import android.content.Context +import android.content.res.Configuration +import android.graphics.PixelFormat +import android.os.Trace +import android.view.Display +import android.view.SurfaceControl +import android.view.SurfaceControlViewHost +import android.view.View +import android.view.WindowManager +import android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE +import android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH +import android.view.WindowManager.LayoutParams.TYPE_APPLICATION +import android.widget.FrameLayout +import com.android.internal.annotations.VisibleForTesting +import com.android.wm.shell.shared.annotations.ShellMainThread +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch + +/** + * An implementation of [WindowDecorViewHost] that supports: + * 1) Replacing the root [View], meaning [WindowDecorViewHost.updateView] maybe be + * called with different [View] instances. This is useful when reusing [WindowDecorViewHost]s + * instances for vastly different view hierarchies, such as Desktop Windowing's App Handles and + * App Headers. + * 2) Pre-warming of the underlying [SurfaceControlViewHost]s. Useful because their creation and + * first root view assignment are expensive, which is undesirable in latency-sensitive code + * paths like during a shell transition. + */ +class ReusableWindowDecorViewHost( + private val context: Context, + @ShellMainThread private val mainScope: CoroutineScope, + display: Display, + val id: Int, + @VisibleForTesting val viewHostAdapter: SurfaceControlViewHostAdapter = + SurfaceControlViewHostAdapter(context, display) +) : WindowDecorViewHost, Warmable { + + @VisibleForTesting + val rootView = FrameLayout(context) + + private var currentUpdateJob: Job? = null + + override val surfaceControl: SurfaceControl + get() = viewHostAdapter.rootSurface + + override fun warmUp() { + if (viewHostAdapter.isInitialized()) { + // Already warmed up. + return + } + Trace.beginSection("$TAG#warmUp") + viewHostAdapter.prepareViewHost(context.resources.configuration) + viewHostAdapter.updateView( + rootView, + WindowManager.LayoutParams( + 0 /* width*/, + 0 /* height */, + TYPE_APPLICATION, + FLAG_NOT_FOCUSABLE or FLAG_SPLIT_TOUCH, + PixelFormat.TRANSPARENT + ).apply { + setTitle("View root of $TAG#$id") + setTrustedOverlay() + } + ) + Trace.endSection() + } + + override fun updateView( + view: View, + attrs: WindowManager.LayoutParams, + configuration: Configuration, + onDrawTransaction: SurfaceControl.Transaction? + ) { + clearCurrentUpdateJob() + updateViewHost(view, attrs, configuration, onDrawTransaction) + } + + override fun updateViewAsync( + view: View, + attrs: WindowManager.LayoutParams, + configuration: Configuration + ) { + clearCurrentUpdateJob() + currentUpdateJob = mainScope.launch { + updateViewHost(view, attrs, configuration, onDrawTransaction = null) + } + } + + override fun release(t: SurfaceControl.Transaction) { + clearCurrentUpdateJob() + viewHostAdapter.release(t) + } + + private fun updateViewHost( + view: View, + attrs: WindowManager.LayoutParams, + configuration: Configuration, + onDrawTransaction: SurfaceControl.Transaction? + ) { + viewHostAdapter.prepareViewHost(configuration) + onDrawTransaction?.let { + viewHostAdapter.applyTransactionOnDraw(it) + } + rootView.removeAllViews() + rootView.addView(view) + viewHostAdapter.updateView(rootView, attrs) + } + + private fun clearCurrentUpdateJob() { + currentUpdateJob?.cancel() + currentUpdateJob = null + } + + interface Factory { + fun create( + context: Context, + @ShellMainThread mainScope: CoroutineScope, + display: Display, + id: Int + ): ReusableWindowDecorViewHost + } + + object DefaultFactory : Factory { + override fun create( + context: Context, + @ShellMainThread mainScope: CoroutineScope, + display: Display, + id: Int + ): ReusableWindowDecorViewHost { + return ReusableWindowDecorViewHost( + context, + mainScope, + display, + id + ) + } + } + + companion object { + private const val TAG = "ReusableWindowDecorViewHost" + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/SurfaceControlViewHostAdapter.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/SurfaceControlViewHostAdapter.kt new file mode 100644 index 000000000000..a54c9ba67cf8 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/SurfaceControlViewHostAdapter.kt @@ -0,0 +1,111 @@ +/* + * 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.windowdecor.viewhost + +import android.content.Context +import android.content.res.Configuration +import android.view.AttachedSurfaceControl +import android.view.Display +import android.view.SurfaceControl +import android.view.SurfaceControlViewHost +import android.view.View +import android.view.WindowManager +import android.view.WindowlessWindowManager +import androidx.tracing.Trace +import com.android.internal.annotations.VisibleForTesting +typealias SurfaceControlViewHostFactory = + (Context, Display, WindowlessWindowManager, String) -> SurfaceControlViewHost + +/** + * Adapter for a [SurfaceControlViewHost] and its backing [SurfaceControl]. + * + * It does not support swapping the root view added to the VRI of the [SurfaceControlViewHost], and + * any attempts to do will throw, which means that once a [View] is added using [updateView], only + * its properties and binding may be changed, its children views may be added, removed or changed + * and its [WindowManager.LayoutParams] may be changed. + */ +class SurfaceControlViewHostAdapter( + private val context: Context, + private val display: Display, + private val surfaceControlViewHostFactory: SurfaceControlViewHostFactory = { c, d, wwm, s -> + SurfaceControlViewHost(c, d, wwm, s) + } +) { + val rootSurface: SurfaceControl = SurfaceControl.Builder() + .setName("SurfaceControlViewHostAdapter surface") + .setContainerLayer() + .setCallsite("SurfaceControlViewHostAdapter#init") + .build() + + private var wwm: WindowlessWindowManager? = null + @VisibleForTesting + var viewHost: SurfaceControlViewHost? = null + + /** Initialize the [SurfaceControlViewHost] if needed. */ + fun prepareViewHost(configuration: Configuration) { + if (wwm == null) { + wwm = WindowlessWindowManager(configuration, rootSurface, null) + } + requireWindowlessWindowManager().setConfiguration(configuration) + if (viewHost == null) { + viewHost = surfaceControlViewHostFactory.invoke( + context, + display, + requireWindowlessWindowManager(), + "SurfaceControlViewHostAdapter#prepareViewHost" + ) + } + } + + /** + * Request to apply the transaction atomically with the next draw of the view hierarchy. + * See [AttachedSurfaceControl.applyTransactionOnDraw]. + */ + fun applyTransactionOnDraw(t: SurfaceControl.Transaction) { + requireViewHost().rootSurfaceControl.applyTransactionOnDraw(t) + } + + /** Update the view hierarchy of the view host. */ + fun updateView(view: View, attrs: WindowManager.LayoutParams) { + if (requireViewHost().view == null) { + Trace.beginSection("SurfaceControlViewHostAdapter#updateView-setView") + requireViewHost().setView(view, attrs) + Trace.endSection() + } else { + check(requireViewHost().view == view) { "Changing view is not allowed" } + Trace.beginSection("SurfaceControlViewHostAdapter#updateView-relayout") + requireViewHost().relayout(attrs) + Trace.endSection() + } + } + + /** Release the view host and remove the backing surface. */ + fun release(t: SurfaceControl.Transaction) { + viewHost?.release() + t.remove(rootSurface) + } + + /** Whether the view host has had a view hierarchy set. */ + fun isInitialized(): Boolean = viewHost?.view != null + + private fun requireWindowlessWindowManager(): WindowlessWindowManager { + return wwm ?: error("Expected non-null windowless window manager") + } + + private fun requireViewHost(): SurfaceControlViewHost { + return viewHost ?: error("Expected non-null view host") + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/NoopGridConsistencyInteractorKosmos.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/Warmable.kt index e3beff727ae3..0df9bfa2ee78 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/NoopGridConsistencyInteractorKosmos.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewhost/Warmable.kt @@ -13,9 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package com.android.wm.shell.windowdecor.viewhost -package com.android.systemui.qs.panels.domain.interactor - -import com.android.systemui.kosmos.Kosmos - -val Kosmos.noopGridConsistencyInteractor by Kosmos.Fixture { NoopGridConsistencyInteractor() } +/** + * An interface for an object that can be warmed up before it's needed. + */ +interface Warmable { + fun warmUp() +} diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/StartAppMediaProjectionResizeAndDrag.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/StartAppMediaProjectionResizeAndDrag.kt new file mode 100644 index 000000000000..f08e50e0d4ee --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/StartAppMediaProjectionResizeAndDrag.kt @@ -0,0 +1,85 @@ +/* + * 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.scenarios + +import android.app.Instrumentation +import android.platform.test.annotations.Postsubmit +import android.tools.NavBar +import android.tools.Rotation +import android.tools.device.apphelpers.CalculatorAppHelper +import android.tools.traces.parsers.WindowManagerStateHelper +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.android.launcher3.tapl.LauncherInstrumentation +import com.android.server.wm.flicker.helpers.DesktopModeAppHelper +import com.android.server.wm.flicker.helpers.DesktopModeAppHelper.Corners.LEFT_TOP +import com.android.server.wm.flicker.helpers.StartMediaProjectionAppHelper +import com.android.window.flags.Flags +import com.android.wm.shell.Utils +import org.junit.After +import org.junit.Assume +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.BlockJUnit4ClassRunner + +@RunWith(BlockJUnit4ClassRunner::class) +@Postsubmit +open class StartAppMediaProjectionResizeAndDrag { + private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() + private val tapl = LauncherInstrumentation() + private val wmHelper = WindowManagerStateHelper(instrumentation) + private val device = UiDevice.getInstance(instrumentation) + + private val targetApp = CalculatorAppHelper(instrumentation) + private val mediaProjectionAppHelper = StartMediaProjectionAppHelper(instrumentation) + private val testApp = DesktopModeAppHelper(mediaProjectionAppHelper) + + @Rule + @JvmField + val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, Rotation.ROTATION_0) + + @Before + fun setup() { + Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet) + tapl.setEnableRotation(true) + tapl.setExpectedRotation(0) + testApp.enterDesktopWithDrag(wmHelper, device) + } + + @Test + open fun startMediaProjectionAndResize() { + mediaProjectionAppHelper.startSingleAppMediaProjection(wmHelper, targetApp) + + with(DesktopModeAppHelper(targetApp)) { + val windowRect = wmHelper.getWindowRegion(this).bounds + // Set start x-coordinate as center of app header. + val startX = windowRect.centerX() + val startY = windowRect.top + + dragWindow(startX, startY, endX = startX + 150, endY = startY + 150, wmHelper, device) + cornerResize(wmHelper, device, LEFT_TOP, -200, -200) + } + } + + @After + fun teardown() { + testApp.exit(wmHelper) + targetApp.exit(wmHelper) + } +} diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/StartAppMediaProjectionWithMaxDesktopWindows.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/StartAppMediaProjectionWithMaxDesktopWindows.kt new file mode 100644 index 000000000000..717ea306eb77 --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/StartAppMediaProjectionWithMaxDesktopWindows.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.wm.shell.scenarios + +import android.app.Instrumentation +import android.platform.test.annotations.Postsubmit +import android.tools.NavBar +import android.tools.Rotation +import android.tools.device.apphelpers.CalculatorAppHelper +import android.tools.traces.parsers.WindowManagerStateHelper +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.android.launcher3.tapl.LauncherInstrumentation +import com.android.server.wm.flicker.helpers.DesktopModeAppHelper +import com.android.server.wm.flicker.helpers.ImeAppHelper +import com.android.server.wm.flicker.helpers.MailAppHelper +import com.android.server.wm.flicker.helpers.NewTasksAppHelper +import com.android.server.wm.flicker.helpers.SimpleAppHelper +import com.android.server.wm.flicker.helpers.StartMediaProjectionAppHelper +import com.android.window.flags.Flags +import com.android.wm.shell.Utils +import org.junit.After +import org.junit.Assume +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.BlockJUnit4ClassRunner + +@RunWith(BlockJUnit4ClassRunner::class) +@Postsubmit +open class StartAppMediaProjectionWithMaxDesktopWindows { + + val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() + val tapl = LauncherInstrumentation() + val wmHelper = WindowManagerStateHelper(instrumentation) + val device = UiDevice.getInstance(instrumentation) + + private val targetApp = CalculatorAppHelper(instrumentation) + private val mailApp = MailAppHelper(instrumentation) + private val newTasksApp = DesktopModeAppHelper(NewTasksAppHelper(instrumentation)) + private val imeApp = DesktopModeAppHelper(ImeAppHelper(instrumentation)) + private val simpleApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation)) + private val mediaProjectionAppHelper = StartMediaProjectionAppHelper(instrumentation) + private val testApp = DesktopModeAppHelper(mediaProjectionAppHelper) + + @Rule + @JvmField + val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, Rotation.ROTATION_0) + + @Before + fun setup() { + Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet) + tapl.setEnableRotation(true) + tapl.setExpectedRotation(0) + testApp.enterDesktopWithDrag(wmHelper, device) + } + + @Test + open fun startMediaProjection() { + // TODO(b/366455106) - handle max task Limit + mediaProjectionAppHelper.startSingleAppMediaProjection(wmHelper, targetApp) + mailApp.launchViaIntent(wmHelper) + simpleApp.launchViaIntent(wmHelper) + newTasksApp.launchViaIntent(wmHelper) + imeApp.launchViaIntent(wmHelper) + } + + @After + fun teardown() { + mailApp.exit(wmHelper) + simpleApp.exit(wmHelper) + newTasksApp.exit(wmHelper) + imeApp.exit(wmHelper) + targetApp.exit(wmHelper) + testApp.exit(wmHelper) + } +} diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/StartScreenMediaProjectionWithMaxDesktopWindows.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/StartScreenMediaProjectionWithMaxDesktopWindows.kt new file mode 100644 index 000000000000..005195296c62 --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/StartScreenMediaProjectionWithMaxDesktopWindows.kt @@ -0,0 +1,85 @@ +/* + * 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.scenarios + +import android.app.Instrumentation +import android.platform.test.annotations.Postsubmit +import android.tools.NavBar +import android.tools.Rotation +import android.tools.traces.parsers.WindowManagerStateHelper +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.android.launcher3.tapl.LauncherInstrumentation +import com.android.server.wm.flicker.helpers.DesktopModeAppHelper +import com.android.server.wm.flicker.helpers.ImeAppHelper +import com.android.server.wm.flicker.helpers.MailAppHelper +import com.android.server.wm.flicker.helpers.NewTasksAppHelper +import com.android.server.wm.flicker.helpers.SimpleAppHelper +import com.android.server.wm.flicker.helpers.StartMediaProjectionAppHelper +import com.android.window.flags.Flags +import com.android.wm.shell.Utils +import org.junit.After +import org.junit.Assume +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.BlockJUnit4ClassRunner + +@RunWith(BlockJUnit4ClassRunner::class) +@Postsubmit +open class StartScreenMediaProjectionWithMaxDesktopWindows { + private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() + private val tapl = LauncherInstrumentation() + private val wmHelper = WindowManagerStateHelper(instrumentation) + private val device = UiDevice.getInstance(instrumentation) + + @Rule + @JvmField + val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, Rotation.ROTATION_0) + + private val mailApp = DesktopModeAppHelper(MailAppHelper(instrumentation)) + private val newTasksApp = DesktopModeAppHelper(NewTasksAppHelper(instrumentation)) + private val imeApp = DesktopModeAppHelper(ImeAppHelper(instrumentation)) + private val simpleApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation)) + private val mediaProjectionAppHelper = StartMediaProjectionAppHelper(instrumentation) + private val testApp = DesktopModeAppHelper(mediaProjectionAppHelper) + + @Before + fun setup() { + Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet) + testApp.enterDesktopWithDrag(wmHelper, device) + } + + @Test + open fun startMediaProjection() { + mediaProjectionAppHelper.startEntireScreenMediaProjection(wmHelper) + simpleApp.launchViaIntent(wmHelper) + mailApp.launchViaIntent(wmHelper) + newTasksApp.launchViaIntent(wmHelper) + imeApp.launchViaIntent(wmHelper) + } + + @After + fun teardown() { + testApp.exit(wmHelper) + simpleApp.exit(wmHelper) + mailApp.exit(wmHelper) + newTasksApp.exit(wmHelper) + imeApp.exit(wmHelper) + } +} diff --git a/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/Android.bp b/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/Android.bp new file mode 100644 index 000000000000..85e6a8d1d865 --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/Android.bp @@ -0,0 +1,38 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +android_test { + name: "WMShellFlickerTestsMediaProjection", + defaults: ["WMShellFlickerTestsDefault"], + manifest: "AndroidManifest.xml", + test_config_template: "AndroidTestTemplate.xml", + srcs: ["src/**/*.kt"], + static_libs: [ + "WMShellFlickerTestsBase", + "WMShellScenariosMediaProjection", + "WMShellTestUtils", + ], + data: ["trace_config/*"], +} diff --git a/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/AndroidManifest.xml b/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/AndroidManifest.xml new file mode 100644 index 000000000000..74b0daf3a2aa --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/AndroidManifest.xml @@ -0,0 +1,85 @@ +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="com.android.wm.shell.flicker"> + + <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29"/> + <!-- Read and write traces from external storage --> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> + <!-- Allow the test to write directly to /sdcard/ --> + <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> + <!-- Write secure settings --> + <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> + <!-- Capture screen contents --> + <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" /> + <!-- Enable / Disable tracing !--> + <uses-permission android:name="android.permission.DUMP" /> + <!-- Run layers trace --> + <uses-permission android:name="android.permission.HARDWARE_TEST"/> + <!-- Capture screen recording --> + <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"/> + <!-- Workaround grant runtime permission exception from b/152733071 --> + <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/> + <uses-permission android:name="android.permission.READ_LOGS"/> + <!-- Force-stop test apps --> + <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"/> + <!-- Control test app's media session --> + <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/> + <!-- ATM.removeRootTasksWithActivityTypes() --> + <uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS" /> + <!-- Enable bubble notification--> + <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" /> + <!-- Allow the test to connect to perfetto trace processor --> + <uses-permission android:name="android.permission.INTERNET"/> + <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> + <uses-permission android:name="android.permission.MANAGE_MEDIA_PROJECTION" /> + + <!-- Allow the test to write directly to /sdcard/ and connect to trace processor --> + <application android:requestLegacyExternalStorage="true" + android:networkSecurityConfig="@xml/network_security_config" + android:largeHeap="true"> + <uses-library android:name="android.test.runner"/> + + <service android:name=".NotificationListener" + android:exported="true" + android:label="WMShellTestsNotificationListenerService" + android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> + <intent-filter> + <action android:name="android.service.notification.NotificationListenerService" /> + </intent-filter> + </service> + + <service android:name="com.android.wm.shell.flicker.utils.MediaProjectionService" + android:foregroundServiceType="mediaProjection" + android:label="WMShellTestsMediaProjectionService" + android:enabled="true"> + </service> + + <!-- (b/197936012) Remove startup provider due to test timeout issue --> + <provider + android:name="androidx.startup.InitializationProvider" + android:authorities="${applicationId}.androidx-startup" + tools:node="remove" /> + </application> + + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.wm.shell.flicker" + android:label="WindowManager Shell Flicker Tests"> + </instrumentation> +</manifest> diff --git a/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/AndroidTestTemplate.xml new file mode 100644 index 000000000000..40dbbac32c7f --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/AndroidTestTemplate.xml @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<configuration description="Runs WindowManager Shell Flicker Tests {MODULE}"> + <option name="test-tag" value="FlickerTests"/> + <!-- Needed for storing the perfetto trace files in the sdcard/test_results--> + <option name="isolated-storage" value="false"/> + + <target_preparer class="com.android.tradefed.targetprep.DeviceSetup"> + <!-- disable DeprecatedTargetSdk warning --> + <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/> + <!-- keeps the screen on during tests --> + <option name="screen-always-on" value="on"/> + <!-- prevents the phone from restarting --> + <option name="force-skip-system-props" value="true"/> + <!-- set WM tracing verbose level to all --> + <option name="run-command" value="cmd window tracing level all"/> + <!-- set WM tracing to frame (avoid incomplete states) --> + <option name="run-command" value="cmd window tracing frame"/> + <!-- disable betterbug as it's log collection dialogues cause flakes in e2e tests --> + <option name="run-command" value="pm disable com.google.android.internal.betterbug"/> + <!-- ensure lock screen mode is swipe --> + <option name="run-command" value="locksettings set-disabled false"/> + <!-- restart launcher to activate TAPL --> + <option name="run-command" + value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher"/> + <!-- Increase trace size: 20mb for WM and 80mb for SF --> + <option name="run-command" value="cmd window tracing size 20480"/> + <option name="run-command" value="su root service call SurfaceFlinger 1029 i32 81920"/> + </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> + <option name="test-user-token" value="%TEST_USER%"/> + <option name="run-command" value="rm -rf /data/user/%TEST_USER%/files/*"/> + <option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1"/> + <option name="run-command" value="settings put system show_touches 1"/> + <option name="run-command" value="settings put system pointer_location 1"/> + <option name="teardown-command" + value="settings delete secure show_ime_with_hard_keyboard"/> + <option name="teardown-command" value="settings delete system show_touches"/> + <option name="teardown-command" value="settings delete system pointer_location"/> + <option name="teardown-command" + value="cmd overlay enable com.android.internal.systemui.navbar.gestural"/> + </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true"/> + <option name="test-file-name" value="{MODULE}.apk"/> + <option name="test-file-name" value="FlickerTestApp.apk"/> + </target_preparer> + + <!-- Needed for pushing the trace config file --> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/> + <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> + <option name="push-file" + key="trace_config.textproto" + value="/data/misc/perfetto-traces/trace_config.textproto" + /> + <!--Install the content provider automatically when we push some file in sdcard folder.--> + <!--Needed to avoid the installation during the test suite.--> + <option name="push-file" key="trace_config.textproto" value="/sdcard/sample.textproto"/> + </target_preparer> + <test class="com.android.tradefed.testtype.AndroidJUnitTest"> + <option name="package" value="{PACKAGE}"/> + <option name="shell-timeout" value="6600s"/> + <option name="test-timeout" value="6000s"/> + <option name="hidden-api-checks" value="false"/> + <option name="device-listeners" value="android.device.collectors.PerfettoListener"/> + <!-- PerfettoListener related arguments --> + <option name="instrumentation-arg" key="perfetto_config_text_proto" value="true"/> + <option name="instrumentation-arg" + key="perfetto_config_file" + value="trace_config.textproto" + /> + <option name="instrumentation-arg" key="per_run" value="true"/> + <option name="instrumentation-arg" key="perfetto_persist_pid_track" value="true"/> + </test> + <!-- Needed for pulling the collected trace config on to the host --> + <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> + <option name="pull-pattern-keys" value="perfetto_file_path"/> + <option name="directory-keys" + value="/data/user/0/com.android.wm.shell.flicker/files"/> + <option name="collect-on-run-ended-only" value="true"/> + <option name="clean-up" value="true"/> + </metrics_collector> +</configuration> diff --git a/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/res/xml/network_security_config.xml b/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/res/xml/network_security_config.xml new file mode 100644 index 000000000000..4bd9ca049f55 --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/res/xml/network_security_config.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<network-security-config> + <domain-config cleartextTrafficPermitted="true"> + <domain includeSubdomains="true">localhost</domain> + </domain-config> +</network-security-config> diff --git a/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/trace_config/trace_config.textproto b/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/trace_config/trace_config.textproto new file mode 100644 index 000000000000..9f2e49755fec --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/mediaprojection/flicker-service/trace_config/trace_config.textproto @@ -0,0 +1,71 @@ +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# proto-message: TraceConfig + +# Enable periodic flushing of the trace buffer into the output file. +write_into_file: true + +# Writes the userspace buffer into the file every 1s. +file_write_period_ms: 2500 + +# See b/126487238 - we need to guarantee ordering of events. +flush_period_ms: 30000 + +# The trace buffers needs to be big enough to hold |file_write_period_ms| of +# trace data. The trace buffer sizing depends on the number of trace categories +# enabled and the device activity. + +# RSS events +buffers: { + size_kb: 63488 + fill_policy: RING_BUFFER +} + +data_sources { + config { + name: "linux.process_stats" + target_buffer: 0 + # polled per-process memory counters and process/thread names. + # If you don't want the polled counters, remove the "process_stats_config" + # section, but keep the data source itself as it still provides on-demand + # thread/process naming for ftrace data below. + process_stats_config { + scan_all_processes_on_start: true + } + } +} + +data_sources: { + config { + name: "linux.ftrace" + ftrace_config { + ftrace_events: "ftrace/print" + ftrace_events: "task/task_newtask" + ftrace_events: "task/task_rename" + atrace_categories: "ss" + atrace_categories: "wm" + atrace_categories: "am" + atrace_categories: "aidl" + atrace_categories: "input" + atrace_categories: "binder_driver" + atrace_categories: "sched_process_exit" + atrace_apps: "com.android.server.wm.flicker.testapp" + atrace_apps: "com.android.systemui" + atrace_apps: "com.android.wm.shell.flicker.service" + atrace_apps: "com.google.android.apps.nexuslauncher" + } + } +} + diff --git a/libs/WindowManager/Shell/tests/e2e/mediaprojection/scenarios/Android.bp b/libs/WindowManager/Shell/tests/e2e/mediaprojection/scenarios/Android.bp new file mode 100644 index 000000000000..997a0af68d1a --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/mediaprojection/scenarios/Android.bp @@ -0,0 +1,46 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // 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"], +} + +java_library { + name: "WMShellScenariosMediaProjection", + platform_apis: true, + optimize: { + enabled: false, + }, + srcs: ["src/**/*.kt"], + static_libs: [ + "WMShellFlickerTestsBase", + "WMShellTestUtils", + "wm-shell-flicker-utils", + "androidx.test.ext.junit", + "flickertestapplib", + "flickerlib-helpers", + "flickerlib-trace_processor_shell", + "platform-test-annotations", + "wm-flicker-common-app-helpers", + "launcher-helper-lib", + "launcher-aosp-tapl", + ], +} diff --git a/libs/WindowManager/Shell/tests/e2e/mediaprojection/scenarios/src/com/android/wm/shell/scenarios/StartAppMediaProjectionWithDisplayRotations.kt b/libs/WindowManager/Shell/tests/e2e/mediaprojection/scenarios/src/com/android/wm/shell/scenarios/StartAppMediaProjectionWithDisplayRotations.kt new file mode 100644 index 000000000000..1573b58853da --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/mediaprojection/scenarios/src/com/android/wm/shell/scenarios/StartAppMediaProjectionWithDisplayRotations.kt @@ -0,0 +1,78 @@ +/* + * 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.scenarios + +import android.app.Instrumentation +import android.platform.test.annotations.Postsubmit +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.rules.ChangeDisplayOrientationRule +import android.tools.device.apphelpers.CalculatorAppHelper +import android.tools.traces.parsers.WindowManagerStateHelper +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.android.launcher3.tapl.LauncherInstrumentation +import com.android.server.wm.flicker.helpers.DesktopModeAppHelper +import com.android.server.wm.flicker.helpers.StartMediaProjectionAppHelper +import com.android.wm.shell.Utils +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.BlockJUnit4ClassRunner + +@RunWith(BlockJUnit4ClassRunner::class) +@Postsubmit +open class StartAppMediaProjectionWithDisplayRotations { + + val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() + val tapl = LauncherInstrumentation() + val wmHelper = WindowManagerStateHelper(instrumentation) + val device = UiDevice.getInstance(instrumentation) + + private val initialRotation = Rotation.ROTATION_0 + private val targetApp = CalculatorAppHelper(instrumentation) + private val mediaProjectionAppHelper = StartMediaProjectionAppHelper(instrumentation) + private val testApp = DesktopModeAppHelper(mediaProjectionAppHelper) + + @Rule + @JvmField + val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, initialRotation) + + @Before + fun setup() { + tapl.setEnableRotation(true) + tapl.setExpectedRotation(initialRotation.value) + testApp.launchViaIntent(wmHelper) + } + + @Test + open fun startMediaProjectionAndRotate() { + mediaProjectionAppHelper.startSingleAppMediaProjection(wmHelper, targetApp) + wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify() + + ChangeDisplayOrientationRule.setRotation(Rotation.ROTATION_90) + ChangeDisplayOrientationRule.setRotation(Rotation.ROTATION_270) + ChangeDisplayOrientationRule.setRotation(Rotation.ROTATION_0) + } + + @After + fun teardown() { + testApp.exit(wmHelper) + } +} diff --git a/libs/WindowManager/Shell/tests/e2e/mediaprojection/scenarios/src/com/android/wm/shell/scenarios/StartScreenMediaProjectionWithDisplayRotations.kt b/libs/WindowManager/Shell/tests/e2e/mediaprojection/scenarios/src/com/android/wm/shell/scenarios/StartScreenMediaProjectionWithDisplayRotations.kt new file mode 100644 index 000000000000..e80a895c1aa6 --- /dev/null +++ b/libs/WindowManager/Shell/tests/e2e/mediaprojection/scenarios/src/com/android/wm/shell/scenarios/StartScreenMediaProjectionWithDisplayRotations.kt @@ -0,0 +1,75 @@ +/* + * 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.scenarios + +import android.app.Instrumentation +import android.platform.test.annotations.Postsubmit +import android.tools.NavBar +import android.tools.Rotation +import android.tools.flicker.rules.ChangeDisplayOrientationRule +import android.tools.traces.parsers.WindowManagerStateHelper +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import com.android.launcher3.tapl.LauncherInstrumentation +import com.android.server.wm.flicker.helpers.DesktopModeAppHelper +import com.android.server.wm.flicker.helpers.StartMediaProjectionAppHelper +import com.android.wm.shell.Utils +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.BlockJUnit4ClassRunner + +@RunWith(BlockJUnit4ClassRunner::class) +@Postsubmit +open class StartScreenMediaProjectionWithDisplayRotations { + + val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() + val tapl = LauncherInstrumentation() + val wmHelper = WindowManagerStateHelper(instrumentation) + val device = UiDevice.getInstance(instrumentation) + + private val initialRotation = Rotation.ROTATION_0 + private val mediaProjectionAppHelper = StartMediaProjectionAppHelper(instrumentation) + private val testApp = DesktopModeAppHelper(mediaProjectionAppHelper) + + @Rule + @JvmField + val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, initialRotation) + + @Before + fun setup() { + tapl.setEnableRotation(true) + testApp.launchViaIntent(wmHelper) + } + + @Test + open fun startMediaProjectionAndRotate() { + mediaProjectionAppHelper.startEntireScreenMediaProjection(wmHelper) + wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify() + + ChangeDisplayOrientationRule.setRotation(Rotation.ROTATION_90) + ChangeDisplayOrientationRule.setRotation(Rotation.ROTATION_270) + ChangeDisplayOrientationRule.setRotation(initialRotation) + } + + @After + fun teardown() { + testApp.exit(wmHelper) + } +} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/MediaProjectionService.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/MediaProjectionService.kt new file mode 100644 index 000000000000..aa4e216f01a2 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/MediaProjectionService.kt @@ -0,0 +1,110 @@ +/* + * 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.flicker.utils + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.Service +import android.content.Intent +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.drawable.Icon +import android.os.IBinder +import android.os.Message +import android.os.Messenger +import android.os.RemoteException +import android.util.Log + +class MediaProjectionService : Service() { + + private var mTestBitmap: Bitmap? = null + + private val notificationId: Int = 1 + private val notificationChannelId: String = "MediaProjectionFlickerTest" + private val notificationChannelName = "FlickerMediaProjectionService" + + var mMessenger: Messenger? = null + + override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { + mMessenger = intent.extras?.getParcelable( + MediaProjectionUtils.EXTRA_MESSENGER, Messenger::class.java) + startForeground() + return super.onStartCommand(intent, flags, startId) + } + + override fun onBind(intent: Intent?): IBinder? = null + + override fun onDestroy() { + mTestBitmap?.recycle() + mTestBitmap = null + sendMessage(MediaProjectionUtils.MSG_SERVICE_DESTROYED) + super.onDestroy() + } + + private fun createNotificationIcon(): Icon { + Log.d(TAG, "createNotification") + + mTestBitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888) + val canvas = Canvas(mTestBitmap!!) + canvas.drawColor(Color.BLUE) + return Icon.createWithBitmap(mTestBitmap) + } + + private fun startForeground() { + Log.d(TAG, "startForeground") + val channel = NotificationChannel( + notificationChannelId, + notificationChannelName, NotificationManager.IMPORTANCE_NONE + ) + channel.lockscreenVisibility = Notification.VISIBILITY_PRIVATE + + val notificationManager: NotificationManager = + getSystemService(NotificationManager::class.java) + notificationManager.createNotificationChannel(channel) + + val notificationBuilder: Notification.Builder = + Notification.Builder(this, notificationChannelId) + + val notification = notificationBuilder.setOngoing(true) + .setContentTitle("App is running") + .setSmallIcon(createNotificationIcon()) + .setCategory(Notification.CATEGORY_SERVICE) + .setContentText("Context") + .build() + + startForeground(notificationId, notification) + sendMessage(MediaProjectionUtils.MSG_START_FOREGROUND_DONE) + } + + fun sendMessage(what: Int) { + Log.d(TAG, "sendMessage") + with(Message.obtain()) { + this.what = what + try { + mMessenger!!.send(this) + } catch (e: RemoteException) { + Log.d(TAG, "Unable to send message", e) + } + } + } + + companion object { + private const val TAG: String = "FlickerMediaProjectionService" + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridConsistencyInteractorKosmos.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/MediaProjectionUtils.kt index 320c2ec1bb99..f9706969ff11 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridConsistencyInteractorKosmos.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/MediaProjectionUtils.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package com.android.systemui.qs.panels.domain.interactor +package com.android.wm.shell.flicker.utils -import com.android.systemui.kosmos.Kosmos - -val Kosmos.infiniteGridConsistencyInteractor by - Kosmos.Fixture { - InfiniteGridConsistencyInteractor(iconTilesInteractor, fixedColumnsSizeInteractor) - } +object MediaProjectionUtils { + const val REQUEST_CODE: Int = 99 + const val MSG_START_FOREGROUND_DONE: Int = 1 + const val MSG_SERVICE_DESTROYED: Int = 2 + const val EXTRA_MESSENGER: String = "messenger" +}
\ No newline at end of file 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 b53ea3837178..227060d15640 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 @@ -137,6 +137,8 @@ public class BackAnimationControllerTest extends ShellTestCase { private Transitions mTransitions; @Mock private RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer; + @Mock + private Handler mHandler; private BackAnimationController mController; private TestableContentResolver mContentResolver; @@ -161,13 +163,14 @@ public class BackAnimationControllerTest extends ShellTestCase { mTestableLooper = TestableLooper.get(this); mShellInit = spy(new ShellInit(mShellExecutor)); mDefaultCrossActivityBackAnimation = new DefaultCrossActivityBackAnimation(mContext, - mAnimationBackground, mRootTaskDisplayAreaOrganizer); - mCrossTaskBackAnimation = new CrossTaskBackAnimation(mContext, mAnimationBackground); + mAnimationBackground, mRootTaskDisplayAreaOrganizer, mHandler); + mCrossTaskBackAnimation = new CrossTaskBackAnimation(mContext, mAnimationBackground, + mHandler); mShellBackAnimationRegistry = new ShellBackAnimationRegistry(mDefaultCrossActivityBackAnimation, mCrossTaskBackAnimation, /* dialogCloseAnimation= */ null, new CustomCrossActivityBackAnimation(mContext, mAnimationBackground, - mRootTaskDisplayAreaOrganizer), + mRootTaskDisplayAreaOrganizer, mHandler), /* defaultBackToHomeAnimation= */ null); mController = new BackAnimationController( @@ -181,7 +184,8 @@ public class BackAnimationControllerTest extends ShellTestCase { mAnimationBackground, mShellBackAnimationRegistry, mShellCommandHandler, - mTransitions); + mTransitions, + mHandler); mShellInit.init(); mShellExecutor.flushAll(); mTouchableRegion = new Rect(0, 0, 100, 100); @@ -344,7 +348,8 @@ public class BackAnimationControllerTest extends ShellTestCase { mAnimationBackground, mShellBackAnimationRegistry, mShellCommandHandler, - mTransitions); + mTransitions, + mHandler); shellInit.init(); registerAnimation(BackNavigationInfo.TYPE_RETURN_TO_HOME); @@ -898,7 +903,8 @@ public class BackAnimationControllerTest extends ShellTestCase { new BackAnimationRunner( mAnimatorCallback, mBackAnimationRunner, - mContext)); + mContext, + mHandler)); } private void unregisterAnimation(int type) { 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 080ad901c656..5b5ef6f48789 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 @@ -22,6 +22,7 @@ import android.app.WindowConfiguration import android.graphics.Color import android.graphics.Point import android.graphics.Rect +import android.os.Handler import android.os.RemoteException import android.testing.AndroidTestingRunner import android.testing.TestableLooper @@ -66,6 +67,7 @@ class CustomCrossActivityBackAnimationTest : ShellTestCase() { @Mock private lateinit var transitionAnimation: TransitionAnimation @Mock private lateinit var appCompatTaskInfo: AppCompatTaskInfo @Mock private lateinit var transaction: Transaction + @Mock private lateinit var handler: Handler private lateinit var customCrossActivityBackAnimation: CustomCrossActivityBackAnimation private lateinit var customAnimationLoader: CustomAnimationLoader @@ -80,7 +82,8 @@ class CustomCrossActivityBackAnimationTest : ShellTestCase() { backAnimationBackground, rootTaskDisplayAreaOrganizer, transaction, - customAnimationLoader + customAnimationLoader, + handler, ) whenever(transitionAnimation.loadAppTransitionAnimation(eq(PACKAGE_NAME), eq(OPEN_RES_ID))) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java index f5847cc27071..cf69704a0470 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.verify; import android.content.res.Configuration; import android.graphics.Rect; +import android.os.Handler; import android.os.SystemClock; import android.provider.DeviceConfig; import android.view.InputDevice; @@ -55,6 +56,7 @@ public class DividerViewTest extends ShellTestCase { private @Mock DisplayController mDisplayController; private @Mock DisplayImeController mDisplayImeController; private @Mock ShellTaskOrganizer mTaskOrganizer; + private @Mock Handler mHandler; private SplitLayout mSplitLayout; private DividerView mDividerView; @@ -65,7 +67,7 @@ public class DividerViewTest extends ShellTestCase { Configuration configuration = getConfiguration(); mSplitLayout = new SplitLayout("TestSplitLayout", mContext, configuration, mSplitLayoutHandler, mCallbacks, mDisplayController, mDisplayImeController, - mTaskOrganizer, SplitLayout.PARALLAX_NONE); + mTaskOrganizer, SplitLayout.PARALLAX_NONE, mHandler); SplitWindowManager splitWindowManager = new SplitWindowManager("TestSplitWindowManager", mContext, configuration, mCallbacks); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java index 82b3a7de521b..177e47a342f6 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java @@ -35,6 +35,7 @@ import static org.mockito.Mockito.verify; import android.app.ActivityManager; import android.content.res.Configuration; import android.graphics.Rect; +import android.os.Handler; import android.window.WindowContainerTransaction; import androidx.test.annotation.UiThreadTest; @@ -65,6 +66,7 @@ public class SplitLayoutTests extends ShellTestCase { @Mock DisplayImeController mDisplayImeController; @Mock ShellTaskOrganizer mTaskOrganizer; @Mock WindowContainerTransaction mWct; + @Mock Handler mHandler; @Captor ArgumentCaptor<Runnable> mRunnableCaptor; private SplitLayout mSplitLayout; @@ -80,7 +82,8 @@ public class SplitLayoutTests extends ShellTestCase { mDisplayController, mDisplayImeController, mTaskOrganizer, - SplitLayout.PARALLAX_NONE)); + SplitLayout.PARALLAX_NONE, + mHandler)); } @Test 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 10557dd9b439..e610ebd6bfab 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 @@ -18,7 +18,9 @@ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RecentTaskInfo import android.app.ActivityManager.RunningTaskInfo +import android.app.ActivityOptions import android.app.KeyguardManager +import android.app.PendingIntent import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM @@ -38,11 +40,13 @@ import android.graphics.Point import android.graphics.PointF import android.graphics.Rect 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 +import android.view.DragEvent import android.view.Gravity import android.view.SurfaceControl import android.view.WindowManager @@ -107,6 +111,7 @@ import com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS import com.android.wm.shell.transition.Transitions.TransitionHandler import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage +import java.util.function.Consumer import java.util.Optional import junit.framework.Assert.assertFalse import junit.framework.Assert.assertTrue @@ -131,8 +136,8 @@ import org.mockito.Mockito.verify import org.mockito.kotlin.any import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.atLeastOnce -import org.mockito.kotlin.eq import org.mockito.kotlin.capture +import org.mockito.kotlin.eq import org.mockito.kotlin.whenever import org.mockito.quality.Strictness @@ -177,6 +182,7 @@ class DesktopTasksControllerTest : ShellTestCase() { private lateinit var mockInteractionJankMonitor: InteractionJankMonitor @Mock private lateinit var mockSurface: SurfaceControl @Mock private lateinit var taskbarDesktopTaskListener: TaskbarDesktopTaskListener + @Mock private lateinit var mockHandler: Handler private lateinit var mockitoSession: StaticMockitoSession private lateinit var controller: DesktopTasksController @@ -217,7 +223,8 @@ class DesktopTasksControllerTest : ShellTestCase() { shellTaskOrganizer, MAX_TASK_LIMIT, mockInteractionJankMonitor, - mContext) + mContext, + mockHandler) whenever(shellTaskOrganizer.getRunningTasks(anyInt())).thenAnswer { runningTasks } whenever(transitions.startTransition(anyInt(), any(), isNull())).thenAnswer { Binder() } @@ -270,7 +277,9 @@ class DesktopTasksControllerTest : ShellTestCase() { shellExecutor, Optional.of(desktopTasksLimiter), recentTasksController, - mockInteractionJankMonitor) + mockInteractionJankMonitor, + mockHandler, + ) } @After @@ -1666,6 +1675,36 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test + fun handleRequest_fullscreenTask_noTasks_enforceDesktop_freeformDisplay_returnFreeformWCT() { + assumeTrue(ENABLE_SHELL_TRANSITIONS) + whenever(DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(context)).thenReturn(true) + val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!! + tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM + + val fullscreenTask = createFullscreenTask() + val wct = controller.handleRequest(Binder(), createTransition(fullscreenTask)) + + assertNotNull(wct, "should handle request") + assertThat(wct.changes[fullscreenTask.token.asBinder()]?.windowingMode) + .isEqualTo(WINDOWING_MODE_UNDEFINED) + assertThat(wct.hierarchyOps).hasSize(1) + wct.assertReorderAt(0, fullscreenTask, toTop = true) + } + + @Test + fun handleRequest_fullscreenTask_noTasks_enforceDesktop_fullscreenDisplay_returnNull() { + assumeTrue(ENABLE_SHELL_TRANSITIONS) + whenever(DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(context)).thenReturn(true) + val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!! + tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN + + val fullscreenTask = createFullscreenTask() + val wct = controller.handleRequest(Binder(), createTransition(fullscreenTask)) + + assertThat(wct).isNull() + } + + @Test fun handleRequest_fullscreenTask_freeformNotVisible_returnNull() { assumeTrue(ENABLE_SHELL_TRANSITIONS) @@ -2956,6 +2995,8 @@ class DesktopTasksControllerTest : ShellTestCase() { screenOrientation = SCREEN_ORIENTATION_LANDSCAPE configuration.windowConfiguration.appBounds = bounds } + appCompatTaskInfo.topActivityLetterboxAppWidth = bounds.width() + appCompatTaskInfo.topActivityLetterboxAppHeight = bounds.height() isResizeable = false } @@ -3050,6 +3091,95 @@ class DesktopTasksControllerTest : ShellTestCase() { assertThat(taskRepository.removeBoundsBeforeMaximize(task.taskId)).isNull() } + + @Test + fun onUnhandledDrag_newFreeformIntent() { + testOnUnhandledDrag(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR, + PointF(1200f, 700f), + Rect(240, 700, 2160, 1900)) + } + + @Test + fun onUnhandledDrag_newFreeformIntentSplitLeft() { + testOnUnhandledDrag(DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR, + PointF(50f, 700f), + Rect(0, 0, 500, 1000)) + } + + @Test + fun onUnhandledDrag_newFreeformIntentSplitRight() { + testOnUnhandledDrag(DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR, + PointF(2500f, 700f), + Rect(500, 0, 1000, 1000)) + } + + @Test + fun onUnhandledDrag_newFullscreenIntent() { + testOnUnhandledDrag(DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR, + PointF(1200f, 50f), + Rect()) + } + + /** + * Assert that an unhandled drag event launches a PendingIntent with the + * windowing mode and bounds we are expecting. + */ + private fun testOnUnhandledDrag( + indicatorType: DesktopModeVisualIndicator.IndicatorType, + inputCoordinate: PointF, + expectedBounds: Rect + ) { + setUpLandscapeDisplay() + val task = setUpFreeformTask() + markTaskVisible(task) + task.isFocused = true + val runningTasks = ArrayList<RunningTaskInfo>() + runningTasks.add(task) + val spyController = spy(controller) + val mockPendingIntent = mock(PendingIntent::class.java) + val mockDragEvent = mock(DragEvent::class.java) + val mockCallback = mock(Consumer::class.java) + val b = SurfaceControl.Builder() + b.setName("test surface") + val dragSurface = b.build() + whenever(shellTaskOrganizer.runningTasks).thenReturn(runningTasks) + whenever(mockDragEvent.dragSurface).thenReturn(dragSurface) + whenever(mockDragEvent.x).thenReturn(inputCoordinate.x) + whenever(mockDragEvent.y).thenReturn(inputCoordinate.y) + whenever(multiInstanceHelper.supportsMultiInstanceSplit(anyOrNull())).thenReturn(true) + whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) + doReturn(indicatorType) + .whenever(spyController).updateVisualIndicator( + eq(task), + anyOrNull(), + anyOrNull(), + anyOrNull(), + eq(DesktopModeVisualIndicator.DragStartState.DRAGGED_INTENT) + ) + + spyController.onUnhandledDrag( + mockPendingIntent, + mockDragEvent, + mockCallback as Consumer<Boolean> + ) + val arg: ArgumentCaptor<WindowContainerTransaction> = + ArgumentCaptor.forClass(WindowContainerTransaction::class.java) + var expectedWindowingMode: Int + if (indicatorType == DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR) { + expectedWindowingMode = WINDOWING_MODE_FULLSCREEN + // Fullscreen launches currently use default transitions + verify(transitions).startTransition(any(), capture(arg), anyOrNull()) + } else { + expectedWindowingMode = WINDOWING_MODE_FREEFORM + // All other launches use a special handler. + verify(dragAndDropTransitionHandler).handleDropEvent(capture(arg)) + } + assertThat(ActivityOptions.fromBundle(arg.value.hierarchyOps[0].launchOptions) + .launchWindowingMode).isEqualTo(expectedWindowingMode) + assertThat(ActivityOptions.fromBundle(arg.value.hierarchyOps[0].launchOptions) + .launchBounds).isEqualTo(expectedBounds) + } + private val desktopWallpaperIntent: Intent get() = Intent(context, DesktopWallpaperActivity::class.java) @@ -3114,6 +3244,18 @@ class DesktopTasksControllerTest : ShellTestCase() { appCompatTaskInfo.isUserFullscreenOverrideEnabled = enableUserFullscreenOverride appCompatTaskInfo.isSystemFullscreenOverrideEnabled = enableSystemFullscreenOverride + if (deviceOrientation == ORIENTATION_LANDSCAPE) { + configuration.windowConfiguration.appBounds = + Rect(0, 0, DISPLAY_DIMENSION_LONG, DISPLAY_DIMENSION_SHORT) + appCompatTaskInfo.topActivityLetterboxAppWidth = DISPLAY_DIMENSION_LONG + appCompatTaskInfo.topActivityLetterboxAppHeight = DISPLAY_DIMENSION_SHORT + } else { + configuration.windowConfiguration.appBounds = + Rect(0, 0, DISPLAY_DIMENSION_SHORT, DISPLAY_DIMENSION_LONG) + appCompatTaskInfo.topActivityLetterboxAppWidth = DISPLAY_DIMENSION_SHORT + appCompatTaskInfo.topActivityLetterboxAppHeight = DISPLAY_DIMENSION_LONG + } + if (shouldLetterbox) { appCompatTaskInfo.setHasMinAspectRatioOverride(aspectRatioOverrideApplied) if (deviceOrientation == ORIENTATION_LANDSCAPE && @@ -3130,14 +3272,6 @@ class DesktopTasksControllerTest : ShellTestCase() { appCompatTaskInfo.topActivityLetterboxAppHeight = 1200 } } - - if (deviceOrientation == ORIENTATION_LANDSCAPE) { - configuration.windowConfiguration.appBounds = - Rect(0, 0, DISPLAY_DIMENSION_LONG, DISPLAY_DIMENSION_SHORT) - } else { - configuration.windowConfiguration.appBounds = - Rect(0, 0, DISPLAY_DIMENSION_SHORT, DISPLAY_DIMENSION_LONG) - } } whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) runningTasks.add(task) 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 2d0e428c45cb..61d03cac035c 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 @@ -18,6 +18,7 @@ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo import android.os.Binder +import android.os.Handler import android.platform.test.flag.junit.SetFlagsRule import android.testing.AndroidTestingRunner import android.view.Display.DEFAULT_DISPLAY @@ -70,6 +71,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { @Mock lateinit var shellTaskOrganizer: ShellTaskOrganizer @Mock lateinit var transitions: Transitions @Mock lateinit var interactionJankMonitor: InteractionJankMonitor + @Mock lateinit var handler: Handler private lateinit var mockitoSession: StaticMockitoSession private lateinit var desktopTasksLimiter: DesktopTasksLimiter @@ -85,7 +87,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { desktopTasksLimiter = DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT, - interactionJankMonitor, mContext) + interactionJankMonitor, mContext, handler) } @After @@ -97,7 +99,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { fun createDesktopTasksLimiter_withZeroLimit_shouldThrow() { assertFailsWith<IllegalArgumentException> { DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, 0, - interactionJankMonitor, mContext) + interactionJankMonitor, mContext, handler) } } @@ -105,7 +107,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { fun createDesktopTasksLimiter_withNegativeLimit_shouldThrow() { assertFailsWith<IllegalArgumentException> { DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, -5, - interactionJankMonitor, mContext) + interactionJankMonitor, mContext, handler) } } @@ -334,7 +336,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { fun getTaskToMinimizeIfNeeded_tasksAboveLimit_otherLimit_returnsBackTask() { desktopTasksLimiter = DesktopTasksLimiter(transitions, desktopTaskRepo, shellTaskOrganizer, MAX_TASK_LIMIT2, - interactionJankMonitor, mContext) + interactionJankMonitor, mContext, handler) val tasks = (1..MAX_TASK_LIMIT2 + 1).map { setUpFreeformTask() } val minimizedTask = desktopTasksLimiter.getTaskToMinimizeIfNeeded( @@ -375,6 +377,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { verify(interactionJankMonitor).begin( any(), eq(mContext), + eq(handler), eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) desktopTasksLimiter.getTransitionObserver().onTransitionFinished( @@ -403,7 +406,9 @@ class DesktopTasksLimiterTest : ShellTestCase() { verify(interactionJankMonitor).begin( any(), eq(mContext), - eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) + eq(handler), + eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW), + ) desktopTasksLimiter.getTransitionObserver().onTransitionFinished( transition, @@ -432,6 +437,7 @@ class DesktopTasksLimiterTest : ShellTestCase() { verify(interactionJankMonitor).begin( any(), eq(mContext), + eq(handler), eq(CUJ_DESKTOP_MODE_MINIMIZE_WINDOW)) desktopTasksLimiter.getTransitionObserver().onTransitionMerged( diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandlerTest.java index e0463b41ad20..fefa933c5208 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandlerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/ExitDesktopTaskTransitionHandlerTest.java @@ -34,6 +34,7 @@ import android.app.WindowConfiguration; import android.content.Context; import android.content.res.Resources; import android.graphics.Point; +import android.os.Handler; import android.os.IBinder; import android.util.DisplayMetrics; import android.view.SurfaceControl; @@ -81,6 +82,8 @@ public class ExitDesktopTaskTransitionHandlerTest extends ShellTestCase { Transitions.TransitionFinishCallback mTransitionFinishCallback; @Mock ShellExecutor mExecutor; + @Mock + Handler mHandler; private Point mPoint; private ExitDesktopTaskTransitionHandler mExitDesktopTaskTransitionHandler; @@ -97,7 +100,7 @@ public class ExitDesktopTaskTransitionHandlerTest extends ShellTestCase { .thenReturn(getContext().getResources().getDisplayMetrics()); mExitDesktopTaskTransitionHandler = new ExitDesktopTaskTransitionHandler(mTransitions, - mContext, mInteractionJankMonitor); + mContext, mInteractionJankMonitor, mHandler); mPoint = new Point(0, 0); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java index 9c7f7237871a..9146906b6385 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java @@ -37,6 +37,7 @@ import static org.mockito.Mockito.when; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; +import android.os.Handler; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.Display; @@ -100,6 +101,8 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { OneHandedSettingsUtil mMockSettingsUitl; @Mock InteractionJankMonitor mJankMonitor; + @Mock + Handler mMockHandler; List<DisplayAreaAppearedInfo> mDisplayAreaAppearedInfoList = new ArrayList<>(); @@ -142,7 +145,8 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { mMockAnimationController, mTutorialHandler, mJankMonitor, - mMockShellMainExecutor)); + mMockShellMainExecutor, + mMockHandler)); for (int i = 0; i < DISPLAYAREA_INFO_COUNT; i++) { mDisplayAreaAppearedInfoList.add(getDummyDisplayAreaInfo()); @@ -429,7 +433,8 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { mMockAnimationController, mTutorialHandler, mJankMonitor, - mMockShellMainExecutor)); + mMockShellMainExecutor, + mMockHandler)); assertThat(testSpiedDisplayAreaOrganizer.isReady()).isFalse(); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java index f3944d5ac352..96003515a485 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java @@ -40,6 +40,7 @@ import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; import android.os.Bundle; +import android.os.Handler; import android.os.RemoteException; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -115,6 +116,7 @@ public class PipControllerTest extends ShellTestCase { @Mock private PipParamsChangedForwarder mMockPipParamsChangedForwarder; @Mock private DisplayInsetsController mMockDisplayInsetsController; @Mock private TabletopModeController mMockTabletopModeController; + @Mock private Handler mMockHandler; @Mock private DisplayLayout mMockDisplayLayout1; @Mock private DisplayLayout mMockDisplayLayout2; @@ -138,7 +140,7 @@ public class PipControllerTest extends ShellTestCase { mMockPipTransitionController, mMockWindowManagerShellWrapper, mMockTaskStackListener, mMockPipParamsChangedForwarder, mMockDisplayInsetsController, mMockTabletopModeController, - mMockOneHandedController, mMockExecutor); + mMockOneHandedController, mMockExecutor, mMockHandler); mShellInit.init(); when(mMockPipBoundsAlgorithm.getSnapAlgorithm()).thenReturn(mMockPipSnapAlgorithm); when(mMockPipTouchHandler.getMotionHelper()).thenReturn(mMockPipMotionHelper); @@ -230,7 +232,7 @@ public class PipControllerTest extends ShellTestCase { mMockPipTransitionController, mMockWindowManagerShellWrapper, mMockTaskStackListener, mMockPipParamsChangedForwarder, mMockDisplayInsetsController, mMockTabletopModeController, - mMockOneHandedController, mMockExecutor)); + mMockOneHandedController, mMockExecutor, mMockHandler)); } @Test 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 new file mode 100644 index 000000000000..769acf7fdfde --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java @@ -0,0 +1,177 @@ +/* + * 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.wm.shell.recents; + +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; + +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.ActivityTaskManager; +import android.app.IApplicationThread; +import android.app.KeyguardManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.platform.test.flag.junit.SetFlagsRule; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.dx.mockito.inline.extended.ExtendedMockito; +import com.android.dx.mockito.inline.extended.StaticMockitoSession; +import com.android.wm.shell.ShellTaskOrganizer; +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.shared.desktopmode.DesktopModeStatus; +import com.android.wm.shell.sysui.ShellCommandHandler; +import com.android.wm.shell.sysui.ShellController; +import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.transition.HomeTransitionObserver; +import com.android.wm.shell.transition.Transitions; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.quality.Strictness; + +import java.util.Optional; + +/** + * Tests for {@link RecentTasksController} + * + * Usage: atest WMShellUnitTests:RecentsTransitionHandlerTest + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +public class RecentsTransitionHandlerTest extends ShellTestCase { + + @Mock + private Context mContext; + @Mock + private TaskStackListenerImpl mTaskStackListener; + @Mock + private ShellCommandHandler mShellCommandHandler; + @Mock + private DesktopModeTaskRepository mDesktopModeTaskRepository; + @Mock + private ActivityTaskManager mActivityTaskManager; + @Mock + private DisplayInsetsController mDisplayInsetsController; + @Mock + private IRecentTasksListener mRecentTasksListener; + @Mock + private TaskStackTransitionObserver mTaskStackTransitionObserver; + + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + + private ShellTaskOrganizer mShellTaskOrganizer; + private RecentTasksController mRecentTasksController; + private RecentTasksController mRecentTasksControllerReal; + private RecentsTransitionHandler mRecentsTransitionHandler; + private ShellInit mShellInit; + private ShellController mShellController; + private TestShellExecutor mMainExecutor; + private static StaticMockitoSession sMockitoSession; + + @Before + public void setUp() { + sMockitoSession = mockitoSession().initMocks(this).strictness(Strictness.LENIENT) + .mockStatic(DesktopModeStatus.class).startMocking(); + ExtendedMockito.doReturn(true) + .when(() -> DesktopModeStatus.canEnterDesktopMode(any())); + + mMainExecutor = new TestShellExecutor(); + when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class)); + when(mContext.getSystemService(KeyguardManager.class)) + .thenReturn(mock(KeyguardManager.class)); + mShellInit = spy(new ShellInit(mMainExecutor)); + mShellController = spy(new ShellController(mContext, mShellInit, mShellCommandHandler, + mDisplayInsetsController, mMainExecutor)); + mRecentTasksControllerReal = new RecentTasksController(mContext, mShellInit, + mShellController, mShellCommandHandler, mTaskStackListener, mActivityTaskManager, + Optional.of(mDesktopModeTaskRepository), mTaskStackTransitionObserver, + mMainExecutor); + mRecentTasksController = spy(mRecentTasksControllerReal); + mShellTaskOrganizer = new ShellTaskOrganizer(mShellInit, mShellCommandHandler, + null /* sizeCompatUI */, Optional.empty(), Optional.of(mRecentTasksController), + mMainExecutor); + + final Transitions transitions = mock(Transitions.class); + doReturn(mMainExecutor).when(transitions).getMainExecutor(); + mRecentsTransitionHandler = new RecentsTransitionHandler(mShellInit, mShellTaskOrganizer, + transitions, mRecentTasksController, mock(HomeTransitionObserver.class)); + + mShellInit.init(); + } + + @After + public void tearDown() { + sMockitoSession.finishMocking(); + } + + @Test + public void testStartSyntheticRecentsTransition_callsOnAnimationStart() throws Exception { + final IRecentsAnimationRunner runner = mock(IRecentsAnimationRunner.class); + doReturn(new Binder()).when(runner).asBinder(); + Bundle options = new Bundle(); + options.putBoolean("is_synthetic_recents_transition", true); + IBinder transition = mRecentsTransitionHandler.startRecentsTransition( + mock(PendingIntent.class), new Intent(), options, mock(IApplicationThread.class), + runner); + verify(runner).onAnimationStart(any(), any(), any(), any(), any(), any()); + + // Finish and verify no transition remains + mRecentsTransitionHandler.findController(transition).finish(true /* toHome */, + false /* sendUserLeaveHint */, null /* finishCb */); + mMainExecutor.flushAll(); + assertNull(mRecentsTransitionHandler.findController(transition)); + } + + @Test + public void testStartSyntheticRecentsTransition_callsOnAnimationCancel() throws Exception { + final IRecentsAnimationRunner runner = mock(IRecentsAnimationRunner.class); + doReturn(new Binder()).when(runner).asBinder(); + Bundle options = new Bundle(); + options.putBoolean("is_synthetic_recents_transition", true); + IBinder transition = mRecentsTransitionHandler.startRecentsTransition( + mock(PendingIntent.class), new Intent(), options, mock(IApplicationThread.class), + runner); + verify(runner).onAnimationStart(any(), any(), any(), any(), any(), any()); + + mRecentsTransitionHandler.findController(transition).cancel("test"); + mMainExecutor.flushAll(); + verify(runner).onAnimationCanceled(any(), any()); + assertNull(mRecentsTransitionHandler.findController(transition)); + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java index 7937a843b90a..fec9e3ebd1ef 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java @@ -557,7 +557,7 @@ public class ShellTransitionTests extends ShellTestCase { mMainExecutor.flushAll(); // Takeover shouldn't happen when the flag is disabled. - setFlagsRule.disableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY); + setFlagsRule.disableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED); IBinder transitToken = new Binder(); transitions.requestStartTransition(transitToken, new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */)); @@ -572,7 +572,7 @@ public class ShellTransitionTests extends ShellTestCase { verify(mOrganizer, times(1)).finishTransition(eq(transitToken), any()); // Takeover should happen when the flag is enabled. - setFlagsRule.enableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY); + setFlagsRule.enableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED); transitions.requestStartTransition(transitToken, new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */)); info = new TransitionInfoBuilder(TRANSIT_OPEN) @@ -1211,7 +1211,7 @@ public class ShellTransitionTests extends ShellTestCase { mTransactionPool, createTestDisplayController(), mMainExecutor, mMainHandler, mAnimExecutor, mock(HomeTransitionObserver.class)); final RecentsTransitionHandler recentsHandler = - new RecentsTransitionHandler(shellInit, transitions, + new RecentsTransitionHandler(shellInit, mock(ShellTaskOrganizer.class), transitions, mock(RecentTasksController.class), mock(HomeTransitionObserver.class)); transitions.replaceDefaultHandlerForTest(mDefaultHandler); shellInit.init(); 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 a18fbf0891ef..85bc7cc287e6 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 @@ -247,7 +247,18 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { whenever(mockDisplayController.getDisplayLayout(any())).thenReturn(mockDisplayLayout) whenever(mockDisplayLayout.stableInsets()).thenReturn(STABLE_INSETS) whenever(mockInputMonitorFactory.create(any(), any())).thenReturn(mockInputMonitor) - whenever(mockTaskPositionerFactory.create(any(), any(), any(), any(), any(), any(), any())) + whenever( + mockTaskPositionerFactory.create( + any(), + any(), + any(), + any(), + any(), + any(), + any(), + any() + ) + ) .thenReturn(mockTaskPositioner) doReturn(mockToast).`when` { Toast.makeText(any(), anyInt(), anyInt()) } 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 92199a11e837..dff42dae16a2 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 @@ -839,7 +839,6 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { } private void verifyHandleMenuCreated(@Nullable Uri uri) { - verify(mMockHandleMenuFactory).create(any(), any(), anyInt(), any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean(), eq(uri), anyInt(), anyInt(), anyInt()); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt index 7784af6b1111..ab41d9c80177 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt @@ -21,6 +21,7 @@ import android.content.Context import android.content.res.Resources import android.graphics.Point import android.graphics.Rect +import android.os.Handler import android.os.IBinder import android.testing.AndroidTestingRunner import android.view.Display @@ -107,6 +108,8 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() { private lateinit var mockResources: Resources @Mock private lateinit var mockInteractionJankMonitor: InteractionJankMonitor + @Mock + private lateinit var mockHandler: Handler private lateinit var taskPositioner: VeiledResizeTaskPositioner @@ -155,7 +158,8 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() { mockDragStartListener, mockTransactionFactory, mockTransitions, - mockInteractionJankMonitor + mockInteractionJankMonitor, + mockHandler, ) } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/DefaultWindowDecorViewHostTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/DefaultWindowDecorViewHostTest.kt index 1b2ce9e4df36..1b0b7d95e657 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/DefaultWindowDecorViewHostTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/DefaultWindowDecorViewHostTest.kt @@ -18,7 +18,6 @@ package com.android.wm.shell.windowdecor.viewhost import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.SurfaceControl -import android.view.SurfaceControlViewHost import android.view.View import android.view.WindowManager import androidx.test.filters.SmallTest @@ -28,7 +27,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest -import org.junit.Assert.assertThrows import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.mock @@ -59,54 +57,8 @@ class DefaultWindowDecorViewHostTest : ShellTestCase() { onDrawTransaction = null ) - assertThat(windowDecorViewHost.viewHost).isNotNull() - assertThat(windowDecorViewHost.viewHost!!.view).isEqualTo(view) - } - - @Test - fun updateView_alreadyLaidOut_relayouts() = runTest { - val windowDecorViewHost = createDefaultViewHost() - val view = View(context) - windowDecorViewHost.updateView( - view = view, - attrs = WindowManager.LayoutParams(100, 100), - configuration = context.resources.configuration, - onDrawTransaction = null - ) - - val otherParams = WindowManager.LayoutParams(200, 200) - windowDecorViewHost.updateView( - view = view, - attrs = otherParams, - configuration = context.resources.configuration, - onDrawTransaction = null - ) - - assertThat(windowDecorViewHost.viewHost!!.view).isEqualTo(view) - assertThat(windowDecorViewHost.viewHost!!.view!!.layoutParams.width) - .isEqualTo(otherParams.width) - } - - @Test - fun updateView_replacingView_throws() = runTest { - val windowDecorViewHost = createDefaultViewHost() - val view = View(context) - windowDecorViewHost.updateView( - view = view, - attrs = WindowManager.LayoutParams(100, 100), - configuration = context.resources.configuration, - onDrawTransaction = null - ) - - val otherView = View(context) - assertThrows(Exception::class.java) { - windowDecorViewHost.updateView( - view = otherView, - attrs = WindowManager.LayoutParams(100, 100), - configuration = context.resources.configuration, - onDrawTransaction = null - ) - } + assertThat(windowDecorViewHost.viewHostAdapter.isInitialized()).isTrue() + assertThat(windowDecorViewHost.view()).isEqualTo(view) } @OptIn(ExperimentalCoroutinesApi::class) @@ -125,7 +77,7 @@ class DefaultWindowDecorViewHostTest : ShellTestCase() { ) // No view host yet, since the coroutine hasn't run. - assertThat(windowDecorViewHost.viewHost).isNull() + assertThat(windowDecorViewHost.viewHostAdapter.isInitialized()).isFalse() windowDecorViewHost.updateView( view = syncView, @@ -137,14 +89,13 @@ class DefaultWindowDecorViewHostTest : ShellTestCase() { // Would run coroutine if it hadn't been cancelled. advanceUntilIdle() - assertThat(windowDecorViewHost.viewHost).isNotNull() - assertThat(windowDecorViewHost.viewHost!!.view).isNotNull() + assertThat(windowDecorViewHost.viewHostAdapter.isInitialized()).isTrue() + assertThat(windowDecorViewHost.view()).isNotNull() // View host view/attrs should match the ones from the sync call, plus, since the // sync/async were made with different views, if the job hadn't been cancelled there // would've been an exception thrown as replacing views isn't allowed. - assertThat(windowDecorViewHost.viewHost!!.view).isEqualTo(syncView) - assertThat(windowDecorViewHost.viewHost!!.view!!.layoutParams.width) - .isEqualTo(syncAttrs.width) + assertThat(windowDecorViewHost.view()).isEqualTo(syncView) + assertThat(windowDecorViewHost.view()!!.layoutParams.width).isEqualTo(syncAttrs.width) } @OptIn(ExperimentalCoroutinesApi::class) @@ -160,11 +111,11 @@ class DefaultWindowDecorViewHostTest : ShellTestCase() { configuration = context.resources.configuration, ) - assertThat(windowDecorViewHost.viewHost).isNull() + assertThat(windowDecorViewHost.viewHostAdapter.isInitialized()).isFalse() advanceUntilIdle() - assertThat(windowDecorViewHost.viewHost).isNotNull() + assertThat(windowDecorViewHost.viewHostAdapter.isInitialized()).isTrue() } @OptIn(ExperimentalCoroutinesApi::class) @@ -187,9 +138,8 @@ class DefaultWindowDecorViewHostTest : ShellTestCase() { advanceUntilIdle() - assertThat(windowDecorViewHost.viewHost).isNotNull() - assertThat(windowDecorViewHost.viewHost!!.view).isNotNull() - assertThat(windowDecorViewHost.viewHost!!.view).isEqualTo(otherView) + assertThat(windowDecorViewHost.viewHostAdapter.isInitialized()).isTrue() + assertThat(windowDecorViewHost.view()).isEqualTo(otherView) } @Test @@ -207,16 +157,15 @@ class DefaultWindowDecorViewHostTest : ShellTestCase() { val t = mock(SurfaceControl.Transaction::class.java) windowDecorViewHost.release(t) - verify(windowDecorViewHost.viewHost!!).release() - verify(t).remove(windowDecorViewHost.surfaceControl) + verify(windowDecorViewHost.viewHostAdapter).release(t) } private fun CoroutineScope.createDefaultViewHost() = DefaultWindowDecorViewHost( context = context, mainScope = this, display = context.display, - surfaceControlViewHostFactory = { c, d, wwm, s -> - spy(SurfaceControlViewHost(c, d, wwm, s)) - } + viewHostAdapter = spy(SurfaceControlViewHostAdapter(context, context.display)), ) + + private fun DefaultWindowDecorViewHost.view(): View? = viewHostAdapter.viewHost?.view }
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/PooledWindowDecorViewHostSupplierTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/PooledWindowDecorViewHostSupplierTest.kt new file mode 100644 index 000000000000..a7e4213ad01d --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/PooledWindowDecorViewHostSupplierTest.kt @@ -0,0 +1,181 @@ +/* + * 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.windowdecor.viewhost + +import android.testing.AndroidTestingRunner +import android.view.SurfaceControl +import androidx.test.filters.SmallTest +import com.android.wm.shell.ShellTestCase +import com.android.wm.shell.TestShellExecutor +import com.android.wm.shell.sysui.ShellInit +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.MockitoAnnotations +import org.mockito.kotlin.any +import org.mockito.kotlin.mock +import org.mockito.kotlin.never +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +/** + * Tests for [PooledWindowDecorViewHostSupplier]. + * + * Build/Install/Run: + * atest WMShellUnitTests:PooledWindowDecorViewHostSupplierTest + */ +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(AndroidTestingRunner::class) +class PooledWindowDecorViewHostSupplierTest : ShellTestCase() { + + private val testExecutor = TestShellExecutor() + private val testShellInit = ShellInit(testExecutor) + @Mock + private lateinit var mockViewHostFactory: ReusableWindowDecorViewHost.Factory + + private lateinit var supplier: PooledWindowDecorViewHostSupplier + + @Test + fun setUp() { + MockitoAnnotations.initMocks(this) + } + + @Test + fun onInit_warmsAndPoolsViewHosts() = runTest { + supplier = createSupplier(maxPoolSize = 5, preWarmSize = 2) + val mockViewHost1 = mock<ReusableWindowDecorViewHost>() + val mockViewHost2 = mock<ReusableWindowDecorViewHost>() + whenever(mockViewHostFactory + .create(context, this, context.display, id = 0)) + .thenReturn(mockViewHost1) + whenever(mockViewHostFactory + .create(context, this, context.display, id = 1)) + .thenReturn(mockViewHost2) + + testExecutor.flushAll() + advanceUntilIdle() + + // Both were warmed up. + verify(mockViewHost1).warmUp() + verify(mockViewHost2).warmUp() + // Both were released, so re-acquiring them provides the same instance. + assertThat(mockViewHost2) + .isEqualTo(supplier.acquire(context, context.display)) + assertThat(mockViewHost1) + .isEqualTo(supplier.acquire(context, context.display)) + } + + @Test(expected = Throwable::class) + fun onInit_warmUpSizeExceedsPoolSize_throws() = runTest { + createSupplier(maxPoolSize = 3, preWarmSize = 4) + } + + @Test + fun acquire_poolHasInstances_reuses() = runTest { + supplier = createSupplier(maxPoolSize = 5, preWarmSize = 0) + + // Prepare the pool with one instance. + val mockViewHost = mock<ReusableWindowDecorViewHost>() + supplier.release(mockViewHost, SurfaceControl.Transaction()) + + assertThat(mockViewHost) + .isEqualTo(supplier.acquire(context, context.display)) + verify(mockViewHostFactory, never()).create(any(), any(), any(), any()) + } + + @Test + fun acquire_pooledHasZeroInstances_creates() = runTest { + supplier = createSupplier(maxPoolSize = 5, preWarmSize = 0) + + supplier.acquire(context, context.display) + + verify(mockViewHostFactory).create(context, this, context.display, id = 0) + } + + @Test + fun release_poolBelowLimit_caches() = runTest { + supplier = createSupplier(maxPoolSize = 5, preWarmSize = 0) + + val mockViewHost = mock<ReusableWindowDecorViewHost>() + val mockT = mock<SurfaceControl.Transaction>() + supplier.release(mockViewHost, mockT) + + assertThat(mockViewHost) + .isEqualTo(supplier.acquire(context, context.display)) + } + + @Test + fun release_poolBelowLimit_doesNotReleaseViewHost() = runTest { + supplier = createSupplier(maxPoolSize = 5, preWarmSize = 0) + + val mockViewHost = mock<ReusableWindowDecorViewHost>() + val mockT = mock<SurfaceControl.Transaction>() + supplier.release(mockViewHost, mockT) + + verify(mockViewHost, never()).release(mockT) + } + + @Test + fun release_poolAtLimit_doesNotCache() = runTest { + supplier = createSupplier(maxPoolSize = 1, preWarmSize = 0) + val mockT = mock<SurfaceControl.Transaction>() + val mockViewHost = mock<ReusableWindowDecorViewHost>() + supplier.release(mockViewHost, mockT) // Maxes pool. + + val mockViewHost2 = mock<ReusableWindowDecorViewHost>() + supplier.release(mockViewHost2, mockT) // Beyond limit. + + assertThat(mockViewHost) + .isEqualTo(supplier.acquire(context, context.display)) + // Second one wasn't cached, so the acquired one should've been a new instance. + assertThat(mockViewHost2) + .isNotEqualTo(supplier.acquire(context, context.display)) + } + + @Test + fun release_poolAtLimit_releasesViewHost() = runTest { + supplier = createSupplier(maxPoolSize = 1, preWarmSize = 0) + val mockT = mock<SurfaceControl.Transaction>() + val mockViewHost = mock<ReusableWindowDecorViewHost>() + supplier.release(mockViewHost, mockT) // Maxes pool. + + val mockViewHost2 = mock<ReusableWindowDecorViewHost>() + supplier.release(mockViewHost2, mockT) // Beyond limit. + + // Second one doesn't fit, so it needs to be released. + verify(mockViewHost2).release(mockT) + } + + private fun CoroutineScope.createSupplier( + maxPoolSize: Int, + preWarmSize: Int + ) = PooledWindowDecorViewHostSupplier( + context, + this, + testShellInit, + mockViewHostFactory, + maxPoolSize, + preWarmSize + ).also { + testShellInit.init() + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/ReusableWindowDecorViewHostTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/ReusableWindowDecorViewHostTest.kt new file mode 100644 index 000000000000..de2444e34ca9 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/ReusableWindowDecorViewHostTest.kt @@ -0,0 +1,182 @@ +/* + * 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.windowdecor.viewhost + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.view.SurfaceControl +import android.view.View +import android.view.WindowManager +import androidx.test.filters.SmallTest +import com.android.wm.shell.ShellTestCase +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.mock +import org.mockito.kotlin.spy +import org.mockito.kotlin.verify + +/** + * Tests for [ReusableWindowDecorViewHost]. + * + * Build/Install/Run: + * atest WMShellUnitTests:ReusableWindowDecorViewHostTest + */ +@SmallTest +@TestableLooper.RunWithLooper +@RunWith(AndroidTestingRunner::class) +class ReusableWindowDecorViewHostTest : ShellTestCase() { + + @Test + fun warmUp_addsRootView() = runTest { + val reusableVH = createReusableViewHost().apply { + warmUp() + } + + assertThat(reusableVH.viewHostAdapter.isInitialized()).isTrue() + assertThat(reusableVH.view()).isEqualTo(reusableVH.rootView) + } + + @Test + fun update_differentView_replacesView() = runTest { + val view = View(context) + val lp = WindowManager.LayoutParams() + val reusableVH = createReusableViewHost() + reusableVH.updateView(view, lp, context.resources.configuration, null) + + assertThat(reusableVH.rootView.childCount).isEqualTo(1) + assertThat(reusableVH.rootView.getChildAt(0)).isEqualTo(view) + + val newView = View(context) + val newLp = WindowManager.LayoutParams() + reusableVH.updateView(newView, newLp, context.resources.configuration, null) + + assertThat(reusableVH.rootView.childCount).isEqualTo(1) + assertThat(reusableVH.rootView.getChildAt(0)).isEqualTo(newView) + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun updateView_clearsPendingAsyncJob() = runTest { + val reusableVH = createReusableViewHost() + val asyncView = View(context) + val syncView = View(context) + val asyncAttrs = WindowManager.LayoutParams(100, 100) + val syncAttrs = WindowManager.LayoutParams(200, 200) + + reusableVH.updateViewAsync( + view = asyncView, + attrs = asyncAttrs, + configuration = context.resources.configuration, + ) + + // No view host yet, since the coroutine hasn't run. + assertThat(reusableVH.viewHostAdapter.isInitialized()).isFalse() + + reusableVH.updateView( + view = syncView, + attrs = syncAttrs, + configuration = context.resources.configuration, + onDrawTransaction = null + ) + + // Would run coroutine if it hadn't been cancelled. + advanceUntilIdle() + + assertThat(reusableVH.viewHostAdapter.isInitialized()).isTrue() + // View host view/attrs should match the ones from the sync call, plus, since the + // sync/async were made with different views, if the job hadn't been cancelled there + // would've been an exception thrown as replacing views isn't allowed. + assertThat(reusableVH.rootView.getChildAt(0)).isEqualTo(syncView) + assertThat(reusableVH.view()!!.layoutParams.width).isEqualTo(syncAttrs.width) + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun updateViewAsync() = runTest { + val reusableVH = createReusableViewHost() + val view = View(context) + val attrs = WindowManager.LayoutParams(100, 100) + + reusableVH.updateViewAsync( + view = view, + attrs = attrs, + configuration = context.resources.configuration, + ) + + assertThat(reusableVH.viewHostAdapter.isInitialized()).isFalse() + + advanceUntilIdle() + + assertThat(reusableVH.viewHostAdapter.isInitialized()).isTrue() + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun updateViewAsync_clearsPendingAsyncJob() = runTest { + val reusableVH = createReusableViewHost() + + val view = View(context) + reusableVH.updateViewAsync( + view = view, + attrs = WindowManager.LayoutParams(100, 100), + configuration = context.resources.configuration, + ) + val otherView = View(context) + reusableVH.updateViewAsync( + view = otherView, + attrs = WindowManager.LayoutParams(100, 100), + configuration = context.resources.configuration, + ) + + advanceUntilIdle() + + assertThat(reusableVH.viewHostAdapter.isInitialized()).isTrue() + assertThat(reusableVH.rootView.getChildAt(0)).isEqualTo(otherView) + } + + @Test + fun release() = runTest { + val reusableVH = createReusableViewHost() + + val view = View(context) + reusableVH.updateView( + view = view, + attrs = WindowManager.LayoutParams(100, 100), + configuration = context.resources.configuration, + onDrawTransaction = null + ) + + val t = mock(SurfaceControl.Transaction::class.java) + reusableVH.release(t) + + verify(reusableVH.viewHostAdapter).release(t) + } + + private fun CoroutineScope.createReusableViewHost() = ReusableWindowDecorViewHost( + context = context, + mainScope = this, + display = context.display, + id = 1, + viewHostAdapter = spy(SurfaceControlViewHostAdapter(context, context.display)), + ) + + private fun ReusableWindowDecorViewHost.view(): View? = viewHostAdapter.viewHost?.view +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/SurfaceControlViewHostAdapterTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/SurfaceControlViewHostAdapterTest.kt new file mode 100644 index 000000000000..d6c80a7fffc1 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/viewhost/SurfaceControlViewHostAdapterTest.kt @@ -0,0 +1,144 @@ +/* + * 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.windowdecor.viewhost + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.view.SurfaceControl +import android.view.SurfaceControlViewHost +import android.view.View +import android.view.WindowManager +import androidx.test.filters.SmallTest +import com.android.wm.shell.ShellTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.Assert.assertThrows +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.mock +import org.mockito.kotlin.spy +import org.mockito.kotlin.verify + +/** + * Tests for [SurfaceControlViewHostAdapter]. + * + * Build/Install/Run: + * atest WMShellUnitTests:SurfaceControlViewHostAdapterTest + */ +@SmallTest +@TestableLooper.RunWithLooper +@RunWith(AndroidTestingRunner::class) +class SurfaceControlViewHostAdapterTest : ShellTestCase() { + + private lateinit var adapter: SurfaceControlViewHostAdapter + + @Before + fun setUp() { + adapter = SurfaceControlViewHostAdapter( + context, + context.display, + surfaceControlViewHostFactory = { c, d, wwm, s -> + spy(SurfaceControlViewHost(c, d, wwm, s)) + } + ) + } + + @Test + fun prepareViewHost() { + adapter.prepareViewHost(context.resources.configuration) + + assertThat(adapter.viewHost).isNotNull() + } + + @Test + fun prepareViewHost_alreadyCreated_skips() { + adapter.prepareViewHost(context.resources.configuration) + + val viewHost = adapter.viewHost!! + + adapter.prepareViewHost(context.resources.configuration) + + assertThat(adapter.viewHost).isEqualTo(viewHost) + } + + @Test + fun updateView_layoutInViewHost() { + val view = View(context) + adapter.prepareViewHost(context.resources.configuration) + + adapter.updateView( + view = view, + attrs = WindowManager.LayoutParams(100, 100) + ) + + assertThat(adapter.isInitialized()).isTrue() + assertThat(adapter.view()).isEqualTo(view) + } + + @Test + fun updateView_alreadyLaidOut_relayouts() { + val view = View(context) + adapter.prepareViewHost(context.resources.configuration) + adapter.updateView( + view = view, + attrs = WindowManager.LayoutParams(100, 100) + ) + + val otherParams = WindowManager.LayoutParams(200, 200) + adapter.updateView( + view = view, + attrs = otherParams + ) + + assertThat(adapter.view()).isEqualTo(view) + assertThat(adapter.view()!!.layoutParams.width).isEqualTo(otherParams.width) + } + + @Test + fun updateView_replacingView_throws() { + val view = View(context) + adapter.prepareViewHost(context.resources.configuration) + adapter.updateView( + view = view, + attrs = WindowManager.LayoutParams(100, 100) + ) + + val otherView = View(context) + assertThrows(Exception::class.java) { + adapter.updateView( + view = otherView, + attrs = WindowManager.LayoutParams(100, 100) + ) + } + } + + @Test + fun release() { + adapter.prepareViewHost(context.resources.configuration) + adapter.updateView( + view = View(context), + attrs = WindowManager.LayoutParams(100, 100) + ) + + val mockT = mock(SurfaceControl.Transaction::class.java) + adapter.release(mockT) + + verify(adapter.viewHost!!).release() + verify(mockT).remove(adapter.rootSurface) + } + + private fun SurfaceControlViewHostAdapter.view(): View? = viewHost?.view +} diff --git a/libs/hwui/aconfig/hwui_flags.aconfig b/libs/hwui/aconfig/hwui_flags.aconfig index faea6d42b156..ab052b902e02 100644 --- a/libs/hwui/aconfig/hwui_flags.aconfig +++ b/libs/hwui/aconfig/hwui_flags.aconfig @@ -121,3 +121,11 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "iso_gainmap_apis" + is_exported: true + namespace: "core_graphics" + description: "APIs that expose gainmap metadata corresponding to those defined in ISO 21496-1" + bug: "349357636" +} diff --git a/libs/hwui/hwui/DrawTextFunctor.h b/libs/hwui/hwui/DrawTextFunctor.h index d7bf20130b71..e13e136550ca 100644 --- a/libs/hwui/hwui/DrawTextFunctor.h +++ b/libs/hwui/hwui/DrawTextFunctor.h @@ -73,6 +73,7 @@ static void simplifyPaint(int color, Paint* paint) { } paint->setStrokeJoin(SkPaint::kRound_Join); paint->setLooper(nullptr); + paint->setBlendMode(SkBlendMode::kSrcOver); } class DrawTextFunctor { diff --git a/libs/hwui/jni/Gainmap.cpp b/libs/hwui/jni/Gainmap.cpp index 0fffee744be0..71972d01b94f 100644 --- a/libs/hwui/jni/Gainmap.cpp +++ b/libs/hwui/jni/Gainmap.cpp @@ -16,6 +16,9 @@ #include <Gainmap.h> +#include "SkColorType.h" +#include "SkGainmapInfo.h" + #ifdef __ANDROID__ #include <binder/Parcel.h> #endif @@ -36,6 +39,28 @@ static Gainmap* fromJava(jlong gainmap) { return reinterpret_cast<Gainmap*>(gainmap); } +static SkGainmapInfo::BaseImageType baseImageTypeFromJava(jint direction) { + switch (direction) { + case 0: + return SkGainmapInfo::BaseImageType::kSDR; + case 1: + return SkGainmapInfo::BaseImageType::kHDR; + default: + LOG_ALWAYS_FATAL("Unrecognized Gainmap direction: %d", direction); + } +} + +static jint baseImageTypeToJava(SkGainmapInfo::BaseImageType type) { + switch (type) { + case SkGainmapInfo::BaseImageType::kSDR: + return 0; + case SkGainmapInfo::BaseImageType::kHDR: + return 1; + default: + LOG_ALWAYS_FATAL("Unrecognized base image: %d", type); + } +} + static int getCreateFlags(const sk_sp<Bitmap>& bitmap) { int flags = 0; if (bitmap->info().alphaType() == kPremul_SkAlphaType) { @@ -169,6 +194,36 @@ static jfloat Gainmap_getDisplayRatioSdr(JNIEnv*, jobject, jlong gainmapPtr) { return fromJava(gainmapPtr)->info.fDisplayRatioSdr; } +static void Gainmap_setAlternativeColorSpace(JNIEnv*, jobject, jlong gainmapPtr, + jlong colorSpacePtr) { + auto colorSpace = GraphicsJNI::getNativeColorSpace(colorSpacePtr); + fromJava(gainmapPtr)->info.fGainmapMathColorSpace = colorSpace; +} + +static jobject Gainmap_getAlternativeColorSpace(JNIEnv* env, jobject, jlong gainmapPtr) { + const auto javaGainmap = fromJava(gainmapPtr); + auto colorSpace = javaGainmap->info.fGainmapMathColorSpace.get(); + if (colorSpace == nullptr) { + return nullptr; + } + + auto colorType = javaGainmap->bitmap->colorType(); + // A8 bitmaps don't support colorspaces, but an alternative colorspace is + // still valid for configuring the gainmap math, so use RGBA8888 instead. + if (colorType == kAlpha_8_SkColorType) { + colorType = kRGBA_8888_SkColorType; + } + return GraphicsJNI::getColorSpace(env, colorSpace, colorType); +} + +static void Gainmap_setDirection(JNIEnv*, jobject, jlong gainmapPtr, jint direction) { + fromJava(gainmapPtr)->info.fBaseImageType = baseImageTypeFromJava(direction); +} + +static jint Gainmap_getDirection(JNIEnv* env, jobject, jlong gainmapPtr) { + return baseImageTypeToJava(fromJava(gainmapPtr)->info.fBaseImageType); +} + // ---------------------------------------------------------------------------- // Serialization // ---------------------------------------------------------------------------- @@ -260,6 +315,11 @@ static const JNINativeMethod gGainmapMethods[] = { {"nGetDisplayRatioHdr", "(J)F", (void*)Gainmap_getDisplayRatioHdr}, {"nSetDisplayRatioSdr", "(JF)V", (void*)Gainmap_setDisplayRatioSdr}, {"nGetDisplayRatioSdr", "(J)F", (void*)Gainmap_getDisplayRatioSdr}, + {"nSetAlternativeColorSpace", "(JJ)V", (void*)Gainmap_setAlternativeColorSpace}, + {"nGetAlternativeColorSpace", "(J)Landroid/graphics/ColorSpace;", + (void*)Gainmap_getAlternativeColorSpace}, + {"nSetDirection", "(JI)V", (void*)Gainmap_setDirection}, + {"nGetDirection", "(J)I", (void*)Gainmap_getDirection}, {"nWriteGainmapToParcel", "(JLandroid/os/Parcel;)V", (void*)Gainmap_writeToParcel}, {"nReadGainmapFromParcel", "(JLandroid/os/Parcel;)V", (void*)Gainmap_readFromParcel}, }; diff --git a/libs/hwui/platform/host/thread/ThreadBase.h b/libs/hwui/platform/host/thread/ThreadBase.h index d709430cc9b6..b4e7bd34971a 100644 --- a/libs/hwui/platform/host/thread/ThreadBase.h +++ b/libs/hwui/platform/host/thread/ThreadBase.h @@ -48,7 +48,7 @@ protected: nsecs_t nextWakeup = mQueue.nextWakeup(lock); std::chrono::nanoseconds duration = std::chrono::nanoseconds::max(); if (nextWakeup < std::numeric_limits<nsecs_t>::max()) { - int timeout = nextWakeup - WorkQueue::clock::now(); + nsecs_t timeout = nextWakeup - WorkQueue::clock::now(); if (timeout < 0) timeout = 0; duration = std::chrono::nanoseconds(timeout); } diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp index 1afef75bc741..d993b8715260 100644 --- a/libs/input/MouseCursorController.cpp +++ b/libs/input/MouseCursorController.cpp @@ -64,25 +64,6 @@ MouseCursorController::~MouseCursorController() { mLocked.pointerSprite.clear(); } -std::optional<FloatRect> MouseCursorController::getBounds() const { - std::scoped_lock lock(mLock); - - return getBoundsLocked(); -} - -std::optional<FloatRect> MouseCursorController::getBoundsLocked() const REQUIRES(mLock) { - if (!mLocked.viewport.isValid()) { - return {}; - } - - return FloatRect{ - static_cast<float>(mLocked.viewport.logicalLeft), - static_cast<float>(mLocked.viewport.logicalTop), - static_cast<float>(mLocked.viewport.logicalRight - 1), - static_cast<float>(mLocked.viewport.logicalBottom - 1), - }; -} - void MouseCursorController::move(float deltaX, float deltaY) { #if DEBUG_MOUSE_CURSOR_UPDATES ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY); @@ -105,11 +86,20 @@ void MouseCursorController::setPosition(float x, float y) { } void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) { - const auto bounds = getBoundsLocked(); - if (!bounds) return; + const auto& v = mLocked.viewport; + if (!v.isValid()) return; - mLocked.pointerX = std::max(bounds->left, std::min(bounds->right, x)); - mLocked.pointerY = std::max(bounds->top, std::min(bounds->bottom, y)); + // The valid bounds for a mouse cursor. Since the right and bottom edges are considered outside + // the display, clip the bounds by one pixel instead of letting the cursor get arbitrarily + // close to the outside edge. + const FloatRect bounds{ + static_cast<float>(mLocked.viewport.logicalLeft), + static_cast<float>(mLocked.viewport.logicalTop), + static_cast<float>(mLocked.viewport.logicalRight - 1), + static_cast<float>(mLocked.viewport.logicalBottom - 1), + }; + mLocked.pointerX = std::max(bounds.left, std::min(bounds.right, x)); + mLocked.pointerY = std::max(bounds.top, std::min(bounds.bottom, y)); updatePointerLocked(); } @@ -216,9 +206,11 @@ void MouseCursorController::setDisplayViewport(const DisplayViewport& viewport, // Reset cursor position to center if size or display changed. if (oldViewport.displayId != viewport.displayId || oldDisplayWidth != newDisplayWidth || oldDisplayHeight != newDisplayHeight) { - if (const auto bounds = getBoundsLocked(); bounds) { - mLocked.pointerX = (bounds->left + bounds->right) * 0.5f; - mLocked.pointerY = (bounds->top + bounds->bottom) * 0.5f; + if (viewport.isValid()) { + // Use integer coordinates as the starting point for the cursor location. + // We usually expect display sizes to be even numbers, so the flooring is precautionary. + mLocked.pointerX = std::floor((viewport.logicalLeft + viewport.logicalRight) / 2); + mLocked.pointerY = std::floor((viewport.logicalTop + viewport.logicalBottom) / 2); // Reload icon resources for density may be changed. loadResourcesLocked(getAdditionalMouseResources); } else { diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h index 860034141a0b..12b31a8c531a 100644 --- a/libs/input/MouseCursorController.h +++ b/libs/input/MouseCursorController.h @@ -43,7 +43,6 @@ public: MouseCursorController(PointerControllerContext& context); ~MouseCursorController(); - std::optional<FloatRect> getBounds() const; void move(float deltaX, float deltaY); void setPosition(float x, float y); FloatPoint getPosition() const; @@ -104,7 +103,6 @@ private: } mLocked GUARDED_BY(mLock); - std::optional<FloatRect> getBoundsLocked() const; void setPositionLocked(float x, float y); void updatePointerLocked(); diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index 5ae967bc369a..78d7d3a7051b 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -138,10 +138,6 @@ std::mutex& PointerController::getLock() const { return mDisplayInfoListener->mLock; } -std::optional<FloatRect> PointerController::getBounds() const { - return mCursorController.getBounds(); -} - void PointerController::move(float deltaX, float deltaY) { const ui::LogicalDisplayId displayId = mCursorController.getDisplayId(); vec2 transformed; diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index 4d1e1d733cc1..ee8d1211341f 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -51,7 +51,6 @@ public: ~PointerController() override; - std::optional<FloatRect> getBounds() const override; void move(float deltaX, float deltaY) override; void setPosition(float x, float y) override; FloatPoint getPosition() const override; @@ -166,9 +165,6 @@ public: ~TouchPointerController() override; - std::optional<FloatRect> getBounds() const override { - LOG_ALWAYS_FATAL("Should not be called"); - } void move(float, float) override { LOG_ALWAYS_FATAL("Should not be called"); } diff --git a/location/java/android/location/flags/location.aconfig b/location/java/android/location/flags/location.aconfig index dcf5c5b46478..cddc337d95b8 100644 --- a/location/java/android/location/flags/location.aconfig +++ b/location/java/android/location/flags/location.aconfig @@ -111,6 +111,17 @@ flag { } flag { + name: "enable_ni_supl_message_injection_by_carrier_config_bugfix" + namespace: "location" + description: "Flag for enabling NI SUPL message injection by carrier config" + bug: "242105192" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "enable_ni_supl_message_injection_by_carrier_config" namespace: "location" description: "Flag for enabling NI SUPL message injection by carrier config" diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index e2e7a46a0ad0..cdb517b3fd3e 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -6318,7 +6318,14 @@ public class AudioManager { /** * @hide * Get the audio devices that would be used for the routing of the given audio attributes. - * @param attributes the {@link AudioAttributes} for which the routing is being queried + * @param attributes the {@link AudioAttributes} for which the routing is being queried. + * For queries about output devices (playback use cases), a valid usage must be specified in + * the audio attributes via AudioAttributes.Builder.setUsage(). The capture preset MUST NOT + * be changed from default. + * For queries about input devices (capture use case), a valid capture preset MUST be + * specified in the audio attributes via AudioAttributes.Builder.setCapturePreset(). If a + * capture preset is present, then this has precedence over any usage or content type also + * present in the audio attrirutes. * @return an empty list if there was an issue with the request, a list of audio devices * otherwise (typically one device, except for duplicated paths). */ diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java index 3cc0ad27bd9a..31f89960836b 100644 --- a/media/java/android/media/projection/MediaProjection.java +++ b/media/java/android/media/projection/MediaProjection.java @@ -90,24 +90,24 @@ public final class MediaProjection { mDisplayManager = displayManager; } - /** - * Register a listener to receive notifications about when the {@link MediaProjection} or captured - * content changes state. - * - * <p>The callback must be registered before invoking {@link #createVirtualDisplay(String, int, - * int, int, int, Surface, VirtualDisplay.Callback, Handler)} to ensure that any notifications on - * the callback are not missed. The client must implement {@link Callback#onStop()} and clean up - * any resources it is holding, e.g. the {@link VirtualDisplay} and {@link Surface}. This should - * also update any application UI indicating the MediaProjection status as MediaProjection has - * stopped. - * - * @param callback The callback to call. - * @param handler The handler on which the callback should be invoked, or null if the callback - * should be invoked on the calling thread's looper. - * @throws NullPointerException If the given callback is null. - * @see #unregisterCallback - */ - public void registerCallback(@NonNull Callback callback, @Nullable Handler handler) { + /** + * Register a listener to receive notifications about when the {@link MediaProjection} or + * captured content changes state. + * + * <p>The callback must be registered before invoking {@link #createVirtualDisplay(String, int, + * int, int, int, Surface, VirtualDisplay.Callback, Handler)} to ensure that any notifications + * on the callback are not missed. The client must implement {@link Callback#onStop()} to + * properly handle MediaProjection clean up any resources it is holding, e.g. the {@link + * VirtualDisplay} and {@link Surface}. This should also update any application UI indicating + * the MediaProjection status as MediaProjection has stopped. + * + * @param callback The callback to call. + * @param handler The handler on which the callback should be invoked, or null if the callback + * should be invoked on the calling thread's looper. + * @throws NullPointerException If the given callback is null. + * @see #unregisterCallback + */ + public void registerCallback(@NonNull Callback callback, @Nullable Handler handler) { try { final Callback c = Objects.requireNonNull(callback); if (handler == null) { @@ -313,7 +313,7 @@ public final class MediaProjection { */ public abstract static class Callback { /** - * Called when the MediaProjection session is no longer valid. + * Called when the MediaProjection session has been stopped and is no longer valid. * * <p>Once a MediaProjection has been stopped, it's up to the application to release any * resources it may be holding (e.g. releasing the {@link VirtualDisplay} and {@link @@ -321,9 +321,9 @@ public final class MediaProjection { * it should be updated to indicate that MediaProjection is no longer active. * * <p>MediaProjection stopping can be a result of the system stopping the ongoing - * MediaProjection due to various reasons, such as another MediaProjection session starting. - * MediaProjection may also stop due to the user explicitly stopping ongoing MediaProjection - * via any available system-level UI. + * MediaProjection due to various reasons, such as another MediaProjection session starting, + * a user stopping the session via UI affordances in system-level UI, or the screen being + * locked. * * <p>After this callback any call to {@link MediaProjection#createVirtualDisplay} will * fail, even if no such {@link VirtualDisplay} was ever created for this MediaProjection diff --git a/media/java/android/media/projection/MediaProjectionManager.java b/media/java/android/media/projection/MediaProjectionManager.java index 03fd2c67fe46..dc55e41fb74c 100644 --- a/media/java/android/media/projection/MediaProjectionManager.java +++ b/media/java/android/media/projection/MediaProjectionManager.java @@ -60,13 +60,14 @@ import java.util.Map; * <li>Register a {@link MediaProjection.Callback} by calling {@link * MediaProjection#registerCallback(MediaProjection.Callback, Handler)}. This is required to * receive notifications about when the {@link MediaProjection} or captured content changes - * state. When receiving an `onStop()` callback, the client must clean up any resources it is - * holding, e.g. the {@link VirtualDisplay} and {@link Surface}. The MediaProjection may - * further no longer create any new {@link VirtualDisplay}s via {@link - * MediaProjection#createVirtualDisplay(String, int, int, int, int, Surface, - * VirtualDisplay.Callback, Handler)}. Note that the `onStop()` callback can be a result of - * the system stopping MediaProjection due to various reasons or the user stopping the - * MediaProjection via UI affordances in system-level UI. + * state. When receiving an `onStop()` callback the {@link MediaProjection} session has been + * finished and the client must clean up any resources it is holding, e.g. the {@link + * VirtualDisplay} and {@link Surface}. The MediaProjection may further no longer create any + * new {@link VirtualDisplay}s via {@link MediaProjection#createVirtualDisplay(String, int, + * int, int, int, Surface, VirtualDisplay.Callback, Handler)}. Note that the `onStop()` + * callback can be a result of the system stopping MediaProjection due to various reasons. + * This includes the user stopping the MediaProjection via UI affordances in system-level UI, + * the screen being locked, or another {@link MediaProjection} session starting. * <li>Start the screen capture session for media projection by calling {@link * MediaProjection#createVirtualDisplay(String, int, int, int, int, Surface, * android.hardware.display.VirtualDisplay.Callback, Handler)}. diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index 25c063d6ccd8..202535d45191 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -273,6 +273,7 @@ LIBANDROID { ASurfaceTransaction_fromJava; # introduced=34 ASurfaceTransaction_reparent; # introduced=29 ASurfaceTransaction_setBuffer; # introduced=29 + ASurfaceTransaction_setBufferWithRelease; # introduced=36 ASurfaceTransaction_setBufferAlpha; # introduced=29 ASurfaceTransaction_setBufferDataSpace; # introduced=29 ASurfaceTransaction_setBufferTransparency; # introduced=29 diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp index 6ce83cd7b765..e46db6bb3727 100644 --- a/native/android/surface_control.cpp +++ b/native/android/surface_control.cpp @@ -416,6 +416,35 @@ void ASurfaceTransaction_setBuffer(ASurfaceTransaction* aSurfaceTransaction, transaction->setBuffer(surfaceControl, graphic_buffer, fence); } +void ASurfaceTransaction_setBufferWithRelease( + ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl, + AHardwareBuffer* buffer, int acquire_fence_fd, void* _Null_unspecified context, + ASurfaceTransaction_OnBufferRelease aReleaseCallback) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + CHECK_NOT_NULL(aReleaseCallback); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + sp<GraphicBuffer> graphic_buffer(GraphicBuffer::fromAHardwareBuffer(buffer)); + + std::optional<sp<Fence>> fence = std::nullopt; + if (acquire_fence_fd != -1) { + fence = new Fence(acquire_fence_fd); + } + + ReleaseBufferCallback releaseBufferCallback = + [context, + aReleaseCallback](const ReleaseCallbackId&, const sp<Fence>& releaseFence, + std::optional<uint32_t> /* currentMaxAcquiredBufferCount */) { + (*aReleaseCallback)(context, (releaseFence) ? releaseFence->dup() : -1); + }; + + transaction->setBuffer(surfaceControl, graphic_buffer, fence, /* frameNumber */ std::nullopt, + /* producerId */ 0, releaseBufferCallback); +} + void ASurfaceTransaction_setGeometry(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl, const ARect& source, const ARect& destination, int32_t transform) { diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt index bc8a7afd94e9..9603c0a9f7c7 100644 --- a/nfc/api/system-current.txt +++ b/nfc/api/system-current.txt @@ -60,8 +60,13 @@ package android.nfc { method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public java.util.List<java.lang.String> getActiveNfceeList(); 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 registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcOemExtension.Callback); + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void setControllerAlwaysOn(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 unregisterCallback(@NonNull android.nfc.NfcOemExtension.Callback); + field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int DISABLE = 0; // 0x0 + field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int ENABLE_DEFAULT = 1; // 0x1 + field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int ENABLE_EE = 3; // 0x3 + field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int ENABLE_TRANSPARENT = 2; // 0x2 field public static final int HCE_ACTIVATE = 1; // 0x1 field public static final int HCE_DATA_TRANSFERRED = 2; // 0x2 field public static final int HCE_DEACTIVATE = 3; // 0x3 diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl index e2ec95215d1a..246efc7ca557 100644 --- a/nfc/java/android/nfc/INfcAdapter.aidl +++ b/nfc/java/android/nfc/INfcAdapter.aidl @@ -73,7 +73,7 @@ interface INfcAdapter boolean setNfcSecure(boolean enable); NfcAntennaInfo getNfcAntennaInfo(); - boolean setControllerAlwaysOn(boolean value); + void setControllerAlwaysOn(int mode); boolean isControllerAlwaysOn(); boolean isControllerAlwaysOnSupported(); void registerControllerAlwaysOnListener(in INfcControllerAlwaysOnListener listener); diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java index f47879385070..de85f1eeabe3 100644 --- a/nfc/java/android/nfc/NfcAdapter.java +++ b/nfc/java/android/nfc/NfcAdapter.java @@ -559,6 +559,18 @@ public final class NfcAdapter { @Retention(RetentionPolicy.SOURCE) public @interface TagIntentAppPreferenceResult {} + /** + * Mode Type for {@link NfcOemExtension#setControllerAlwaysOn(int)}. + * @hide + */ + public static final int CONTROLLER_ALWAYS_ON_MODE_DEFAULT = 1; + + /** + * Mode Type for {@link NfcOemExtension#setControllerAlwaysOn(int)}. + * @hide + */ + public static final int CONTROLLER_ALWAYS_ON_DISABLE = 0; + // Guarded by sLock static boolean sIsInitialized = false; static boolean sHasNfcFeature; @@ -2330,7 +2342,8 @@ public final class NfcAdapter { * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF, * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE * are unavailable - * @return void + * @return true if feature is supported by the device and operation has bee initiated, + * false if the feature is not supported by the device. * @hide */ @SystemApi @@ -2339,8 +2352,13 @@ public final class NfcAdapter { if (!sHasNfcFeature && !sHasCeFeature) { throw new UnsupportedOperationException(); } - return callServiceReturn(() -> sService.setControllerAlwaysOn(value), false); - + int mode = value ? CONTROLLER_ALWAYS_ON_MODE_DEFAULT : CONTROLLER_ALWAYS_ON_DISABLE; + try { + callService(() -> sService.setControllerAlwaysOn(mode)); + } catch (UnsupportedOperationException e) { + return false; + } + return true; } /** diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java index d51b704a7e7f..45038d41e237 100644 --- a/nfc/java/android/nfc/NfcOemExtension.java +++ b/nfc/java/android/nfc/NfcOemExtension.java @@ -70,6 +70,58 @@ public final class NfcOemExtension { private boolean mRfDiscoveryStarted = false; /** + * Mode Type for {@link #setControllerAlwaysOn(int)}. + * Enables the controller in default mode when NFC is disabled (existing API behavior). + * works same as {@link NfcAdapter#setControllerAlwaysOn(boolean)}. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + public static final int ENABLE_DEFAULT = NfcAdapter.CONTROLLER_ALWAYS_ON_MODE_DEFAULT; + + /** + * Mode Type for {@link #setControllerAlwaysOn(int)}. + * Enables the controller in transparent mode when NFC is disabled. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + public static final int ENABLE_TRANSPARENT = 2; + + /** + * Mode Type for {@link #setControllerAlwaysOn(int)}. + * Enables the controller and initializes and enables the EE subsystem when NFC is disabled. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + public static final int ENABLE_EE = 3; + + /** + * Mode Type for {@link #setControllerAlwaysOn(int)}. + * Disable the Controller Always On Mode. + * works same as {@link NfcAdapter#setControllerAlwaysOn(boolean)}. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + public static final int DISABLE = NfcAdapter.CONTROLLER_ALWAYS_ON_DISABLE; + + /** + * Possible controller modes for {@link #setControllerAlwaysOn(int)}. + * + * @hide + */ + @IntDef(prefix = { "" }, value = { + ENABLE_DEFAULT, + ENABLE_TRANSPARENT, + ENABLE_EE, + DISABLE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ControllerMode{} + + /** * Event that Host Card Emulation is activated. */ public static final int HCE_ACTIVATE = 1; @@ -389,6 +441,32 @@ public final class NfcOemExtension { NfcAdapter.sService.fetchActiveNfceeList(), new ArrayList<String>()); } + /** + * Sets NFC controller always on feature. + * <p>This API is for the NFCC internal state management. It allows to discriminate + * the controller function from the NFC function by keeping the NFC controller on without + * any NFC RF enabled if necessary. + * <p>This call is asynchronous, register listener {@link NfcAdapter.ControllerAlwaysOnListener} + * by {@link NfcAdapter#registerControllerAlwaysOnListener} to find out when the operation is + * complete. + * @param mode one of {@link ControllerMode} modes + * @throws UnsupportedOperationException if + * <li> if FEATURE_NFC, FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF, + * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE + * are unavailable </li> + * <li> if the feature is unavailable @see NfcAdapter#isNfcControllerAlwaysOnSupported() </li> + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) + public void setControllerAlwaysOn(@ControllerMode int mode) { + if (!NfcAdapter.sHasNfcFeature && !NfcAdapter.sHasCeFeature) { + throw new UnsupportedOperationException(); + } + NfcAdapter.callService(() -> NfcAdapter.sService.setControllerAlwaysOn(mode)); + } + private final class NfcOemExtensionCallback extends INfcOemExtensionCallback.Stub { @Override diff --git a/packages/CarrierDefaultApp/res/values-ar/strings.xml b/packages/CarrierDefaultApp/res/values-ar/strings.xml index fe746f24912b..53a27332a2d1 100644 --- a/packages/CarrierDefaultApp/res/values-ar/strings.xml +++ b/packages/CarrierDefaultApp/res/values-ar/strings.xml @@ -8,7 +8,7 @@ <string name="portal_notification_detail" msgid="2295729385924660881">"النقر للانتقال إلى موقع %s الإلكتروني"</string> <string name="no_data_notification_detail" msgid="3112125343857014825">"يُرجى الاتصال بمقدم الخدمة %s"</string> <string name="no_mobile_data_connection_title" msgid="7449525772416200578">"لا يوجد اتصال بيانات الجوال"</string> - <string name="no_mobile_data_connection" msgid="544980465184147010">"إضافة بيانات أو خطة تجوال خلال %s"</string> + <string name="no_mobile_data_connection" msgid="544980465184147010">"إضافة بيانات أو خطة تجوال خلال %%s"</string> <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"حالة بيانات الجوّال"</string> <string name="action_bar_label" msgid="4290345990334377177">"تسجيل الدخول إلى شبكة الجوّال"</string> <string name="ssl_error_warning" msgid="3127935140338254180">"الشبكة التي تحاول الانضمام إليها بها مشاكل أمنية."</string> diff --git a/packages/CarrierDefaultApp/res/values-ur/strings.xml b/packages/CarrierDefaultApp/res/values-ur/strings.xml index d6225c2dd16e..20d1300d89a9 100644 --- a/packages/CarrierDefaultApp/res/values-ur/strings.xml +++ b/packages/CarrierDefaultApp/res/values-ur/strings.xml @@ -16,7 +16,7 @@ <string name="ssl_error_continue" msgid="1138548463994095584">"براؤزر کے ذریعے بہرحال جاری رکھیں"</string> <string name="performance_boost_notification_channel" msgid="3475440855635538592">"پرفارمینس بوسٹ"</string> <string name="performance_boost_notification_title" msgid="3126203390685781861">"آپ کے کیریئر سے 5G کے اختیارات"</string> - <string name="performance_boost_notification_detail" msgid="216569851036236346">"اپنی ایپ کے تجربے کے اختیارات دیکھنے کے لیے %s کی ویب سائٹ ملاحظہ کریں"</string> + <string name="performance_boost_notification_detail" msgid="216569851036236346">"اپنی ایپ کے تجربے کے اختیارات دیکھنے کے لیے %%s کی ویب سائٹ ملاحظہ کریں"</string> <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ابھی نہیں"</string> <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"نظم کریں"</string> <string name="slice_purchase_app_label" msgid="7170191659233241166">"پرفارمینس بوسٹ خریدیں۔"</string> diff --git a/packages/CredentialManager/res/values-te/strings.xml b/packages/CredentialManager/res/values-te/strings.xml index 3b98438a568f..77c0d41b6199 100644 --- a/packages/CredentialManager/res/values-te/strings.xml +++ b/packages/CredentialManager/res/values-te/strings.xml @@ -52,7 +52,7 @@ <string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"మరొక పరికరంలో పాస్-కీని క్రియేట్ చేయాలా?"</string> <string name="save_password_on_other_device_title" msgid="5829084591948321207">"మరొక పరికరంలో పాస్వర్డ్ను సేవ్ చేయాలా?"</string> <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"మరో పరికరంలో సైన్-ఇన్ని సేవ్ చేయాలా?"</string> - <string name="use_provider_for_all_title" msgid="4201020195058980757">"మీ అన్ని సైన్-ఇన్ వివరాల కోసం <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>ను ఉపయోగించాలా?"</string> + <string name="use_provider_for_all_title" msgid="4201020195058980757">"మీరు సైన్-ఇన్ చేసే సందర్భాలన్నిటికీ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>ను ఉపయోగించాలా?"</string> <string name="use_provider_for_all_description" msgid="1998772715863958997">"<xliff:g id="USERNAME">%1$s</xliff:g> కోసం ఈ పాస్వర్డ్ మేనేజర్ మీకు సులభంగా సైన్ ఇన్ చేయడంలో సహాయపడటానికి మీ పాస్వర్డ్లు, పాస్-కీలను స్టోర్ చేస్తుంది"</string> <string name="set_as_default" msgid="4415328591568654603">"ఆటోమేటిక్ సెట్టింగ్గా సెట్ చేయండి"</string> <string name="settings" msgid="6536394145760913145">"సెట్టింగ్లు"</string> diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 1963b15c21b3..f072de8eead7 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Hierdie tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Geaktiveer"</string> <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_usb_device_name" msgid="7699141088423210903">"Bedrade oorfone"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 002d3bc17755..86f21d3045a0 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"ይህ ጡባዊ"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ነቅቷል"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"የእርስዎን መሣሪያ ይህ ለው ለማመልከት እንደገና መነሣት አለበት። አሁን እንደገና ያስነሡ ወይም ይተዉት።"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ባለገመድ ጆሮ ማዳመጫ"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 a459a8688960..39219f43e321 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"هذا الجهاز اللوحي"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"مفعّل"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"يجب إعادة تشغيل جهازك ليتم تطبيق هذا التغيير. يمكنك إعادة التشغيل الآن أو إلغاء التغيير."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"سمّاعة سلكية"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 6f6dce75747d..ae27622ae7c7 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"এই টেবলেটটো"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"সক্ষম কৰা আছে"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"এই সলনিটো কার্যকৰী হ’বলৈ আপোনাৰ ডিভাইচটো ৰিবুট কৰিবই লাগিব। এতিয়াই ৰিবুট কৰক অথবা বাতিল কৰক।"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"তাঁৰযুক্ত হেডফ\'ন"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 8cc67cb70500..843c1be7ba09 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Bu planşet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiv"</string> <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_usb_device_name" msgid="7699141088423210903">"Naqilli qulaqlıq"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 3688d0cbb35d..f9066341d5a9 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Ovaj tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogućeno"</string> <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_usb_device_name" msgid="7699141088423210903">"Žičane slušalice"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 f4f5331cbea0..613b7446b474 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Гэты планшэт"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Уключана"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Перазагрузіце прыладу, каб прымяніць гэта змяненне. Перазагрузіце ці скасуйце."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Правадныя навушнікі"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 dd16fc91db09..767be337c258 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Този таблет"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Активирано"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"За да бъде приложена тази промяна, устройството ви трябва да бъде рестартирано. Рестартирайте сега или анулирайте."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Слушалки с кабел"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 6b377178bd50..841954441f34 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"এই ট্যাবলেট"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"চালু করা আছে"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"এই পরিবর্তনটি প্রয়োগ করার জন্য আপনার ডিভাইসটি অবশ্যই রিবুট করতে হবে। এখনই রিবুট করুন বা বাতিল করুন।"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"তার যুক্ত হেডফোন"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 cb71f256a48c..12e8c73d33ae 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Ovaj tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogućeno"</string> <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_usb_device_name" msgid="7699141088423210903">"Žičane slušalice"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 84eb51fedda8..44780d3893d9 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Aquesta tauleta"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activat"</string> <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_usb_device_name" msgid="7699141088423210903">"Auriculars amb cable"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <skip /> <string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activa"</string> <string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactiva"</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 a8764b6cd9e4..cadb17021248 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Tento tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Zapnuto"</string> <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_usb_device_name" msgid="7699141088423210903">"Kabelová sluchátka"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 697802ead227..d3b064cce164 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Denne tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiveret"</string> <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_usb_device_name" msgid="7699141088423210903">"Høretelefoner med ledning"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 cb745fca6148..50bc9ccd0717 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Dieses Tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiviert"</string> <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_usb_device_name" msgid="7699141088423210903">"Kabelgebundene Kopfhörer"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 89817dd59661..ea6b3bacaad8 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Αυτό το tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ενεργή"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Για να εφαρμοστεί αυτή η αλλαγή, θα πρέπει να επανεκκινήσετε τη συσκευή σας. Επανεκκίνηση τώρα ή ακύρωση."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Ενσύρματα ακουστικά"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 b6e41c474746..03e505a76c0f 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"This tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string> <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_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 be5dfaa7434e..9fce5666b349 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"This tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string> <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_usb_device_name" msgid="7699141088423210903">"Wired headphone"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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">"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 b6e41c474746..03e505a76c0f 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"This tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string> <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_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index b6e41c474746..03e505a76c0f 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"This tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string> <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_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 92af28477547..85cf936a764b 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"This tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string> <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_usb_device_name" msgid="7699141088423210903">"Wired headphone"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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">"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 ff69f6495eda..3feee4c5cabd 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -564,8 +564,7 @@ <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas y recordatorios"</string> <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite que esta app establezca alarmas y programe acciones para horarios específicos. De esta manera, la app puede ejecutarse en segundo plano, lo que podría aumentar el consumo de batería.\n\nSi se desactiva este permiso, no funcionarán las alarmas ni los eventos basados en el tiempo existentes que programe esta app."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarma, recordatorio, reloj"</string> - <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) --> - <skip /> + <string name="zen_mode_do_not_disturb_name" msgid="6798711401734798283">"No interrumpir"</string> <string name="zen_mode_settings_title" msgid="7374070457626419755">"No interrumpir"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activar"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activar No interrumpir"</string> @@ -585,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Esta tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -686,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Habilitado"</string> <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_usb_device_name" msgid="7699141088423210903">"Auriculares con cable"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 e2d35891d149..d2c7a029af2c 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -564,8 +564,7 @@ <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas y recordatorios"</string> <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite que esta aplicación programe alarmas y otras acciones que se llevan a cabo a una hora determinada. Esto hace que la aplicación pueda seguir activa en segundo plano, lo que puede usar más batería.\n\nSi este permiso está desactivado, no funcionarán las alarmas ni los eventos que se activan a una hora determinada que programe esta aplicación."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarma, recordatorio, reloj"</string> - <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) --> - <skip /> + <string name="zen_mode_do_not_disturb_name" msgid="6798711401734798283">"No molestar"</string> <string name="zen_mode_settings_title" msgid="7374070457626419755">"No molestar"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activar"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activar el modo No molestar"</string> @@ -585,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Esta tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -686,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Habilitado"</string> <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_usb_device_name" msgid="7699141088423210903">"Auriculares con cable"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 8f7c4a722f1b..1452a0e162fd 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"See tahvelarvuti"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Lubatud"</string> <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_usb_device_name" msgid="7699141088423210903">"Juhtmega kõrvaklapid"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 72855477ad25..2d97bbfb4a12 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Tableta hau"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Gaituta"</string> <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_usb_device_name" msgid="7699141088423210903">"Entzungailu kableduna"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 ff0ad1df79b6..11dcc998e6eb 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"این رایانه لوحی"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"فعال"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"برای اعمال این تغییر، دستگاه باید بازراهاندازی شود. یا اکنون بازراهاندازی کنید یا لغو کنید."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"هدفون سیمی"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 800f327f2a39..4ee5c60b3688 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Tämä tabletti"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Käytössä"</string> <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_usb_device_name" msgid="7699141088423210903">"Langalliset kuulokkeet"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 f36b5f00beb3..d975f3e9b47a 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Cette tablette"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activé"</string> <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_usb_device_name" msgid="7699141088423210903">"Écouteurs filaires"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 432770857815..c987bc480b04 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -564,8 +564,7 @@ <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes et rappels"</string> <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Autoriser cette appli à définir des alarmes et à programmer des actions à certaines heures. Elle s\'exécutera alors en arrière-plan, ce qui peut solliciter davantage la batterie.\n\nSi l\'autorisation est désactivée, les alarmes existantes et les événements programmés par l\'appli ne fonctionneront pas."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"définir, alarme, rappel, horloge"</string> - <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) --> - <skip /> + <string name="zen_mode_do_not_disturb_name" msgid="6798711401734798283">"Ne pas déranger"</string> <string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne pas déranger"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activer"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activer le mode Ne pas déranger"</string> @@ -585,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Cette tablette"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -686,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activé"</string> <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_usb_device_name" msgid="7699141088423210903">"Casque filaire"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 bac62f22f1fd..0216ad92b809 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Esta tableta"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activado"</string> <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_usb_device_name" msgid="7699141088423210903">"Auriculares con cable"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 9af8e48d818a..bc34173a1e37 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"આ ટૅબ્લેટ"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ચાલુ છે"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"આ ફેરફારને લાગુ કરવા માટે તમારા ડિવાઇસને રીબૂટ કરવાની જરૂર છે. હમણાં જ રીબૂટ કરો કે રદ કરો."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"વાયરવાળો હૅડફોન"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 785ef59df6d6..25309b3eb986 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"यह टैबलेट"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"चालू है"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"बदली गई सेटिंग को लागू करने के लिए, डिवाइस को रीस्टार्ट करना होगा. अपने डिवाइस को रीस्टार्ट करें या रद्द करें."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"वायर वाला हेडफ़ोन"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 107c5617998b..516834dc5fde 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Ovaj tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogućeno"</string> <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_usb_device_name" msgid="7699141088423210903">"Žičane slušalice"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 dff22d9d3517..1d2b71560a63 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Ez a táblagép"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Engedélyezve"</string> <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_usb_device_name" msgid="7699141088423210903">"Vezetékes fejhallgató"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 60e5adfee7f1..85b554884846 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Այս պլանշետը"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Միացված է"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Սարքն անհրաժեշտ է վերագործարկել, որպեսզի փոփոխությունը կիրառվի։ Վերագործարկեք հիմա կամ չեղարկեք փոփոխությունը։"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Լարով ականջակալ"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 f0b76cef02c6..6660188ca2dc 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Tablet ini"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktif"</string> <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_usb_device_name" msgid="7699141088423210903">"Headphone berkabel"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 61813a392bc8..098489271b01 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Þessi spjaldtölva"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Virkt"</string> <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_usb_device_name" msgid="7699141088423210903">"Heyrnartól með snúru"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 10394f1f597a..e70c415ce49a 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -564,8 +564,7 @@ <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Sveglie e promemoria"</string> <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Consenti a questa app di impostare sveglie e programmare azioni per orari specifici. L\'app potrà essere eseguita in background, comportando un consumo maggiore della batteria.\n\nSe questa autorizzazione viene disattivata, le sveglie esistenti e gli eventi basati sull\'orario programmati da questa app non funzioneranno."</string> <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programmare, sveglia, promemoria, orologio"</string> - <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) --> - <skip /> + <string name="zen_mode_do_not_disturb_name" msgid="6798711401734798283">"Non disturbare"</string> <string name="zen_mode_settings_title" msgid="7374070457626419755">"Non disturbare"</string> <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Attiva"</string> <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Attiva Non disturbare"</string> @@ -585,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Questo tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -686,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Attivo"</string> <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_usb_device_name" msgid="7699141088423210903">"Cuffie con cavo"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 c0f1e8782a74..662455d93a2d 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"הטאבלט הזה"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"מופעל"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"צריך להפעיל מחדש את המכשיר כדי להחיל את השינוי. יש להפעיל מחדש עכשיו או לבטל."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"אוזניות חוטיות"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 71aae44b000b..70fc2d068fc9 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"このタブレット"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"有効"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"この変更を適用するには、デバイスの再起動が必要です。今すぐ再起動するか、キャンセルしてください。"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有線ヘッドフォン"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 7801417586df..040c046f0b26 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"ამ ტაბლეტზე"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ჩართული"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ამ ცვლილების ასამოქმედებლად თქვენი მოწყობილობა უნდა გადაიტვირთოს. გადატვირთეთ ახლავე ან გააუქმეთ."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"სადენიანი ყურსასმენი"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 2ae8250189fd..f54067c00f46 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Осы планшет"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Қосулы"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Бұл өзгеріс күшіне енуі үшін, құрылғыны қайта жүктеу керек. Қазір қайта жүктеңіз не бас тартыңыз."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Сымды құлақаспап"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 85801c9cd606..807e7e2cfb4e 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"ថេប្លេតនេះ"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"បានបើក"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ត្រូវតែចាប់ផ្ដើមឧបករណ៍របស់អ្នកឡើងវិញ ដើម្បីឱ្យការផ្លាស់ប្ដូរនេះមានប្រសិទ្ធភាព។ ចាប់ផ្ដើមឡើងវិញឥឡូវនេះ ឬបោះបង់។"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"កាសមានខ្សែ"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 6dc3ae9d2ea1..23e31c246cab 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"ಈ ಟ್ಯಾಬ್ಲೆಟ್"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ಈ ಬದಲಾವಣೆ ಅನ್ವಯವಾಗಲು ನಿಮ್ಮ ಸಾಧನವನ್ನು ರೀಬೂಟ್ ಮಾಡಬೇಕು. ಇದೀಗ ರೀಬೂಟ್ ಮಾಡಿ ಅಥವಾ ರದ್ದುಗೊಳಿಸಿ."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ವೈಯರ್ ಹೊಂದಿರುವ ಹೆಡ್ಫೋನ್"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 14e8f4f1561b..cfbddad8d259 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"이 태블릿"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"사용 설정됨"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"변경사항을 적용하려면 기기를 재부팅해야 합니다. 지금 재부팅하거나 취소하세요."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"유선 헤드폰"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 9ff62cf0f96a..c5a3bcca9e19 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Ушул планшет"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Күйүк"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Бул өзгөрүү күчүнө кириши үчүн, түзмөктү өчүрүп күйгүзүңүз. Азыр же кийинчерээк өчүрүп күйгүзсөңүз болот."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Зымдуу гарнитура"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 5d5a4c6188a5..70fd1964154e 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"ແທັບເລັດນີ້"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ເປີດການນຳໃຊ້ແລ້ວ"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ທ່ານຕ້ອງປິດເປີດອຸປະກອນຄືນໃໝ່ເພື່ອນຳໃຊ້ການປ່ຽນແປງນີ້. ປິດເປີດໃໝ່ດຽວນີ້ ຫຼື ຍົກເລີກ."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ຫູຟັງແບບມີສາຍ"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 2b0b71d368e5..54884378704a 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Šis planšetinis kompiuteris"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Įgalinta"</string> <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_usb_device_name" msgid="7699141088423210903">"Laidinės ausinės"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 a8a4ea063cb7..faf7b5f26480 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Šis planšetdators"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Iespējots"</string> <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_usb_device_name" msgid="7699141088423210903">"Vadu austiņas"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 923ea5cc046a..2f215e8487b0 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Овој таблет"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Овозможено"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"За да се примени променава, уредот мора да се рестартира. Рестартирајте сега или откажете."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Жичени слушалки"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 05579fec0a10..859ac3b1ad0d 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"ഈ ടാബ്ലെറ്റ്"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"പ്രവർത്തനക്ഷമമാക്കി"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ഈ മാറ്റം ബാധകമാകുന്നതിന് നിങ്ങളുടെ ഉപകരണം റീബൂട്ട് ചെയ്യേണ്ടതുണ്ട്. ഇപ്പോൾ റീബൂട്ട് ചെയ്യുകയോ റദ്ദാക്കുകയോ ചെയ്യുക."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"വയേർഡ് ഹെഡ്ഫോൺ"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 8957a2b174a1..7615dccb3f95 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Энэ таблет"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Идэвхжүүлсэн"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Энэ өөрчлөлтийг хэрэгжүүлэхийн тулд таны төхөөрөмжийг дахин асаах ёстой. Одоо дахин асаах эсвэл цуцлана уу."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Утастай чихэвч"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 36b967e3131f..fb90ce35b8f5 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"हा टॅबलेट"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"सुरू केले आहे"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"हा बदल लागू करण्यासाठी तुमचे डिव्हाइस रीबूट करणे आवश्यक आहे. आता रीबूट करा किंवा रद्द करा."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"वायर असलेला हेडफोन"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 2db04be96e21..acd84876f94d 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Tablet ini"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Didayakan"</string> <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_usb_device_name" msgid="7699141088423210903">"Fon kepala berwayar"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 660fd146e8bd..2640c3a6e0b2 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"ဤတက်ဘလက်"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ဖွင့်ထားသည်"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ဤအပြောင်းအလဲ ထည့်သွင်းရန် သင့်စက်ကို ပြန်လည်စတင်ရမည်။ ယခု ပြန်လည်စတင်ပါ သို့မဟုတ် ပယ်ဖျက်ပါ။"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ကြိုးတပ်နားကြပ်"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 3e5d141616b1..4a53090e37b3 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Dette nettbrettet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Slått på"</string> <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_usb_device_name" msgid="7699141088423210903">"hodetelefoner med kabel"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 ad2888285c42..a04028f39aa8 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"यो ट्याब्लेट"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"सक्षम पारिएको छ"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"यो परिवर्तन लागू गर्न तपाईंको यन्त्र अनिवार्य रूपमा रिबुट गर्नु पर्छ। अहिले रिबुट गर्नुहोस् वा रद्द गर्नुहोस्।"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"तारसहितको हेडफोन"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 0fcc6fecf578..c3998c5d6beb 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Deze tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aan"</string> <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_usb_device_name" msgid="7699141088423210903">"Bedrade koptelefoon"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 694d034812c8..676a4269e10c 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"ଏହି ଟାବଲେଟ"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ସକ୍ଷମ କରାଯାଇଛି"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ଏହି ପରିବର୍ତ୍ତନ ଲାଗୁ କରିବା ପାଇଁ ଆପଣଙ୍କ ଡିଭାଇସକୁ ନିଶ୍ଚିତ ରୂପେ ରିବୁଟ୍ କରାଯିବା ଆବଶ୍ୟକ। ବର୍ତ୍ତମାନ ରିବୁଟ୍ କରନ୍ତୁ କିମ୍ବା ବାତିଲ କରନ୍ତୁ।"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ତାରଯୁକ୍ତ ହେଡଫୋନ୍"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 d0cf8205aa92..4ef2308c1368 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"ਇਹ ਟੈਬਲੈੱਟ"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ਇਸ ਤਬਦੀਲੀ ਨੂੰ ਲਾਗੂ ਕਰਨ ਲਈ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨੂੰ ਰੀਬੂਟ ਕਰਨਾ ਲਾਜ਼ਮੀ ਹੈ। ਹੁਣੇ ਰੀਬੂਟ ਕਰੋ ਜਾਂ ਰੱਦ ਕਰੋ।"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ਤਾਰ ਵਾਲੇ ਹੈੱਡਫ਼ੋਨ"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 c6d78f6f9e20..3693c388527d 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Ten tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Włączono"</string> <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_usb_device_name" msgid="7699141088423210903">"Słuchawki przewodowe"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 98bda8519c50..75ffcd1b7a27 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Este tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ativado"</string> <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_usb_device_name" msgid="7699141088423210903">"Fones de ouvido com fio"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 20acb00d89e5..535261b6d7e4 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Este tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ativada"</string> <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_usb_device_name" msgid="7699141088423210903">"Auscultadores com fios"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 98bda8519c50..75ffcd1b7a27 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Este tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ativado"</string> <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_usb_device_name" msgid="7699141088423210903">"Fones de ouvido com fio"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 a6d17c19d6c1..242127ead7fa 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Această tabletă"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activat"</string> <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_usb_device_name" msgid="7699141088423210903">"Căști cu fir"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 838b5eda1573..2ac012867d79 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Этот планшет"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Включено"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Чтобы изменение вступило в силу, необходимо перезапустить устройство. Вы можете сделать это сейчас или позже."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Проводные наушники"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 cc7a45eb344f..f8565c4669cf 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"මෙම ටැබ්ලටය"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"සබලයි"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"මෙම වෙනස යෙදීමට ඔබේ උපාංගය නැවත පණ ගැන්විය යුතුය. දැන් නැවත පණ ගන්වන්න හෝ අවලංගු කරන්න."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"රැහැන්ගත කළ හෙඩ්ෆෝන්"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 43db02b48ce9..00bb994c812d 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Tento tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Zapnuté"</string> <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_usb_device_name" msgid="7699141088423210903">"Slúchadlá s káblom"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 ddd0fb235be6..5bce9fac9596 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Ta tablični računalnik"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogočeno"</string> <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_usb_device_name" msgid="7699141088423210903">"Žične slušalke"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 3831cf4e3ec6..59472e3f5f21 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Ky tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiv"</string> <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_usb_device_name" msgid="7699141088423210903">"Kufje me tela"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 73794bd5f1be..57e2a0a60fe4 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Овај таблет"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Омогућено"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Морате да рестартујете уређај да би се ова промена применила. Рестартујте га одмах или откажите."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Жичане слушалице"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 f47bdabaa594..a3eaee13e357 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Den här surfplattan"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiverat"</string> <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_usb_device_name" msgid="7699141088423210903">"Hörlurar med sladd"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 02db3e13c8bf..9979a9d4bd57 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Kishikwambi hiki"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Imewashwa"</string> <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_usb_device_name" msgid="7699141088423210903">"Vipokea sauti vya waya"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 a5a96f20b8e1..18a3186b6f44 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"இந்த டேப்லெட்"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"இயக்கப்பட்டது"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"இந்த மாற்றங்கள் செயல்படுத்தப்பட உங்கள் சாதனத்தை மறுபடி தொடங்க வேண்டும். இப்போதே மறுபடி தொடங்கவும் அல்லது ரத்துசெய்யவும்."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"வயருள்ள ஹெட்ஃபோன்"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 5577389cafa8..f883796fb07b 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"ఈ టాబ్లెట్"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ఎనేబుల్ చేయబడింది"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"ఈ మార్పును వర్తింపజేయాలంటే మీరు మీ పరికరాన్ని తప్పనిసరిగా రీబూట్ చేయాలి. ఇప్పుడే రీబూట్ చేయండి లేదా రద్దు చేయండి."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"వైర్ ఉన్న హెడ్ఫోన్"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 48087c27cf93..e56656b33152 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"แท็บเล็ตเครื่องนี้"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"เปิดใช้"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"คุณต้องรีบูตอุปกรณ์เพื่อให้การเปลี่ยนแปลงนี้มีผล รีบูตเลยหรือยกเลิก"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"หูฟังแบบมีสาย"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 34d51d4434e9..3e9f238783eb 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Ang tablet na ito"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Na-enable"</string> <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_usb_device_name" msgid="7699141088423210903">"Wired na headphone"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 9b5cc2926479..22c0ab168fb3 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Bu tablet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Etkin"</string> <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_usb_device_name" msgid="7699141088423210903">"Kablolu kulaklık"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 a3967987340f..50ebd24c380f 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Цей планшет"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Увімкнено"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Щоб застосувати ці зміни, потрібний перезапуск. Перезапустіть пристрій або скасуйте зміни."</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Дротові навушники"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 c60a58bb41ba..d6dd2c8f18ae 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"یہ ٹیبلیٹ"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"فعال"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"اس تبدیلی کو لاگو کرنے کے ليے آپ کے آلہ کو ریبوٹ کرنا ضروری ہے۔ ابھی ریبوٹ کریں یا منسوخ کریں۔"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"وائرڈ ہیڈ فون"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 3beb5148844d..1e3d64f34acf 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Shu planshet"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Yoniq"</string> <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_usb_device_name" msgid="7699141088423210903">"Simli quloqlik"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 d3152f4c7850..95092ff23f63 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Máy tính bảng này"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Đã bật"</string> <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_usb_device_name" msgid="7699141088423210903">"Tai nghe có dây"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 964c3dacafc2..fb9e7b17de45 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"这部平板电脑"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"已启用"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"设备必须重新启动才能应用此更改。您可以立即重新启动或取消。"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有线耳机"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 a35b9f23667c..9c6da5ffa2f0 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"此平板電腦"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"已啟用"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"你的裝置必須重新開機,才能套用此變更。請立即重新開機或取消。"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有線耳機"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 274767b11e97..501b088dcec5 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"這台平板電腦"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"已啟用"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"裝置必須重新啟動才能套用這項變更。請立即重新啟動或取消變更。"</string> <string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有線耳機"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 9ccb2616e3ad..4f875deb546b 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -584,6 +584,8 @@ <string name="media_transfer_this_device_name_tablet" msgid="2975593806278422086">"Le thebhulethi"</string> <!-- no translation found for media_transfer_this_device_name_tv (5285685336836896535) --> <skip /> + <!-- no translation found for media_transfer_internal_mic (797333824290228595) --> + <skip /> <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> @@ -685,6 +687,10 @@ <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Inikwe amandla"</string> <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_usb_device_name" msgid="7699141088423210903">"Ama-headphone anentambo"</string> + <!-- no translation found for media_transfer_wired_device_mic_name (7417067197803840965) --> + <skip /> + <!-- no translation found for media_transfer_usb_device_mic_name (9189914846215516322) --> + <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 feee89a51e7c..34e33c0df8f5 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1409,6 +1409,8 @@ <string name="media_transfer_this_device_name">This phone</string> <!-- Name of the tablet device. [CHAR LIMIT=30] --> <string name="media_transfer_this_device_name_tablet">This tablet</string> + <!-- Name of the internal speaker. [CHAR LIMIT=30] --> + <string name="media_transfer_this_device_name_desktop">This computer (internal)</string> <!-- Name of the default media output of the TV. [CHAR LIMIT=30] --> <string name="media_transfer_this_device_name_tv">@string/tv_media_transfer_default</string> <!-- Name of the internal mic. [CHAR LIMIT=30] --> @@ -1637,7 +1639,13 @@ <string name="cached_apps_freezer_reboot_dialog_text">Your device must be rebooted for this change to apply. Reboot now or cancel.</string> <!-- Name of the 3.5mm and usb audio device. [CHAR LIMIT=50] --> - <string name="media_transfer_wired_usb_device_name">Wired headphone</string> + <string name="media_transfer_wired_headphone_name">Wired headphone</string> + + <!-- Name of the 3.5mm headphone, used in desktop devices. [CHAR LIMIT=50] --> + <string name="media_transfer_headphone_name">Headphone</string> + + <!-- Name of the usb audio device speaker, used in desktop devices. [CHAR LIMIT=50] --> + <string name="media_transfer_usb_speaker_name">USB speaker</string> <!-- Name of the 3.5mm audio device mic. [CHAR LIMIT=50] --> <string name="media_transfer_wired_device_mic_name">Mic jack</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java index 148e164e4806..c9f9d1be9c15 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java @@ -151,7 +151,19 @@ public class LocalBluetoothLeBroadcastAssistant implements LocalBluetoothProfile Log.d(TAG, "The BluetoothLeBroadcastAssistant is null"); return; } - mService.addSource(sink, metadata, isGroupOp); + try { + mService.addSource(sink, metadata, isGroupOp); + } catch (IllegalStateException e) { + // BT will check callback registration before add source. + // If it throw callback exception when bt is disabled, then the failure is intended, + // just catch it here. + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if (adapter != null && adapter.isEnabled()) { + throw e; + } else { + Log.d(TAG, "Catch addSource failure when bt is disabled: " + e); + } + } } /** diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java index 548eb3fd4b8f..874e03012ae2 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java @@ -57,7 +57,7 @@ public final class InputRouteManager { } }; - /* package */ InputRouteManager(@NonNull Context context, @NonNull AudioManager audioManager) { + public InputRouteManager(@NonNull Context context, @NonNull AudioManager audioManager) { mContext = context; mAudioManager = audioManager; Handler handler = new Handler(context.getMainLooper()); diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java index 9eaf8d3838d8..0b8fb22cef3a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java @@ -72,6 +72,8 @@ public class PhoneMediaDevice extends MediaDevice { return context.getString(R.string.media_transfer_this_device_name_tv); } else if (isTablet()) { return context.getString(R.string.media_transfer_this_device_name_tablet); + } else if (inputRoutingEnabledAndIsDesktop()) { + return context.getString(R.string.media_transfer_this_device_name_desktop); } else { return context.getString(R.string.media_transfer_this_device_name); } @@ -85,10 +87,18 @@ public class PhoneMediaDevice extends MediaDevice { switch (routeInfo.getType()) { case TYPE_WIRED_HEADSET: case TYPE_WIRED_HEADPHONES: + name = + inputRoutingEnabledAndIsDesktop() + ? context.getString(R.string.media_transfer_headphone_name) + : context.getString(R.string.media_transfer_wired_headphone_name); + break; case TYPE_USB_DEVICE: case TYPE_USB_HEADSET: case TYPE_USB_ACCESSORY: - name = context.getString(R.string.media_transfer_wired_usb_device_name); + name = + inputRoutingEnabledAndIsDesktop() + ? context.getString(R.string.media_transfer_usb_speaker_name) + : context.getString(R.string.media_transfer_wired_headphone_name); break; case TYPE_DOCK: name = context.getString(R.string.media_transfer_dock_speaker_device_name); @@ -139,6 +149,16 @@ public class PhoneMediaDevice extends MediaDevice { .contains("tablet"); } + static boolean isDesktop() { + return Arrays.asList(SystemProperties.get("ro.build.characteristics").split(",")) + .contains("desktop"); + } + + static boolean inputRoutingEnabledAndIsDesktop() { + return com.android.media.flags.Flags.enableAudioInputDeviceRoutingAndVolumeControl() + && isDesktop(); + } + // MediaRoute2Info.getType was made public on API 34, but exists since API 30. @SuppressWarnings("NewApi") @Override diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java index e2d58d660fd5..da5f428ce23b 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java @@ -47,6 +47,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.shadows.ShadowSystemProperties; @RunWith(RobolectricTestRunner.class) public class PhoneMediaDeviceTest { @@ -105,12 +106,37 @@ public class PhoneMediaDeviceTest { when(mInfo.getName()).thenReturn(deviceName); assertThat(mPhoneMediaDevice.getName()) - .isEqualTo(mContext.getString(R.string.media_transfer_wired_usb_device_name)); + .isEqualTo(mContext.getString(R.string.media_transfer_wired_headphone_name)); when(mInfo.getType()).thenReturn(TYPE_USB_DEVICE); assertThat(mPhoneMediaDevice.getName()) - .isEqualTo(mContext.getString(R.string.media_transfer_wired_usb_device_name)); + .isEqualTo(mContext.getString(R.string.media_transfer_wired_headphone_name)); + + when(mInfo.getType()).thenReturn(TYPE_BUILTIN_SPEAKER); + + assertThat(mPhoneMediaDevice.getName()).isEqualTo(getMediaTransferThisDeviceName(mContext)); + } + + @EnableFlags(Flags.FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL) + @Test + public void getName_returnCorrectName_desktop() { + ShadowSystemProperties.override("ro.build.characteristics", "desktop"); + + when(mInfo.getType()).thenReturn(TYPE_WIRED_HEADPHONES); + + assertThat(mPhoneMediaDevice.getName()) + .isEqualTo(mContext.getString(R.string.media_transfer_headphone_name)); + + when(mInfo.getType()).thenReturn(TYPE_WIRED_HEADSET); + + assertThat(mPhoneMediaDevice.getName()) + .isEqualTo(mContext.getString(R.string.media_transfer_headphone_name)); + + when(mInfo.getType()).thenReturn(TYPE_USB_DEVICE); + + assertThat(mPhoneMediaDevice.getName()) + .isEqualTo(mContext.getString(R.string.media_transfer_usb_speaker_name)); when(mInfo.getType()).thenReturn(TYPE_BUILTIN_SPEAKER); diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp index c107ff5a34ce..1a99d25786ff 100644 --- a/packages/SettingsProvider/Android.bp +++ b/packages/SettingsProvider/Android.bp @@ -36,6 +36,7 @@ android_library { "aconfig_new_storage_flags_lib", "aconfigd_java_utils", "aconfig_demo_flags_java_lib", + "configinfra_framework_flags_java_lib", "device_config_service_flags_java", "libaconfig_java_proto_lite", "SettingsLibDeviceStateRotationLock", diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java index c9ad5a5e3b90..fbce6ca07b3e 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java @@ -99,13 +99,23 @@ public final class DeviceConfigService extends Binder { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.print("SyncDisabledForTests: "); - MyShellCommand.getSyncDisabledForTests(pw, pw); - - pw.print("Is mainline: "); - pw.println(UpdatableDeviceConfigServiceReadiness.shouldStartUpdatableService()); + if (android.provider.flags.Flags.dumpImprovements()) { + pw.print("SyncDisabledForTests: "); + MyShellCommand.getSyncDisabledForTests(pw, pw); + + pw.print("UpdatableDeviceConfigServiceReadiness.shouldStartUpdatableService(): "); + pw.println(UpdatableDeviceConfigServiceReadiness.shouldStartUpdatableService()); + + pw.println("DeviceConfig provider: "); + try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(fd)) { + DeviceConfig.dump(pfd, pw, /* prefix= */ " ", args); + } catch (IOException e) { + pw.print("IOException creating ParcelFileDescriptor: "); + pw.println(e); + } + } - final IContentProvider iprovider = mProvider.getIContentProvider(); + IContentProvider iprovider = mProvider.getIContentProvider(); pw.println("DeviceConfig flags:"); for (String line : MyShellCommand.listAll(iprovider)) { pw.println(line); @@ -251,22 +261,13 @@ public final class DeviceConfigService extends Binder { public static HashMap<String, String> getAllFlags(IContentProvider provider) { HashMap<String, String> allFlags = new HashMap<String, String>(); - try { - Bundle args = new Bundle(); - args.putInt(Settings.CALL_METHOD_USER_KEY, - ActivityManager.getService().getCurrentUser().id); - Bundle b = provider.call(new AttributionSource(Process.myUid(), - resolveCallingPackage(), null), Settings.AUTHORITY, - Settings.CALL_METHOD_LIST_CONFIG, null, args); - if (b != null) { - Map<String, String> flagsToValues = - (HashMap) b.getSerializable(Settings.NameValueTable.VALUE); - allFlags.putAll(flagsToValues); + for (DeviceConfig.Properties properties : DeviceConfig.getAllProperties()) { + List<String> keys = new ArrayList<>(properties.getKeyset()); + for (String flagName : properties.getKeyset()) { + String fullName = properties.getNamespace() + "/" + flagName; + allFlags.put(fullName, properties.getString(flagName, null)); } - } catch (RemoteException e) { - throw new RuntimeException("Failed in IPC", e); } - return allFlags; } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index ba59ce81d362..0ae4da53045e 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -545,6 +545,10 @@ public class SettingsProvider extends ContentProvider { reportDeviceConfigAccess(prefix); return result; } + case Settings.CALL_METHOD_LIST_NAMESPACES_CONFIG -> { + Bundle result = packageNamespacesForCallResult(getAllConfigFlagNamespaces()); + return result; + } case Settings.CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG -> { RemoteCallback callback = args.getParcelable( Settings.CALL_METHOD_MONITOR_CALLBACK_KEY); @@ -1337,6 +1341,23 @@ public class SettingsProvider extends ContentProvider { } @NonNull + private HashSet<String> getAllConfigFlagNamespaces() { + Set<String> flagNames = getAllConfigFlags(null).keySet(); + HashSet<String> namespaces = new HashSet(); + for (String name : flagNames) { + int slashIndex = name.indexOf("/"); + boolean validSlashIndex = slashIndex != -1 + && slashIndex != 0 + && slashIndex != name.length(); + if (validSlashIndex) { + String namespace = name.substring(0, slashIndex); + namespaces.add(namespace); + } + } + return namespaces; + } + + @NonNull private HashMap<String, String> getAllConfigFlags(@Nullable String prefix) { if (DEBUG) { Slog.v(LOG_TAG, "getAllConfigFlags() for " + prefix); @@ -2561,6 +2582,12 @@ public class SettingsProvider extends ContentProvider { return result; } + private Bundle packageNamespacesForCallResult(@NonNull HashSet<String> namespaces) { + Bundle result = new Bundle(); + result.putSerializable(Settings.NameValueTable.VALUE, namespaces); + return result; + } + private void setMonitorCallback(RemoteCallback callback) { if (callback == null) { return; diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index f59eab001be9..cd16af76d4b8 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -452,7 +452,7 @@ filegroup { "tests/src/**/systemui/clipboardoverlay/ClipboardListenerTest.java", "tests/src/**/systemui/doze/DozeScreenStateTest.java", "tests/src/**/systemui/keyguard/WorkLockActivityControllerTest.java", - "tests/src/**/systemui/media/dialog/MediaOutputControllerTest.java", + "tests/src/**/systemui/media/dialog/MediaSwitchingControllerTest.java", "tests/src/**/systemui/navigationbar/views/NavigationBarTest.java", "tests/src/**/systemui/power/PowerNotificationWarningsTest.java", "tests/src/**/systemui/power/PowerUITest.java", diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 7974f9222a0c..855ebe3799b8 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -149,6 +149,16 @@ flag { } flag { + name: "modes_dialog_single_rows" + namespace: "systemui" + description: "[Experiment] Display one entry per grid row in the Modes Dialog." + bug: "366034002" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "pss_app_selector_recents_split_screen" namespace: "systemui" description: "Allows recent apps selected for partial screenshare to be launched in split screen mode" @@ -528,6 +538,13 @@ flag { } flag { + name: "status_bar_connected_displays" + namespace: "systemui" + description: "Shows the status bar on connected displays" + bug: "362720336" +} + +flag { name: "status_bar_switch_to_spn_from_data_spn" namespace: "systemui" description: "Fix usage of the SPN broadcast extras" @@ -538,10 +555,10 @@ flag { } flag { - name: "haptic_volume_slider" + name: "status_bar_simple_fragment" namespace: "systemui" - description: "Adds haptic feedback to the volume slider." - bug: "316953430" + description: "Feature flag for refactoring the collapsed status bar fragment" + bug: "364360986" } flag { @@ -668,13 +685,6 @@ flag { } flag { - name: "compose_lockscreen" - namespace: "systemui" - description: "Enables the compose version of lockscreen that runs standalone, outside of Flexiglass." - bug: "301968149" -} - -flag { name: "enable_contextual_tip_for_power_off" namespace: "systemui" description: "Enables on-screen contextual tip about how to power off or restart phone" diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt index 9d0b095ad4cc..d02527531a53 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt @@ -57,6 +57,7 @@ import com.android.systemui.Flags.activityTransitionUseLargestWindow import com.android.systemui.Flags.translucentOccludingActivityFix import com.android.systemui.animation.TransitionAnimator.Companion.toTransitionState import com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary +import com.android.systemui.shared.Flags.returnAnimationFrameworkLongLived import com.android.wm.shell.shared.IShellTransitions import com.android.wm.shell.shared.ShellTransitions import java.util.concurrent.Executor @@ -607,8 +608,8 @@ constructor( * this registration. */ fun register(controller: Controller) { - check(returnAnimationFrameworkLibrary()) { - "Long-lived registrations cannot be used when the returnAnimationFrameworkLibrary " + + check(returnAnimationFrameworkLongLived()) { + "Long-lived registrations cannot be used when the returnAnimationFrameworkLongLived " + "flag is disabled" } diff --git a/packages/SystemUI/compose/core/src/com/android/compose/windowsizeclass/WindowSizeClass.kt b/packages/SystemUI/compose/core/src/com/android/compose/windowsizeclass/WindowSizeClass.kt index c01396a96b6e..4674d6e5f25a 100644 --- a/packages/SystemUI/compose/core/src/com/android/compose/windowsizeclass/WindowSizeClass.kt +++ b/packages/SystemUI/compose/core/src/com/android/compose/windowsizeclass/WindowSizeClass.kt @@ -16,16 +16,15 @@ package com.android.compose.windowsizeclass -import android.view.WindowManager import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi import androidx.compose.material3.windowsizeclass.WindowSizeClass import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.graphics.toComposeRect import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity +import androidx.window.layout.WindowMetricsCalculator val LocalWindowSizeClass = staticCompositionLocalOf<WindowSizeClass> { @@ -42,10 +41,7 @@ fun calculateWindowSizeClass(): WindowSizeClass { LocalConfiguration.current val density = LocalDensity.current val context = LocalContext.current - val metrics = - remember(context) { - context.getSystemService(WindowManager::class.java)!!.currentWindowMetrics - } + val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context) val size = with(density) { metrics.bounds.toComposeRect().size.toDpSize() } return WindowSizeClass.calculateFromSize(size) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt index 163b35596c1b..8321238b28b1 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt @@ -16,7 +16,6 @@ package com.android.systemui.bouncer.ui.composable -import android.view.HapticFeedbackConstants import androidx.annotation.VisibleForTesting import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.AnimationVector1D @@ -133,10 +132,7 @@ fun PatternBouncer( // Perform haptic feedback, but only if the current dot is not null, so we don't perform it // when the UI first shows up or when the user lifts their pointer/finger. if (currentDot != null) { - view.performHapticFeedback( - HapticFeedbackConstants.VIRTUAL_KEY, - HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING, - ) + viewModel.performDotFeedback(view) } if (!isAnimationEnabled) { @@ -206,10 +202,7 @@ fun PatternBouncer( // Show the failure animation if the user entered the wrong input. LaunchedEffect(animateFailure) { if (animateFailure) { - showFailureAnimation( - dots = dots, - scalingAnimatables = dotScalingAnimatables, - ) + showFailureAnimation(dots = dots, scalingAnimatables = dotScalingAnimatables) viewModel.onFailureAnimationShown() } } @@ -358,15 +351,10 @@ fun PatternBouncer( (1 - checkNotNull(dotAppearMoveUpAnimatables[dot]).value) * initialOffset drawCircle( center = - pixelOffset( - dot, - spacing, - horizontalOffset, - verticalOffset + appearOffset, - ), + pixelOffset(dot, spacing, horizontalOffset, verticalOffset + appearOffset), color = dotColor.copy(alpha = checkNotNull(dotAppearFadeInAnimatables[dot]).value), - radius = dotRadius * checkNotNull(dotScalingAnimatables[dot]).value + radius = dotRadius * checkNotNull(dotScalingAnimatables[dot]).value, ) } } @@ -387,7 +375,7 @@ private suspend fun showEntryAnimation( delayMillis = 33 * dot.y, durationMillis = 450, easing = Easings.LegacyDecelerate, - ) + ), ) } } @@ -400,7 +388,7 @@ private suspend fun showEntryAnimation( delayMillis = 0, durationMillis = 450 + (33 * dot.y), easing = Easings.StandardDecelerate, - ) + ), ) } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt index 489e24e8b328..0830c9b359a4 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt @@ -16,8 +16,8 @@ package com.android.systemui.bouncer.ui.composable -import android.view.HapticFeedbackConstants import android.view.MotionEvent +import android.view.View import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.AnimationSpec @@ -72,11 +72,7 @@ import kotlinx.coroutines.launch /** Renders the PIN button pad. */ @Composable -fun PinPad( - viewModel: PinBouncerViewModel, - verticalSpacing: Dp, - modifier: Modifier = Modifier, -) { +fun PinPad(viewModel: PinBouncerViewModel, verticalSpacing: Dp, modifier: Modifier = Modifier) { DisposableEffect(Unit) { onDispose { viewModel.onHidden() } } val isInputEnabled: Boolean by viewModel.isInputEnabled.collectAsStateWithLifecycle() @@ -104,7 +100,7 @@ fun PinPad( columns = columns, verticalSpacing = verticalSpacing, horizontalSpacing = calculateHorizontalSpacingBetweenColumns(gridWidth = 300.dp), - modifier = modifier.focusRequester(focusRequester).sysuiResTag("pin_pad_grid") + modifier = modifier.focusRequester(focusRequester).sysuiResTag("pin_pad_grid"), ) { repeat(9) { index -> DigitButton( @@ -126,10 +122,11 @@ fun PinPad( ), isInputEnabled = isInputEnabled, onClicked = viewModel::onBackspaceButtonClicked, + onPointerDown = viewModel::onBackspaceButtonPressed, onLongPressed = viewModel::onBackspaceButtonLongPressed, appearance = backspaceButtonAppearance, scaling = buttonScaleAnimatables[9]::value, - elementId = "delete_button" + elementId = "delete_button", ) DigitButton( @@ -138,7 +135,7 @@ fun PinPad( onClicked = viewModel::onPinButtonClicked, scaling = buttonScaleAnimatables[10]::value, isAnimationEnabled = isDigitButtonAnimationEnabled, - onPointerDown = viewModel::onDigitButtonDown + onPointerDown = viewModel::onDigitButtonDown, ) ActionButton( @@ -152,7 +149,7 @@ fun PinPad( onClicked = viewModel::onAuthenticateButtonClicked, appearance = confirmButtonAppearance, scaling = buttonScaleAnimatables[11]::value, - elementId = "key_enter" + elementId = "key_enter", ) } } @@ -162,7 +159,7 @@ private fun DigitButton( digit: Int, isInputEnabled: Boolean, onClicked: (Int) -> Unit, - onPointerDown: () -> Unit, + onPointerDown: (View?) -> Unit, scaling: () -> Float, isAnimationEnabled: Boolean, ) { @@ -178,7 +175,7 @@ private fun DigitButton( val scale = if (isAnimationEnabled) scaling() else 1f scaleX = scale scaleY = scale - } + }, ) { contentColor -> // TODO(b/281878426): once "color: () -> Color" (added to BasicText in aosp/2568972) makes // it into Text, use that here, to animate more efficiently. @@ -197,6 +194,7 @@ private fun ActionButton( onClicked: () -> Unit, elementId: String, onLongPressed: (() -> Unit)? = null, + onPointerDown: ((View?) -> Unit)? = null, appearance: ActionButtonAppearance, scaling: () -> Float, ) { @@ -222,18 +220,16 @@ private fun ActionButton( foregroundColor = foregroundColor, isAnimationEnabled = true, elementId = elementId, + onPointerDown = onPointerDown, modifier = Modifier.graphicsLayer { alpha = hiddenAlpha val scale = scaling() scaleX = scale scaleY = scale - } + }, ) { contentColor -> - Icon( - icon = icon, - tint = contentColor(), - ) + Icon(icon = icon, tint = contentColor()) } } @@ -247,22 +243,13 @@ private fun PinPadButton( modifier: Modifier = Modifier, elementId: String? = null, onLongPressed: (() -> Unit)? = null, - onPointerDown: (() -> Unit)? = null, + onPointerDown: ((View?) -> Unit)? = null, content: @Composable (contentColor: () -> Color) -> Unit, ) { val interactionSource = remember { MutableInteractionSource() } val isPressed by interactionSource.collectIsPressedAsState() val indication = LocalIndication.current.takeUnless { isPressed } - val view = LocalView.current - LaunchedEffect(isPressed) { - if (isPressed) { - view.performHapticFeedback( - HapticFeedbackConstants.VIRTUAL_KEY, - HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING, - ) - } - } // Pin button animation specification is asymmetric: fast animation to the pressed state, and a // slow animation upon release. Note that isPressed is guaranteed to be true for at least the @@ -277,7 +264,7 @@ private fun PinPadButton( animateDpAsState( if (isAnimationEnabled && isPressed) 24.dp else pinButtonMaxSize / 2, label = "PinButton round corners", - animationSpec = tween(animDurationMillis, easing = animEasing) + animationSpec = tween(animDurationMillis, easing = animEasing), ) val colorAnimationSpec: AnimationSpec<Color> = tween(animDurationMillis, easing = animEasing) val containerColor: Color by @@ -287,7 +274,7 @@ private fun PinPadButton( else -> backgroundColor }, label = "Pin button container color", - animationSpec = colorAnimationSpec + animationSpec = colorAnimationSpec, ) val contentColor = animateColorAsState( @@ -296,7 +283,7 @@ private fun PinPadButton( else -> foregroundColor }, label = "Pin button container color", - animationSpec = colorAnimationSpec + animationSpec = colorAnimationSpec, ) Box( @@ -319,11 +306,11 @@ private fun PinPadButton( interactionSource = interactionSource, indication = indication, onClick = onClicked, - onLongClick = onLongPressed + onLongClick = onLongPressed, ) .pointerInteropFilter { motionEvent -> if (motionEvent.action == MotionEvent.ACTION_DOWN) { - onPointerDown?.let { it() } + onPointerDown?.let { it(view) } } false } @@ -353,10 +340,7 @@ private suspend fun showFailureAnimation( animatable.animateTo( targetValue = 1f, animationSpec = - tween( - durationMillis = pinButtonErrorRevertMs, - easing = Easings.Legacy, - ), + tween(durationMillis = pinButtonErrorRevertMs, easing = Easings.Legacy), ) } } @@ -364,9 +348,7 @@ private suspend fun showFailureAnimation( } /** Returns the amount of horizontal spacing between columns, in dips. */ -private fun calculateHorizontalSpacingBetweenColumns( - gridWidth: Dp, -): Dp { +private fun calculateHorizontalSpacingBetweenColumns(gridWidth: Dp): Dp { return (gridWidth - (pinButtonMaxSize * columns)) / (columns - 1) } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/ScreenDecorProvider.kt b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/ScreenDecorProvider.kt index 296fc27ac0ff..dcf32b2bcda4 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/ScreenDecorProvider.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/ScreenDecorProvider.kt @@ -16,15 +16,10 @@ package com.android.systemui.common.ui.compose.windowinsets -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.asPaddingValues -import androidx.compose.foundation.layout.displayCutout -import androidx.compose.foundation.layout.systemBars import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue import androidx.compose.runtime.staticCompositionLocalOf -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -36,9 +31,6 @@ val LocalDisplayCutout = staticCompositionLocalOf { DisplayCutout() } /** The corner radius in px of the current display. */ val LocalScreenCornerRadius = staticCompositionLocalOf { 0.dp } -/** The screen height in px without accounting for any screen insets (cutouts, status/nav bars) */ -val LocalRawScreenHeight = staticCompositionLocalOf { 0f } - @Composable fun ScreenDecorProvider( displayCutout: StateFlow<DisplayCutout>, @@ -48,22 +40,9 @@ fun ScreenDecorProvider( val cutout by displayCutout.collectAsStateWithLifecycle() val screenCornerRadiusDp = with(LocalDensity.current) { screenCornerRadius.toDp() } - val density = LocalDensity.current - val navBarHeight = - with(density) { WindowInsets.systemBars.asPaddingValues().calculateBottomPadding().toPx() } - val statusBarHeight = WindowInsets.systemBars.asPaddingValues().calculateTopPadding() - val displayCutoutHeight = WindowInsets.displayCutout.asPaddingValues().calculateTopPadding() - val screenHeight = - with(density) { - (LocalConfiguration.current.screenHeightDp.dp + - maxOf(statusBarHeight, displayCutoutHeight)) - .toPx() - } + navBarHeight - CompositionLocalProvider( LocalScreenCornerRadius provides screenCornerRadiusDp, LocalDisplayCutout provides cutout, - LocalRawScreenHeight provides screenHeight, ) { content() } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt index 5f7b1adca6a0..f4d9e820ad8f 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt @@ -35,7 +35,6 @@ import com.android.systemui.media.controls.ui.controller.MediaCarouselController import com.android.systemui.media.controls.ui.view.MediaHost import com.android.systemui.res.R import com.android.systemui.util.animation.MeasurementInput -import kotlinx.coroutines.ExperimentalCoroutinesApi object MediaCarousel { object Elements { @@ -47,7 +46,6 @@ object MediaCarousel { } } -@ExperimentalCoroutinesApi @Composable fun SceneScope.MediaCarousel( isVisible: Boolean, @@ -79,7 +77,7 @@ fun SceneScope.MediaCarousel( offsetProvider?.invoke() ?: IntOffset.Zero ) } - } + }, ) .layout { measurable, constraints -> val placeable = measurable.measure(constraints) @@ -89,7 +87,7 @@ fun SceneScope.MediaCarousel( MeasurementInput(placeable.width, placeable.height) carouselController.setSceneContainerSize( placeable.width, - placeable.height + placeable.height, ) layout(placeable.width, placeable.height) { @@ -106,7 +104,7 @@ fun SceneScope.MediaCarousel( } }, update = { it.setView(carouselController.mediaFrame) }, - onRelease = { it.removeAllViews() } + onRelease = { it.removeAllViews() }, ) } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt index 897a8613263f..a2ae8bbf66e4 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt @@ -24,9 +24,11 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.dp import com.android.compose.nestedscroll.PriorityNestedScrollConnection -import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight import kotlin.math.max import kotlin.math.roundToInt import kotlin.math.tanh @@ -36,9 +38,10 @@ import kotlinx.coroutines.launch @Composable fun Modifier.stackVerticalOverscroll( coroutineScope: CoroutineScope, - canScrollForward: () -> Boolean + canScrollForward: () -> Boolean, ): Modifier { - val screenHeight = LocalRawScreenHeight.current + val screenHeight = + with(LocalDensity.current) { LocalConfiguration.current.screenHeightDp.dp.toPx() } val overscrollOffset = remember { Animatable(0f) } val stackNestedScrollConnection = remember { NotificationStackNestedScrollConnection( @@ -60,10 +63,10 @@ fun Modifier.stackVerticalOverscroll( overscrollOffset.animateTo( targetValue = 0f, initialVelocity = velocityAvailable, - animationSpec = tween() + animationSpec = tween(), ) } - } + }, ) } 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 91ecfc18a76e..1b99a9644575 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 @@ -19,6 +19,7 @@ package com.android.systemui.notifications.ui.composable import android.util.Log import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.AnimationVector1D import androidx.compose.animation.core.tween import androidx.compose.foundation.ScrollState import androidx.compose.foundation.background @@ -29,6 +30,8 @@ import androidx.compose.foundation.gestures.rememberScrollableState import androidx.compose.foundation.gestures.scrollBy import androidx.compose.foundation.gestures.scrollable import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.absoluteOffset @@ -36,9 +39,11 @@ import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.imeAnimationTarget import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.layout.windowInsetsBottomHeight import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme @@ -68,6 +73,7 @@ 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 import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.unit.Dp @@ -81,7 +87,6 @@ import com.android.compose.animation.scene.LowestZIndexContentPicker import com.android.compose.animation.scene.NestedScrollBehavior import com.android.compose.animation.scene.SceneScope import com.android.compose.modifiers.thenIf -import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight import com.android.systemui.common.ui.compose.windowinsets.LocalScreenCornerRadius import com.android.systemui.res.R import com.android.systemui.scene.session.ui.composable.SaveableSession @@ -96,6 +101,7 @@ import com.android.systemui.statusbar.notification.stack.ui.viewmodel.Notificati import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel import kotlin.math.roundToInt +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch object Notifications { @@ -171,7 +177,7 @@ fun SceneScope.SnoozeableHeadsUpNotificationSpace( setCurrent = { scrollOffset = it }, min = minScrollOffset, max = maxScrollOffset, - delta + delta, ) } @@ -209,8 +215,8 @@ fun SceneScope.SnoozeableHeadsUpNotificationSpace( calculateHeadsUpPlaceholderYOffset( scrollOffset.roundToInt(), minScrollOffset.roundToInt(), - stackScrollView.topHeadsUpHeight - ) + stackScrollView.topHeadsUpHeight, + ), ) } .thenIf(isHeadsUp) { @@ -218,11 +224,8 @@ fun SceneScope.SnoozeableHeadsUpNotificationSpace( bottomBehavior = NestedScrollBehavior.EdgeAlways ) .nestedScroll(nestedScrollConnection) - .scrollable( - orientation = Orientation.Vertical, - state = scrollableState, - ) - } + .scrollable(orientation = Orientation.Vertical, state = scrollableState) + }, ) } @@ -259,6 +262,7 @@ fun SceneScope.ConstrainedNotificationStack( * Adds the space where notification stack should appear in the scene, with a scrim and nested * scrolling. */ +@OptIn(ExperimentalLayoutApi::class) @Composable fun SceneScope.NotificationScrollingStack( shadeSession: SaveableSession, @@ -291,7 +295,7 @@ fun SceneScope.NotificationScrollingStack( val navBarHeight = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding() val bottomPadding = if (shouldReserveSpaceForNavBar) navBarHeight else 0.dp - val screenHeight = LocalRawScreenHeight.current + val screenHeight = with(density) { LocalConfiguration.current.screenHeightDp.dp.toPx() } /** * The height in px of the contents of notification stack. Depending on the number of @@ -325,6 +329,14 @@ fun SceneScope.NotificationScrollingStack( screenHeight - maxScrimTop() - with(density) { navBarHeight.toPx() } } + val isRemoteInputActive by viewModel.isRemoteInputActive.collectAsStateWithLifecycle(false) + + // The bottom Y bound of the currently focused remote input notification. + val remoteInputRowBottom by viewModel.remoteInputRowBottomBound.collectAsStateWithLifecycle(0f) + + // The top y bound of the IME. + val imeTop = remember { mutableFloatStateOf(0f) } + // we are not scrolled to the top unless the scrim is at its maximum offset. LaunchedEffect(viewModel, scrimOffset) { snapshotFlow { scrimOffset.value >= 0f } @@ -342,15 +354,34 @@ fun SceneScope.NotificationScrollingStack( LaunchedEffect(syntheticScroll, scrimOffset, scrollState) { snapshotFlow { syntheticScroll.value } .collect { delta -> - val minOffset = minScrimOffset() - if (scrimOffset.value > minOffset) { - val remainingDelta = (minOffset - (scrimOffset.value - delta)).coerceAtLeast(0f) - scrimOffset.snapTo((scrimOffset.value - delta).coerceAtLeast(minOffset)) - if (remainingDelta > 0f) { - scrollState.scrollBy(remainingDelta) - } - } else { - scrollState.scrollTo(delta.roundToInt()) + scrollNotificationStack( + scope = coroutineScope, + delta = delta, + animate = false, + scrimOffset = scrimOffset, + minScrimOffset = minScrimOffset, + scrollState = scrollState, + ) + } + } + + // if remote input state changes, compare the row and IME's overlap and offset the scrim and + // placeholder accordingly. + LaunchedEffect(isRemoteInputActive, remoteInputRowBottom, imeTop) { + imeTop.floatValue = 0f + snapshotFlow { imeTop.floatValue } + .collect { imeTopValue -> + // only scroll the stack if ime value has been populated (ime placeholder has been + // composed at least once), and our remote input row overlaps with the ime bounds. + if (isRemoteInputActive && imeTopValue > 0f && remoteInputRowBottom > imeTopValue) { + scrollNotificationStack( + scope = coroutineScope, + delta = remoteInputRowBottom - imeTopValue, + animate = true, + scrimOffset = scrimOffset, + minScrimOffset = minScrimOffset, + scrollState = scrollState, + ) } } } @@ -394,12 +425,12 @@ fun SceneScope.NotificationScrollingStack( scrimOffset.value < 0 && layoutState.isTransitioning( from = Scenes.Shade, - to = Scenes.QuickSettings + to = Scenes.QuickSettings, ) ) { IntOffset( x = 0, - y = (scrimOffset.value * (1 - shadeToQsFraction)).roundToInt() + y = (scrimOffset.value * (1 - shadeToQsFraction)).roundToInt(), ) } else { IntOffset(x = 0, y = scrimOffset.value.roundToInt()) @@ -458,13 +489,11 @@ fun SceneScope.NotificationScrollingStack( .thenIf(shouldFillMaxSize) { Modifier.fillMaxSize() } .debugBackground(viewModel, DEBUG_BOX_COLOR) ) { - NotificationPlaceholder( - stackScrollView = stackScrollView, - viewModel = viewModel, + Column( modifier = Modifier.verticalNestedScrollToScene( topBehavior = NestedScrollBehavior.EdgeWithPreview, - isExternalOverscrollGesture = { isCurrentGestureOverscroll.value } + isExternalOverscrollGesture = { isCurrentGestureOverscroll.value }, ) .thenIf(shadeMode == ShadeMode.Single) { Modifier.nestedScroll(scrimNestedScrollConnection) @@ -473,18 +502,31 @@ fun SceneScope.NotificationScrollingStack( .verticalScroll(scrollState) .padding(top = topPadding) .fillMaxWidth() - .notificationStackHeight( - view = stackScrollView, - totalVerticalPadding = topPadding + bottomPadding, - ) - .onSizeChanged { size -> stackHeight.intValue = size.height }, - ) + ) { + NotificationPlaceholder( + stackScrollView = stackScrollView, + viewModel = viewModel, + modifier = + Modifier.notificationStackHeight( + view = stackScrollView, + totalVerticalPadding = topPadding + bottomPadding, + ) + .onSizeChanged { size -> stackHeight.intValue = size.height }, + ) + Spacer( + modifier = + Modifier.windowInsetsBottomHeight(WindowInsets.imeAnimationTarget) + .onGloballyPositioned { coordinates: LayoutCoordinates -> + imeTop.floatValue = screenHeight - coordinates.size.height + } + ) + } } if (shouldIncludeHeadsUpSpace) { HeadsUpNotificationSpace( stackScrollView = stackScrollView, viewModel = viewModel, - modifier = Modifier.padding(top = topPadding) + modifier = Modifier.padding(top = topPadding), ) } } @@ -572,6 +614,42 @@ private fun SceneScope.NotificationPlaceholder( ) } +private suspend fun scrollNotificationStack( + scope: CoroutineScope, + delta: Float, + animate: Boolean, + scrimOffset: Animatable<Float, AnimationVector1D>, + minScrimOffset: () -> Float, + scrollState: ScrollState, +) { + val minOffset = minScrimOffset() + if (scrimOffset.value > minOffset) { + val remainingDelta = + (minOffset - (scrimOffset.value - delta)).coerceAtLeast(0f).roundToInt() + if (remainingDelta > 0) { + if (animate) { + // launch a new coroutine for the remainder animation so that it doesn't suspend the + // scrim animation, allowing both to play simultaneously. + scope.launch { scrollState.animateScrollTo(remainingDelta) } + } else { + scrollState.scrollTo(remainingDelta) + } + } + val newScrimOffset = (scrimOffset.value - delta).coerceAtLeast(minOffset) + if (animate) { + scrimOffset.animateTo(newScrimOffset) + } else { + scrimOffset.snapTo(newScrimOffset) + } + } else { + if (animate) { + scrollState.animateScrollBy(delta) + } else { + scrollState.scrollBy(delta) + } + } +} + private fun calculateCornerRadius( scrimCornerRadius: Dp, screenCornerRadius: Dp, @@ -618,7 +696,7 @@ private fun consumeDeltaWithinRange( setCurrent: (Float) -> Unit, min: Float, max: Float, - delta: Float + delta: Float, ): Float { return if (delta < 0 && current > min) { val remainder = (current + delta - min).coerceAtMost(0f) @@ -631,10 +709,7 @@ private fun consumeDeltaWithinRange( } else 0f } -private inline fun debugLog( - viewModel: NotificationsPlaceholderViewModel, - msg: () -> Any, -) { +private inline fun debugLog(viewModel: NotificationsPlaceholderViewModel, msg: () -> Any) { if (viewModel.isDebugLoggingEnabled) { Log.d(TAG, msg().toString()) } 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 fa92bef34f38..d91958adaa1b 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 @@ -61,6 +61,7 @@ import androidx.compose.ui.graphics.CompositingStrategy import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.layout.Layout import androidx.compose.ui.layout.layoutId +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.colorResource @@ -79,7 +80,6 @@ import com.android.compose.windowsizeclass.LocalWindowSizeClass import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.common.ui.compose.windowinsets.CutoutLocation import com.android.systemui.common.ui.compose.windowinsets.LocalDisplayCutout -import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.dagger.SysUISingleton import com.android.systemui.lifecycle.ExclusiveActivatable @@ -229,17 +229,16 @@ private fun SceneScope.QuickSettingsScene( } .thenIf(cutoutLocation != CutoutLocation.CENTER) { Modifier.displayCutoutPadding() } ) { + val density = LocalDensity.current val isCustomizing by viewModel.qsSceneAdapter.isCustomizing.collectAsStateWithLifecycle() val isCustomizerShowing by viewModel.qsSceneAdapter.isCustomizerShowing.collectAsStateWithLifecycle() val customizingAnimationDuration by viewModel.qsSceneAdapter.customizerAnimationDuration.collectAsStateWithLifecycle() - val screenHeight = LocalRawScreenHeight.current + val screenHeight = with(density) { LocalConfiguration.current.screenHeightDp.dp.toPx() } BackHandler(enabled = isCustomizing) { viewModel.qsSceneAdapter.requestCloseCustomizer() } - val collapsedHeaderHeight = - with(LocalDensity.current) { ShadeHeader.Dimensions.CollapsedHeight.roundToPx() } val lifecycleOwner = LocalLifecycleOwner.current val footerActionsViewModel = remember(lifecycleOwner, viewModel) { @@ -268,7 +267,6 @@ private fun SceneScope.QuickSettingsScene( val navBarBottomHeight = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() - val density = LocalDensity.current val bottomPadding by animateDpAsState( targetValue = if (isCustomizing) 0.dp else navBarBottomHeight, @@ -394,7 +392,7 @@ private fun SceneScope.QuickSettingsScene( { mediaOffset.roundToPx() }, ) } - Box(modifier = Modifier.padding(horizontal = shadeHorizontalPadding)) { + Column(modifier = Modifier.padding(horizontal = shadeHorizontalPadding)) { if (mediaInRow) { Layout(content = content, measurePolicy = landscapeQsMediaMeasurePolicy) } else { diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt index b85523bc1694..6c4edf49fd83 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt @@ -18,6 +18,7 @@ package com.android.systemui.shade.ui.composable +import android.view.HapticFeedbackConstants import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box @@ -39,17 +40,20 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.platform.LocalView import androidx.compose.ui.unit.dp import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.LowestZIndexContentPicker import com.android.compose.animation.scene.SceneScope import com.android.compose.windowsizeclass.LocalWindowSizeClass +import com.android.systemui.scene.shared.model.Scenes /** Renders a lightweight shade UI container, as an overlay. */ @Composable @@ -58,6 +62,13 @@ fun SceneScope.OverlayShade( modifier: Modifier = Modifier, content: @Composable () -> Unit, ) { + val view = LocalView.current + LaunchedEffect(Unit) { + if (layoutState.currentTransition?.fromContent == Scenes.Gone) { + view.performHapticFeedback(HapticFeedbackConstants.GESTURE_START) + } + } + Box(modifier) { Scrim(onClicked = onScrimClicked) 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 fb9dde345251..0bb1d928c2b4 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 @@ -51,6 +51,7 @@ import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.Velocity import androidx.compose.ui.util.fastAll import androidx.compose.ui.util.fastAny +import androidx.compose.ui.util.fastFilter import androidx.compose.ui.util.fastFirstOrNull import androidx.compose.ui.util.fastSumBy import com.android.compose.ui.util.SpaceVectorConverter @@ -234,8 +235,15 @@ internal class MultiPointerDraggableNode( pointersDown == 0 -> { startedPosition = null - val lastPointerUp = changes.single { it.id == velocityPointerId } - velocityTracker.addPointerInputChange(lastPointerUp) + // In case of multiple events with 0 pointers down (not pressed) we may have + // already removed the velocityPointer + val lastPointerUp = changes.fastFilter { it.id == velocityPointerId } + check(lastPointerUp.isEmpty() || lastPointerUp.size == 1) { + "There are ${lastPointerUp.size} pointers up: $lastPointerUp" + } + if (lastPointerUp.size == 1) { + velocityTracker.addPointerInputChange(lastPointerUp.first()) + } } // The first pointer down, startedPosition was not set. diff --git a/packages/SystemUI/docs/scene.md b/packages/SystemUI/docs/scene.md index 0ac15c583b29..234c7a032d2e 100644 --- a/packages/SystemUI/docs/scene.md +++ b/packages/SystemUI/docs/scene.md @@ -68,15 +68,13 @@ file evalutes to `true`. 1. Set a collection of **aconfig flags** to `true` by running the following commands: ```console - $ adb shell device_config override systemui com.android.systemui.scene_container true - $ adb shell device_config override systemui com.android.systemui.compose_lockscreen true $ adb shell device_config override systemui com.android.systemui.keyguard_bottom_area_refactor true $ adb shell device_config override systemui com.android.systemui.keyguard_wm_state_refactor true - $ adb shell device_config override systemui com.android.systemui.media_in_scene_container true $ adb shell device_config override systemui com.android.systemui.migrate_clocks_to_blueprint true - $ adb shell device_config override systemui com.android.systemui.notifications_heads_up_refactor true + $ adb shell device_config override systemui com.android.systemui.notification_avalanche_throttle_hun true $ adb shell device_config override systemui com.android.systemui.predictive_back_sysui true $ adb shell device_config override systemui com.android.systemui.device_entry_udfps_refactor true + $ adb shell device_config override systemui com.android.systemui.scene_container true ``` 2. **Restart** System UI by issuing the following command: ```console diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java index 156e06843d15..312e62d0b624 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerTest.java @@ -196,6 +196,28 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { } @Test + public void testUserSwitcherToOneHandedRemovesViews() { + // Can happen when a SIM is inserted into a large screen device + initMode(MODE_USER_SWITCHER); + { + View view1 = mKeyguardSecurityContainer.findViewById( + R.id.keyguard_bouncer_user_switcher); + View view2 = mKeyguardSecurityContainer.findViewById(R.id.user_switcher_header); + assertThat(view1).isNotNull(); + assertThat(view2).isNotNull(); + } + + initMode(MODE_ONE_HANDED); + { + View view1 = mKeyguardSecurityContainer.findViewById( + R.id.keyguard_bouncer_user_switcher); + View view2 = mKeyguardSecurityContainer.findViewById(R.id.user_switcher_header); + assertThat(view1).isNull(); + assertThat(view2).isNull(); + } + } + + @Test public void updatePosition_movesKeyguard() { setupForUpdateKeyguardPosition(/* oneHandedMode= */ true); mKeyguardSecurityContainer.updatePositionByTouchX( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt index deef65218c4b..9552564cf1a2 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt @@ -16,18 +16,26 @@ package com.android.systemui.bouncer.ui.viewmodel +import android.platform.test.annotations.EnableFlags import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.keyguard.AuthInteractionProperties +import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository 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.haptics.msdl.bouncerHapticPlayer +import com.android.systemui.haptics.msdl.fakeMSDLPlayer import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.testKosmos +import com.google.android.msdl.data.model.MSDLToken import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -39,11 +47,15 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope + private val msdlPlayer = kosmos.fakeMSDLPlayer + private val bouncerHapticPlayer = kosmos.bouncerHapticPlayer + private val authInteractionProperties = AuthInteractionProperties() private val underTest = kosmos.pinBouncerViewModelFactory.create( isInputEnabled = MutableStateFlow(true), onIntentionalUserInput = {}, authenticationMethod = AuthenticationMethodModel.Pin, + bouncerHapticPlayer = bouncerHapticPlayer, ) @Before @@ -77,4 +89,42 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { underTest.onAuthenticateButtonClicked() assertThat(animateFailure).isFalse() } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + @EnableFlags(Flags.FLAG_MSDL_FEEDBACK) + fun onAuthenticationResult_playUnlockTokenIfSuccessful() = + testScope.runTest { + kosmos.fakeAuthenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin + ) + // Correct PIN: + FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit -> + underTest.onPinButtonClicked(digit) + } + underTest.onAuthenticateButtonClicked() + runCurrent() + + assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.UNLOCK) + assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties) + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + @EnableFlags(Flags.FLAG_MSDL_FEEDBACK) + fun onAuthenticationResult_playFailureTokenIfFailure() = + testScope.runTest { + kosmos.fakeAuthenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin + ) + // Wrong PIN: + FakeAuthenticationRepository.DEFAULT_PIN.drop(2).forEach { digit -> + underTest.onPinButtonClicked(digit) + } + underTest.onAuthenticateButtonClicked() + runCurrent() + + assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.FAILURE) + assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt index 7c773a902367..c163c6fc0a30 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt @@ -16,9 +16,11 @@ package com.android.systemui.bouncer.ui.viewmodel +import android.platform.test.annotations.EnableFlags import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.SceneKey +import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.data.repository.authenticationRepository @@ -27,12 +29,16 @@ import com.android.systemui.authentication.domain.interactor.authenticationInter import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate as Point import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.haptics.msdl.FakeMSDLPlayer +import com.android.systemui.haptics.msdl.bouncerHapticPlayer +import com.android.systemui.haptics.msdl.fakeMSDLPlayer import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.testKosmos +import com.google.android.msdl.data.model.MSDLToken import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -55,10 +61,13 @@ class PatternBouncerViewModelTest : SysuiTestCase() { private val authenticationInteractor by lazy { kosmos.authenticationInteractor } private val sceneInteractor by lazy { kosmos.sceneInteractor } private val bouncerViewModel by lazy { kosmos.bouncerSceneContentViewModel } + private val msdlPlayer: FakeMSDLPlayer = kosmos.fakeMSDLPlayer + private val bouncerHapticHelper = kosmos.bouncerHapticPlayer private val underTest = kosmos.patternBouncerViewModelFactory.create( isInputEnabled = MutableStateFlow(true).asStateFlow(), onIntentionalUserInput = {}, + bouncerHapticPlayer = bouncerHapticHelper, ) private val containerSize = 90 // px @@ -115,10 +124,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() { .that(selectedDots) .isEqualTo( CORRECT_PATTERN.subList(0, index + 1).map { - PatternDotViewModel( - x = it.x, - y = it.y, - ) + PatternDotViewModel(x = it.x, y = it.y) } ) assertWithMessage("Wrong current dot for index $index") @@ -174,7 +180,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() { listOf( PatternDotViewModel(0, 0), PatternDotViewModel(1, 0), - PatternDotViewModel(2, 0) + PatternDotViewModel(2, 0), ) ) } @@ -200,7 +206,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() { listOf( PatternDotViewModel(1, 0), PatternDotViewModel(1, 1), - PatternDotViewModel(1, 2) + PatternDotViewModel(1, 2), ) ) } @@ -228,7 +234,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() { listOf( PatternDotViewModel(2, 0), PatternDotViewModel(1, 1), - PatternDotViewModel(0, 2) + PatternDotViewModel(0, 2), ) ) } @@ -300,10 +306,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() { val attempts = FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT + 1 repeat(attempts) { attempt -> underTest.onDragStart() - CORRECT_PATTERN.subList( - 0, - kosmos.authenticationRepository.minPatternLength - 1, - ) + CORRECT_PATTERN.subList(0, kosmos.authenticationRepository.minPatternLength - 1) .forEach { coordinate -> underTest.onDrag( xPx = 30f * coordinate.x + 15, @@ -341,6 +344,16 @@ class PatternBouncerViewModelTest : SysuiTestCase() { assertThat(authResult).isTrue() } + @Test + @EnableFlags(Flags.FLAG_MSDL_FEEDBACK) + fun performDotFeedback_deliversDragToken() = + testScope.runTest { + underTest.performDotFeedback(null) + + assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.DRAG_INDICATOR) + assertThat(msdlPlayer.latestPropertiesPlayed).isNull() + } + private fun dragOverCoordinates(vararg coordinatesDragged: Point) { underTest.onDragStart() coordinatesDragged.forEach(::dragToCoordinate) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt index 2ee4aee2abab..af5f2acb444d 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt @@ -27,6 +27,7 @@ import androidx.compose.ui.input.key.KeyEventType import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.SceneKey +import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository @@ -35,12 +36,15 @@ import com.android.systemui.authentication.shared.model.AuthenticationMethodMode import com.android.systemui.bouncer.data.repository.fakeSimBouncerRepository import com.android.systemui.classifier.fakeFalsingCollector import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.haptics.msdl.bouncerHapticPlayer +import com.android.systemui.haptics.msdl.fakeMSDLPlayer import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.testKosmos +import com.google.android.msdl.data.model.MSDLToken import com.google.common.truth.Truth.assertThat import kotlin.random.Random import kotlin.random.nextInt @@ -64,11 +68,14 @@ class PinBouncerViewModelTest : SysuiTestCase() { private val testScope = kosmos.testScope private val sceneInteractor by lazy { kosmos.sceneInteractor } private val authenticationInteractor by lazy { kosmos.authenticationInteractor } + private val msdlPlayer = kosmos.fakeMSDLPlayer + private val bouncerHapticPlayer = kosmos.bouncerHapticPlayer private val underTest by lazy { kosmos.pinBouncerViewModelFactory.create( isInputEnabled = MutableStateFlow(true), onIntentionalUserInput = {}, authenticationMethod = AuthenticationMethodModel.Pin, + bouncerHapticPlayer = bouncerHapticPlayer, ) } @@ -97,6 +104,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { isInputEnabled = MutableStateFlow(true), onIntentionalUserInput = {}, authenticationMethod = AuthenticationMethodModel.Sim, + bouncerHapticPlayer = bouncerHapticPlayer, ) assertThat(underTest.isSimAreaVisible).isTrue() @@ -122,6 +130,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { isInputEnabled = MutableStateFlow(true), onIntentionalUserInput = {}, authenticationMethod = AuthenticationMethodModel.Pin, + bouncerHapticPlayer = bouncerHapticPlayer, ) kosmos.fakeAuthenticationRepository.setAutoConfirmFeatureEnabled(true) val hintedPinLength by collectLastValue(underTest.hintedPinLength) @@ -487,11 +496,39 @@ class PinBouncerViewModelTest : SysuiTestCase() { testScope.runTest { lockDeviceAndOpenPinBouncer() - underTest.onDigitButtonDown() + underTest.onDigitButtonDown(null) assertTrue(kosmos.fakeFalsingCollector.wasLastGestureAvoided()) } + @Test + @EnableFlags(Flags.FLAG_MSDL_FEEDBACK) + fun onDigiButtonDown_deliversKeyStandardToken() = + testScope.runTest { + underTest.onDigitButtonDown(null) + + assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.KEYPRESS_STANDARD) + assertThat(msdlPlayer.latestPropertiesPlayed).isNull() + } + + @Test + @EnableFlags(Flags.FLAG_MSDL_FEEDBACK) + fun onBackspaceButtonPressed_deliversKeyDeleteToken() { + underTest.onBackspaceButtonPressed(null) + + assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.KEYPRESS_DELETE) + assertThat(msdlPlayer.latestPropertiesPlayed).isNull() + } + + @Test + @EnableFlags(Flags.FLAG_MSDL_FEEDBACK) + fun onBackspaceButtonLongPressed_deliversLongPressToken() { + underTest.onBackspaceButtonLongPressed() + + assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.LONG_PRESS) + assertThat(msdlPlayer.latestPropertiesPlayed).isNull() + } + private fun TestScope.switchToScene(toScene: SceneKey) { val currentScene by collectLastValue(sceneInteractor.currentScene) val bouncerHidden = currentScene == Scenes.Bouncer && toScene != Scenes.Bouncer diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java index 956c12916c98..2028d28804bd 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java @@ -25,6 +25,8 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.view.MotionEvent; import android.view.accessibility.AccessibilityManager; @@ -33,6 +35,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.testing.FakeMetricsLogger; +import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -201,6 +204,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { } @Test + @DisableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING) public void testTrackpadGesture() { assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue(); when(mFalsingDataProvider.isFromTrackpad()).thenReturn(true); @@ -208,6 +212,14 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { } @Test + @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING) + public void testTrackpadGesture_touchScreenSource_false() { + assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue(); + when(mFalsingDataProvider.isTouchScreenSource()).thenReturn(false); + assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isFalse(); + } + + @Test public void testAddAndRemoveFalsingBeliefListener() { verify(mHistoryTracker, never()).addBeliefListener(any()); diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java index df4b0480f5c7..5a4799cecae5 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java @@ -312,6 +312,7 @@ public class FalsingDataProviderTest extends ClassifierTest { } @Test + @DisableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING) public void test_IsFromTrackpad() { MotionEvent motionEventOrigin = appendTrackpadDownEvent(0, 0); diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt index 70529cc762e0..ee65fbd810ae 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt @@ -21,6 +21,8 @@ import android.platform.test.annotations.EnableFlags import android.provider.Settings import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.internal.logging.uiEventLogger +import com.android.internal.logging.uiEventLoggerFake import com.android.systemui.Flags.FLAG_COMMUNAL_HUB import com.android.systemui.Flags.FLAG_COMMUNAL_SCENE_KTF_REFACTOR import com.android.systemui.SysuiTestCase @@ -28,6 +30,7 @@ import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.communal.domain.interactor.communalSettingsInteractor import com.android.systemui.communal.domain.interactor.setCommunalAvailable +import com.android.systemui.communal.shared.log.CommunalUiEvent import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.communal.shared.model.EditModeState import com.android.systemui.coroutines.collectLastValue @@ -35,7 +38,6 @@ import com.android.systemui.dock.dockManager import com.android.systemui.dock.fakeDockManager import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED import com.android.systemui.flags.fakeFeatureFlagsClassic -import com.android.systemui.flags.featureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.keyguardInteractor @@ -93,6 +95,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { bgScope = applicationCoroutineScope, mainDispatcher = testDispatcher, centralSurfacesOpt = centralSurfacesOptional, + uiEventLogger = uiEventLoggerFake, ) .apply { start() } @@ -119,7 +122,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.PRIMARY_BOUNCER, to = KeyguardState.GONE, - testScope = this + testScope = this, ) assertThat(scene).isEqualTo(CommunalScenes.Communal) @@ -140,7 +143,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.PRIMARY_BOUNCER, to = KeyguardState.GONE, - testScope = this + testScope = this, ) assertThat(scene).isEqualTo(CommunalScenes.Communal) @@ -161,7 +164,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.PRIMARY_BOUNCER, to = KeyguardState.GONE, - testScope = this + testScope = this, ) assertThat(scene).isEqualTo(CommunalScenes.Blank) @@ -181,7 +184,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.ALTERNATE_BOUNCER, to = KeyguardState.GONE, - testScope = this + testScope = this, ) // Scene change will be handled in EditWidgetsActivity not here assertThat(scene).isEqualTo(CommunalScenes.Communal) @@ -200,7 +203,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.GONE, to = KeyguardState.LOCKSCREEN, - testScope = this + testScope = this, ) assertThat(scene).isEqualTo(CommunalScenes.Communal) } @@ -220,7 +223,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.OCCLUDED, - testScope = this + testScope = this, ) assertThat(scene).isEqualTo(CommunalScenes.Blank) } @@ -240,7 +243,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.OCCLUDED, - testScope = this + testScope = this, ) assertThat(scene).isEqualTo(CommunalScenes.Communal) } @@ -258,7 +261,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.LOCKSCREEN, - testScope = this + testScope = this, ) assertThat(scene).isEqualTo(CommunalScenes.Blank) } @@ -276,7 +279,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.OFF, - testScope = this + testScope = this, ) assertThat(scene).isEqualTo(CommunalScenes.Communal) @@ -298,7 +301,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.OFF, - testScope = this + testScope = this, ) assertThat(scene).isEqualTo(CommunalScenes.Communal) advanceTimeBy(CommunalSceneStartable.AWAKE_DEBOUNCE_DELAY / 2) @@ -307,7 +310,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.OFF, to = KeyguardState.GLANCEABLE_HUB, - testScope = this + testScope = this, ) advanceTimeBy(CommunalSceneStartable.AWAKE_DEBOUNCE_DELAY) @@ -327,7 +330,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.LOCKSCREEN, - testScope = this + testScope = this, ) updateDocked(true) @@ -349,7 +352,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.LOCKSCREEN, - testScope = this + testScope = this, ) updateDocked(true) @@ -361,7 +364,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.DREAMING, - testScope = this + testScope = this, ) advanceTimeBy(CommunalSceneStartable.DOCK_DEBOUNCE_DELAY) assertThat(scene).isEqualTo(CommunalScenes.Blank) @@ -511,6 +514,9 @@ class CommunalSceneStartableTest : SysuiTestCase() { advanceTimeBy(SCREEN_TIMEOUT.milliseconds) assertThat(scene).isEqualTo(CommunalScenes.Blank) + assertThat(uiEventLoggerFake.logs.first().eventId) + .isEqualTo(CommunalUiEvent.COMMUNAL_HUB_TIMEOUT.id) + assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1) } } @@ -526,7 +532,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.DOZING, to = KeyguardState.GLANCEABLE_HUB, - testScope = this + testScope = this, ) assertThat(scene).isEqualTo(CommunalScenes.Communal) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorTest.kt index c2acc5ff6689..160865d625f5 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorTest.kt @@ -31,8 +31,11 @@ import com.android.systemui.flags.fakeSystemPropertiesHelper import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeTrustRepository +import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.AuthenticationFlags +import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest @@ -211,7 +214,7 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() { val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus) kosmos.fakeUserRepository.setSelectedUserInfo( primaryUser, - SelectionStatus.SELECTION_COMPLETE + SelectionStatus.SELECTION_COMPLETE, ) kosmos.fakeTrustRepository.setCurrentUserTrusted(true) @@ -240,6 +243,49 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() { } @Test + fun deviceUnlockStatus_becomesUnlocked_whenFingerprintUnlocked_whileDeviceAsleepInAod() = + testScope.runTest { + val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus) + assertThat(deviceUnlockStatus?.isUnlocked).isFalse() + + kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.AOD, + testScope = this, + ) + kosmos.powerInteractor.setAsleepForTest() + runCurrent() + + assertThat(deviceUnlockStatus?.isUnlocked).isFalse() + + kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus( + SuccessFingerprintAuthenticationStatus(0, true) + ) + runCurrent() + assertThat(deviceUnlockStatus?.isUnlocked).isTrue() + } + + @Test + fun deviceUnlockStatus_staysLocked_whenFingerprintUnlocked_whileDeviceAsleep() = + testScope.runTest { + val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus) + assertThat(deviceUnlockStatus?.isUnlocked).isFalse() + assertThat(kosmos.keyguardTransitionInteractor.getCurrentState()) + .isEqualTo(KeyguardState.LOCKSCREEN) + + kosmos.powerInteractor.setAsleepForTest() + runCurrent() + + assertThat(deviceUnlockStatus?.isUnlocked).isFalse() + + kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus( + SuccessFingerprintAuthenticationStatus(0, true) + ) + runCurrent() + assertThat(deviceUnlockStatus?.isUnlocked).isFalse() + } + + @Test fun deviceEntryRestrictionReason_whenFaceOrFingerprintOrTrust_alwaysNull() = testScope.runTest { kosmos.fakeBiometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(false) @@ -273,7 +319,7 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() { LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN to DeviceEntryRestrictionReason.UserLockdown, LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW to - DeviceEntryRestrictionReason.PolicyLockdown + DeviceEntryRestrictionReason.PolicyLockdown, ) } @@ -285,7 +331,7 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() { kosmos.fakeTrustRepository.setTrustUsuallyManaged(false) kosmos.fakeSystemPropertiesHelper.set( DeviceUnlockedInteractor.SYS_BOOT_REASON_PROP, - "not mainline reboot" + "not mainline reboot", ) runCurrent() @@ -321,7 +367,7 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() { kosmos.fakeTrustRepository.setTrustUsuallyManaged(false) kosmos.fakeSystemPropertiesHelper.set( DeviceUnlockedInteractor.SYS_BOOT_REASON_PROP, - "not mainline reboot" + "not mainline reboot", ) runCurrent() @@ -358,7 +404,7 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() { kosmos.fakeTrustRepository.setCurrentUserTrustManaged(false) kosmos.fakeSystemPropertiesHelper.set( DeviceUnlockedInteractor.SYS_BOOT_REASON_PROP, - "not mainline reboot" + "not mainline reboot", ) runCurrent() @@ -394,12 +440,12 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() { collectLastValue(underTest.deviceEntryRestrictionReason) kosmos.fakeSystemPropertiesHelper.set( DeviceUnlockedInteractor.SYS_BOOT_REASON_PROP, - DeviceUnlockedInteractor.REBOOT_MAINLINE_UPDATE + DeviceUnlockedInteractor.REBOOT_MAINLINE_UPDATE, ) kosmos.fakeBiometricSettingsRepository.setAuthenticationFlags( AuthenticationFlags( userId = 1, - flag = LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT + flag = LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT, ) ) runCurrent() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt index 50b727c3fed9..9cfd328a9484 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt @@ -25,6 +25,7 @@ import com.android.systemui.contextualeducation.GestureType.BACK import com.android.systemui.coroutines.collectLastValue import com.android.systemui.education.data.model.EduDeviceConnectionTime import com.android.systemui.education.data.model.GestureEduModel +import com.android.systemui.education.domain.interactor.mockEduInputManager import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope @@ -62,7 +63,13 @@ class ContextualEducationRepositoryTest : SysuiTestCase() { // Create TestContext here because TemporaryFolder.create() is called in @Before. It is // needed before calling TemporaryFolder.newFolder(). val testContext = TestContext(context, tmpFolder.newFolder()) - underTest = UserContextualEducationRepository(testContext, dsScopeProvider) + underTest = + UserContextualEducationRepository( + testContext, + dsScopeProvider, + kosmos.mockEduInputManager, + kosmos.testDispatcher + ) underTest.setUser(testUserId) } @@ -99,7 +106,8 @@ class ContextualEducationRepositoryTest : SysuiTestCase() { lastShortcutTriggeredTime = kosmos.fakeEduClock.instant(), lastEducationTime = kosmos.fakeEduClock.instant(), usageSessionStartTime = kosmos.fakeEduClock.instant(), - userId = testUserId + userId = testUserId, + gestureType = BACK ) underTest.updateGestureEduModel(BACK) { newModel } val model by collectLastValue(underTest.readGestureEduModelFlow(BACK)) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt index 64915fbf551f..8201bbe4dc47 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt @@ -17,15 +17,13 @@ package com.android.systemui.education.domain.interactor import android.content.pm.UserInfo -import android.hardware.input.InputManager -import android.hardware.input.KeyGestureEvent -import android.view.KeyEvent -import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.contextualeducation.GestureType import com.android.systemui.contextualeducation.GestureType.ALL_APPS import com.android.systemui.contextualeducation.GestureType.BACK +import com.android.systemui.contextualeducation.GestureType.HOME +import com.android.systemui.contextualeducation.GestureType.OVERVIEW import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.education.data.model.GestureEduModel @@ -40,20 +38,21 @@ import com.android.systemui.user.data.repository.fakeUserRepository import com.google.common.truth.Truth.assertThat import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.launch import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest +import org.junit.Assume.assumeTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentCaptor -import org.mockito.kotlin.any -import org.mockito.kotlin.verify +import platform.test.runner.parameterized.ParameterizedAndroidJunit4 +import platform.test.runner.parameterized.Parameters @SmallTest -@RunWith(AndroidJUnit4::class) +@RunWith(ParameterizedAndroidJunit4::class) @kotlinx.coroutines.ExperimentalCoroutinesApi -class KeyboardTouchpadEduInteractorTest : SysuiTestCase() { +class KeyboardTouchpadEduInteractorTest(private val gestureType: GestureType) : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private val contextualEduInteractor = kosmos.contextualEducationInteractor @@ -71,21 +70,27 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() { underTest.start() contextualEduInteractor.start() userRepository.setUserInfos(USER_INFOS) + testScope.launch { + contextualEduInteractor.updateKeyboardFirstConnectionTime() + contextualEduInteractor.updateTouchpadFirstConnectionTime() + } } @Test fun newEducationInfoOnMaxSignalCountReached() = testScope.runTest { - triggerMaxEducationSignals(BACK) + triggerMaxEducationSignals(gestureType) val model by collectLastValue(underTest.educationTriggered) - assertThat(model?.gestureType).isEqualTo(BACK) + + assertThat(model?.gestureType).isEqualTo(gestureType) } @Test fun newEducationToastOn1stEducation() = testScope.runTest { val model by collectLastValue(underTest.educationTriggered) - triggerMaxEducationSignals(BACK) + triggerMaxEducationSignals(gestureType) + assertThat(model?.educationUiType).isEqualTo(EducationUiType.Toast) } @@ -93,12 +98,12 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() { fun newEducationNotificationOn2ndEducation() = testScope.runTest { val model by collectLastValue(underTest.educationTriggered) - triggerMaxEducationSignals(BACK) + triggerMaxEducationSignals(gestureType) // runCurrent() to trigger 1st education runCurrent() eduClock.offset(minDurationForNextEdu) - triggerMaxEducationSignals(BACK) + triggerMaxEducationSignals(gestureType) assertThat(model?.educationUiType).isEqualTo(EducationUiType.Notification) } @@ -106,7 +111,7 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() { @Test fun noEducationInfoBeforeMaxSignalCountReached() = testScope.runTest { - contextualEduInteractor.incrementSignalCount(BACK) + contextualEduInteractor.incrementSignalCount(gestureType) val model by collectLastValue(underTest.educationTriggered) assertThat(model).isNull() } @@ -115,8 +120,8 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() { fun noEducationInfoWhenShortcutTriggeredPreviously() = testScope.runTest { val model by collectLastValue(underTest.educationTriggered) - contextualEduInteractor.updateShortcutTriggerTime(BACK) - triggerMaxEducationSignals(BACK) + contextualEduInteractor.updateShortcutTriggerTime(gestureType) + triggerMaxEducationSignals(gestureType) assertThat(model).isNull() } @@ -124,12 +129,12 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() { fun no2ndEducationBeforeMinEduIntervalReached() = testScope.runTest { val models by collectValues(underTest.educationTriggered) - triggerMaxEducationSignals(BACK) + triggerMaxEducationSignals(gestureType) runCurrent() // Offset a duration that is less than the required education interval eduClock.offset(1.seconds) - triggerMaxEducationSignals(BACK) + triggerMaxEducationSignals(gestureType) runCurrent() assertThat(models.filterNotNull().size).isEqualTo(1) @@ -140,15 +145,15 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() { testScope.runTest { val models by collectValues(underTest.educationTriggered) // Trigger 2 educations - triggerMaxEducationSignals(BACK) + triggerMaxEducationSignals(gestureType) runCurrent() eduClock.offset(minDurationForNextEdu) - triggerMaxEducationSignals(BACK) + triggerMaxEducationSignals(gestureType) runCurrent() // Try triggering 3rd education eduClock.offset(minDurationForNextEdu) - triggerMaxEducationSignals(BACK) + triggerMaxEducationSignals(gestureType) assertThat(models.filterNotNull().size).isEqualTo(2) } @@ -157,18 +162,21 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() { fun startNewUsageSessionWhen2ndSignalReceivedAfterSessionDeadline() = testScope.runTest { val model by - collectLastValue(kosmos.contextualEducationRepository.readGestureEduModelFlow(BACK)) - contextualEduInteractor.incrementSignalCount(BACK) + collectLastValue( + kosmos.contextualEducationRepository.readGestureEduModelFlow(gestureType) + ) + contextualEduInteractor.incrementSignalCount(gestureType) eduClock.offset(KeyboardTouchpadEduInteractor.usageSessionDuration.plus(1.seconds)) val secondSignalReceivedTime = eduClock.instant() - contextualEduInteractor.incrementSignalCount(BACK) + contextualEduInteractor.incrementSignalCount(gestureType) assertThat(model) .isEqualTo( GestureEduModel( signalCount = 1, usageSessionStartTime = secondSignalReceivedTime, - userId = 0 + userId = 0, + gestureType = gestureType ) ) } @@ -252,22 +260,9 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() { @Test fun updateShortcutTimeOnKeyboardShortcutTriggered() = testScope.runTest { - // runCurrent() to trigger inputManager#registerKeyGestureEventListener in the - // interactor - runCurrent() - val listenerCaptor = - ArgumentCaptor.forClass(InputManager.KeyGestureEventListener::class.java) - verify(kosmos.mockEduInputManager) - .registerKeyGestureEventListener(any(), listenerCaptor.capture()) - - val allAppsKeyGestureEvent = - KeyGestureEvent.Builder() - .setDeviceId(1) - .setModifierState(KeyEvent.META_META_ON) - .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS) - .setAction(KeyGestureEvent.ACTION_GESTURE_COMPLETE) - .build() - listenerCaptor.value.onKeyGestureEvent(allAppsKeyGestureEvent) + // Only All Apps needs to update the keyboard shortcut + assumeTrue(gestureType == ALL_APPS) + kosmos.contextualEducationRepository.setKeyboardShortcutTriggered(ALL_APPS) val model by collectLastValue( @@ -293,10 +288,18 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() { runCurrent() } + private suspend fun setUpForDeviceConnection() { + contextualEduInteractor.updateKeyboardFirstConnectionTime() + contextualEduInteractor.updateTouchpadFirstConnectionTime() + } + companion object { - private val USER_INFOS = - listOf( - UserInfo(101, "Second User", 0), - ) + private val USER_INFOS = listOf(UserInfo(101, "Second User", 0)) + + @JvmStatic + @Parameters(name = "{0}") + fun getGestureTypes(): List<GestureType> { + return listOf(BACK, HOME, OVERVIEW, ALL_APPS) + } } } 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 c4ac585f7e4a..ab33269ec954 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 @@ -37,6 +37,7 @@ import com.android.systemui.res.R import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.launch import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest @@ -69,6 +70,11 @@ class ContextualEduUiCoordinatorTest : SysuiTestCase() { @Before fun setUp() { + testScope.launch { + interactor.updateKeyboardFirstConnectionTime() + interactor.updateTouchpadFirstConnectionTime() + } + val viewModel = ContextualEduViewModel( kosmos.applicationContext.resources, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt index 686b518b56e0..366b55db4f20 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt @@ -23,6 +23,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityTransitionAnimator +import com.android.systemui.classifier.falsingManager import com.android.systemui.haptics.fakeVibratorHelper import com.android.systemui.kosmos.testScope import com.android.systemui.log.core.FakeLogBuffer @@ -68,11 +69,13 @@ class QSLongPressEffectTest : SysuiTestCase() { vibratorHelper.primitiveDurations[VibrationEffect.Composition.PRIMITIVE_SPIN] = spinDuration whenever(kosmos.keyguardStateController.isUnlocked).thenReturn(true) + kosmos.falsingManager.setFalseLongTap(false) longPressEffect = QSLongPressEffect( vibratorHelper, kosmos.keyguardStateController, + kosmos.falsingManager, FakeLogBuffer.Factory.create(), ) longPressEffect.callback = callback @@ -180,11 +183,7 @@ class QSLongPressEffectTest : SysuiTestCase() { // THEN the expected texture is played val reverseHaptics = - LongPressHapticBuilder.createReversedEffect( - progress, - lowTickDuration, - effectDuration, - ) + LongPressHapticBuilder.createReversedEffect(progress, lowTickDuration, effectDuration) assertThat(reverseHaptics).isNotNull() assertThat(vibratorHelper.hasVibratedWithEffects(reverseHaptics!!)).isTrue() } @@ -224,6 +223,20 @@ class QSLongPressEffectTest : SysuiTestCase() { } @Test + fun onAnimationComplete_isFalseLongClick_effectEndsInIdleWithReset() = + testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) { + // GIVEN that the long-click is false + kosmos.falsingManager.setFalseLongTap(true) + + // GIVEN that the animation completes + longPressEffect.handleAnimationComplete() + + // THEN the long-press effect ends in the idle state and the properties are reset + assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE) + verify(callback, times(1)).onResetProperties() + } + + @Test fun onAnimationComplete_whenRunningBackwardsFromUp_endsWithFinishedReversingAndClick() = testWhileInState(QSLongPressEffect.State.RUNNING_BACKWARDS_FROM_UP) { // GIVEN that the animation completes diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt index 0c716137f434..639737b37efd 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt @@ -25,6 +25,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues +import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger import com.android.systemui.inputdevice.tutorial.domain.interactor.KeyboardTouchpadConnectionInteractor import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD @@ -53,6 +54,7 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.mock +import org.mockito.kotlin.mock @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @@ -81,6 +83,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { Optional.of(kosmos.touchpadGesturesInteractor), KeyboardTouchpadConnectionInteractor(keyboardRepo, touchpadRepo), hasTouchpadTutorialScreens, + mock<InputDeviceTutorialLogger>(), SavedStateHandle(mapOf(INTENT_TUTORIAL_TYPE_KEY to startingPeripheral)) ) lifecycle.addObserver(viewModel) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt index 6c3c7ef0162d..fcf4662be145 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt @@ -16,7 +16,10 @@ */ package com.android.systemui.keyguard.data.quickaffordance +import android.app.Flags import android.net.Uri +import android.platform.test.annotations.DisableFlags +import android.platform.test.annotations.EnableFlags import android.provider.Settings import android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS import android.provider.Settings.Global.ZEN_MODE_OFF @@ -25,6 +28,7 @@ import android.provider.Settings.Secure.ZEN_DURATION_PROMPT import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.notification.modes.EnableZenModeDialog +import com.android.settingslib.notification.modes.TestModeBuilder import com.android.systemui.SysuiTestCase import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.ContentDescription @@ -35,7 +39,11 @@ import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.res.R import com.android.systemui.settings.UserTracker +import com.android.systemui.shared.settings.data.repository.secureSettingsRepository import com.android.systemui.statusbar.policy.ZenModeController +import com.android.systemui.statusbar.policy.data.repository.fakeDeviceProvisioningRepository +import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository +import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor import com.android.systemui.testKosmos import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.eq @@ -43,6 +51,7 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.android.systemui.util.settings.fakeSettings import com.google.common.truth.Truth.assertThat +import java.time.Duration import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest @@ -66,8 +75,13 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { private val kosmos = testKosmos() private val testDispatcher = kosmos.testDispatcher private val testScope = kosmos.testScope + private val settings = kosmos.fakeSettings + private val zenModeRepository = kosmos.fakeZenModeRepository + private val deviceProvisioningRepository = kosmos.fakeDeviceProvisioningRepository + private val secureSettingsRepository = kosmos.secureSettingsRepository + @Mock private lateinit var zenModeController: ZenModeController @Mock private lateinit var userTracker: UserTracker @Mock private lateinit var conditionUri: Uri @@ -85,17 +99,36 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { DoNotDisturbQuickAffordanceConfig( context, zenModeController, + kosmos.zenModeInteractor, settings, userTracker, testDispatcher, + testScope.backgroundScope, conditionUri, enableZenModeDialog, ) } @Test + @EnableFlags(Flags.FLAG_MODES_UI) fun dndNotAvailable_pickerStateHidden() = testScope.runTest { + deviceProvisioningRepository.setDeviceProvisioned(false) + runCurrent() + + val result = underTest.getPickerScreenState() + runCurrent() + + assertEquals( + KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice, + result, + ) + } + + @Test + @DisableFlags(Flags.FLAG_MODES_UI) + fun controllerDndNotAvailable_pickerStateHidden() = + testScope.runTest { // given whenever(zenModeController.isZenAvailable).thenReturn(false) @@ -105,13 +138,33 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { // then assertEquals( KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice, - result + result, ) } @Test + @EnableFlags(Flags.FLAG_MODES_UI) fun dndAvailable_pickerStateVisible() = testScope.runTest { + deviceProvisioningRepository.setDeviceProvisioned(true) + runCurrent() + + val result = underTest.getPickerScreenState() + runCurrent() + + assertThat(result) + .isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java) + val defaultPickerState = + result as KeyguardQuickAffordanceConfig.PickerScreenState.Default + assertThat(defaultPickerState.configureIntent).isNotNull() + assertThat(defaultPickerState.configureIntent?.action) + .isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS) + } + + @Test + @DisableFlags(Flags.FLAG_MODES_UI) + fun controllerDndAvailable_pickerStateVisible() = + testScope.runTest { // given whenever(zenModeController.isZenAvailable).thenReturn(true) @@ -129,7 +182,27 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun onTriggered_dndModeIsNotZEN_MODE_OFF_setToZEN_MODE_OFF() = + @EnableFlags(Flags.FLAG_MODES_UI) + fun onTriggered_dndModeIsNotOff_setToOff() = + testScope.runTest { + val currentModes by collectLastValue(zenModeRepository.modes) + + zenModeRepository.addMode(TestModeBuilder.MANUAL_DND_ACTIVE) + secureSettingsRepository.setInt(Settings.Secure.ZEN_DURATION, -2) + collectLastValue(underTest.lockScreenState) + runCurrent() + + val result = underTest.onTriggered(null) + runCurrent() + + val dndMode = currentModes!!.single() + assertThat(dndMode.isActive).isFalse() + assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result) + } + + @Test + @DisableFlags(Flags.FLAG_MODES_UI) + fun onTriggered_controllerDndModeIsNotZEN_MODE_OFF_setToZEN_MODE_OFF() = testScope.runTest { // given whenever(zenModeController.isZenAvailable).thenReturn(true) @@ -140,11 +213,12 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { // when val result = underTest.onTriggered(null) + verify(zenModeController) .setZen( spyZenMode.capture(), spyConditionId.capture(), - eq(DoNotDisturbQuickAffordanceConfig.TAG) + eq(DoNotDisturbQuickAffordanceConfig.TAG), ) // then @@ -154,7 +228,28 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun onTriggered_dndModeIsZEN_MODE_OFF_settingFOREVER_setZenWithoutCondition() = + @EnableFlags(Flags.FLAG_MODES_UI) + fun onTriggered_dndModeIsOff_settingFOREVER_setZenWithoutCondition() = + testScope.runTest { + val currentModes by collectLastValue(zenModeRepository.modes) + + zenModeRepository.addMode(TestModeBuilder.MANUAL_DND_INACTIVE) + secureSettingsRepository.setInt(Settings.Secure.ZEN_DURATION, ZEN_DURATION_FOREVER) + collectLastValue(underTest.lockScreenState) + runCurrent() + + val result = underTest.onTriggered(null) + runCurrent() + + val dndMode = currentModes!!.single() + assertThat(dndMode.isActive).isTrue() + assertThat(zenModeRepository.getModeActiveDuration(dndMode.id)).isNull() + assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result) + } + + @Test + @DisableFlags(Flags.FLAG_MODES_UI) + fun onTriggered_controllerDndModeIsZEN_MODE_OFF_settingFOREVER_setZenWithoutCondition() = testScope.runTest { // given whenever(zenModeController.isZenAvailable).thenReturn(true) @@ -169,7 +264,7 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { .setZen( spyZenMode.capture(), spyConditionId.capture(), - eq(DoNotDisturbQuickAffordanceConfig.TAG) + eq(DoNotDisturbQuickAffordanceConfig.TAG), ) // then @@ -179,7 +274,27 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun onTriggered_dndZEN_MODE_OFF_settingNotFOREVERorPROMPT_zenWithCondition() = + @EnableFlags(Flags.FLAG_MODES_UI) + fun onTriggered_dndModeIsOff_settingNotFOREVERorPROMPT_dndWithDuration() = + testScope.runTest { + val currentModes by collectLastValue(zenModeRepository.modes) + zenModeRepository.addMode(TestModeBuilder.MANUAL_DND_INACTIVE) + secureSettingsRepository.setInt(Settings.Secure.ZEN_DURATION, -900) + runCurrent() + + val result = underTest.onTriggered(null) + runCurrent() + + assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result) + val dndMode = currentModes!!.single() + assertThat(dndMode.isActive).isTrue() + assertThat(zenModeRepository.getModeActiveDuration(dndMode.id)) + .isEqualTo(Duration.ofMinutes(-900)) + } + + @Test + @DisableFlags(Flags.FLAG_MODES_UI) + fun onTriggered_controllerDndZEN_MODE_OFF_settingNotFOREVERorPROMPT_zenWithCondition() = testScope.runTest { // given whenever(zenModeController.isZenAvailable).thenReturn(true) @@ -194,7 +309,7 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { .setZen( spyZenMode.capture(), spyConditionId.capture(), - eq(DoNotDisturbQuickAffordanceConfig.TAG) + eq(DoNotDisturbQuickAffordanceConfig.TAG), ) // then @@ -204,7 +319,28 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun onTriggered_dndModeIsZEN_MODE_OFF_settingIsPROMPT_showDialog() = + @EnableFlags(Flags.FLAG_MODES_UI) + fun onTriggered_dndModeIsOff_settingIsPROMPT_showDialog() = + testScope.runTest { + val expandable: Expandable = mock() + zenModeRepository.addMode(TestModeBuilder.MANUAL_DND_INACTIVE) + secureSettingsRepository.setInt(Settings.Secure.ZEN_DURATION, ZEN_DURATION_PROMPT) + whenever(enableZenModeDialog.createDialog()).thenReturn(mock()) + collectLastValue(underTest.lockScreenState) + runCurrent() + + val result = underTest.onTriggered(expandable) + + assertTrue(result is KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog) + assertEquals( + expandable, + (result as KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog).expandable, + ) + } + + @Test + @DisableFlags(Flags.FLAG_MODES_UI) + fun onTriggered_controllerDndModeIsZEN_MODE_OFF_settingIsPROMPT_showDialog() = testScope.runTest { // given val expandable: Expandable = mock() @@ -222,13 +358,31 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { assertTrue(result is KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog) assertEquals( expandable, - (result as KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog).expandable + (result as KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog).expandable, ) } @Test + @EnableFlags(Flags.FLAG_MODES_UI) fun lockScreenState_dndAvailableStartsAsTrue_changeToFalse_StateIsHidden() = testScope.runTest { + deviceProvisioningRepository.setDeviceProvisioned(true) + val valueSnapshot = collectLastValue(underTest.lockScreenState) + val secondLastValue = valueSnapshot() + runCurrent() + + deviceProvisioningRepository.setDeviceProvisioned(false) + runCurrent() + val lastValue = valueSnapshot() + + assertTrue(secondLastValue is KeyguardQuickAffordanceConfig.LockScreenState.Visible) + assertTrue(lastValue is KeyguardQuickAffordanceConfig.LockScreenState.Hidden) + } + + @Test + @DisableFlags(Flags.FLAG_MODES_UI) + fun lockScreenState_controllerDndAvailableStartsAsTrue_changeToFalse_StateIsHidden() = + testScope.runTest { // given whenever(zenModeController.isZenAvailable).thenReturn(true) val callbackCaptor: ArgumentCaptor<ZenModeController.Callback> = argumentCaptor() @@ -246,7 +400,44 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { } @Test - fun lockScreenState_dndModeStartsAsZEN_MODE_OFF_changeToNotOFF_StateVisible() = + @EnableFlags(Flags.FLAG_MODES_UI) + fun lockScreenState_dndModeStartsAsOff_changeToOn_StateVisible() = + testScope.runTest { + val lockScreenState by collectLastValue(underTest.lockScreenState) + + zenModeRepository.addMode(TestModeBuilder.MANUAL_DND_INACTIVE) + runCurrent() + + assertThat(lockScreenState) + .isEqualTo( + KeyguardQuickAffordanceConfig.LockScreenState.Visible( + Icon.Resource( + R.drawable.qs_dnd_icon_off, + ContentDescription.Resource(R.string.dnd_is_off), + ), + ActivationState.Inactive, + ) + ) + + zenModeRepository.removeMode(TestModeBuilder.MANUAL_DND_INACTIVE.id) + zenModeRepository.addMode(TestModeBuilder.MANUAL_DND_ACTIVE) + runCurrent() + + assertThat(lockScreenState) + .isEqualTo( + KeyguardQuickAffordanceConfig.LockScreenState.Visible( + Icon.Resource( + R.drawable.qs_dnd_icon_on, + ContentDescription.Resource(R.string.dnd_is_on), + ), + ActivationState.Active, + ) + ) + } + + @Test + @DisableFlags(Flags.FLAG_MODES_UI) + fun lockScreenState_controllerDndModeStartsAsZEN_MODE_OFF_changeToNotOFF_StateVisible() = testScope.runTest { // given whenever(zenModeController.isZenAvailable).thenReturn(true) @@ -265,9 +456,9 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { KeyguardQuickAffordanceConfig.LockScreenState.Visible( Icon.Resource( R.drawable.qs_dnd_icon_off, - ContentDescription.Resource(R.string.dnd_is_off) + ContentDescription.Resource(R.string.dnd_is_off), ), - ActivationState.Inactive + ActivationState.Inactive, ), secondLastValue, ) @@ -275,9 +466,9 @@ class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() { KeyguardQuickAffordanceConfig.LockScreenState.Visible( Icon.Resource( R.drawable.qs_dnd_icon_on, - ContentDescription.Resource(R.string.dnd_is_on) + ContentDescription.Resource(R.string.dnd_is_on), ), - ActivationState.Active + ActivationState.Active, ), lastValue, ) 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 c18deb134075..fac931273ac7 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 @@ -14,22 +14,6 @@ * 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. - */ - package com.android.systemui.keyguard.domain.interactor import android.os.PowerManager @@ -47,7 +31,6 @@ import com.android.systemui.communal.data.repository.FakeCommunalSceneRepository import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository import com.android.systemui.communal.domain.interactor.setCommunalAvailable import com.android.systemui.communal.shared.model.CommunalScenes -import com.android.systemui.communal.shared.model.CommunalTransitionKeys import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository @@ -129,7 +112,7 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT transitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.DOZING, - testScope + testScope, ) kosmos.fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockMode.NONE) reset(transitionRepository) @@ -145,10 +128,7 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT // Under default conditions, we should transition to LOCKSCREEN when waking up. assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.DOZING, - to = KeyguardState.LOCKSCREEN, - ) + .startedTransition(from = KeyguardState.DOZING, to = KeyguardState.LOCKSCREEN) } @Test @@ -166,10 +146,7 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT // If dreaming is possible and communal is available, then we should transition to // GLANCEABLE_HUB when waking up due to power button press. assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.DOZING, - to = KeyguardState.GLANCEABLE_HUB, - ) + .startedTransition(from = KeyguardState.DOZING, to = KeyguardState.GLANCEABLE_HUB) } @Test @@ -186,8 +163,7 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT // If dreaming is possible and communal is available, then we should transition to // GLANCEABLE_HUB when waking up due to power button press. - verify(kosmos.fakeCommunalSceneRepository) - .changeScene(CommunalScenes.Communal, CommunalTransitionKeys.Immediately) + verify(kosmos.fakeCommunalSceneRepository).snapToScene(CommunalScenes.Communal) } @Test @@ -204,10 +180,7 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT // If dreaming is NOT possible but communal is available, then we should transition to // LOCKSCREEN when waking up due to power button press. assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.DOZING, - to = KeyguardState.LOCKSCREEN, - ) + .startedTransition(from = KeyguardState.DOZING, to = KeyguardState.LOCKSCREEN) } @Test @@ -224,10 +197,7 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT // If dreaming is possible but communal is NOT available, then we should transition to // LOCKSCREEN when waking up due to power button press. assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.DOZING, - to = KeyguardState.LOCKSCREEN, - ) + .startedTransition(from = KeyguardState.DOZING, to = KeyguardState.LOCKSCREEN) } @Test @@ -245,10 +215,7 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT // Under default conditions, we should transition to LOCKSCREEN when waking up. assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.DOZING, - to = KeyguardState.GLANCEABLE_HUB, - ) + .startedTransition(from = KeyguardState.DOZING, to = KeyguardState.GLANCEABLE_HUB) } @Test @@ -261,10 +228,7 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT // Waking with a SHOW_WHEN_LOCKED activity on top should transition to OCCLUDED. assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.DOZING, - to = KeyguardState.OCCLUDED, - ) + .startedTransition(from = KeyguardState.DOZING, to = KeyguardState.OCCLUDED) } @Test @@ -282,10 +246,7 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT // Waking with a SHOW_WHEN_LOCKED activity on top should transition to OCCLUDED. assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.DOZING, - to = KeyguardState.OCCLUDED, - ) + .startedTransition(from = KeyguardState.DOZING, to = KeyguardState.OCCLUDED) } @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt index 59f16d70fab5..84b7f5c28265 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt @@ -17,17 +17,16 @@ package com.android.systemui.keyguard.domain.interactor -import android.platform.test.annotations.DisableFlags -import android.platform.test.annotations.EnableFlags import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.data.repository.fakeFingerprintPropertyRepository import com.android.systemui.biometrics.shared.model.FingerprintSensorType import com.android.systemui.biometrics.shared.model.SensorStrength import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.DisableSceneContainer +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository import com.android.systemui.keyguard.data.repository.keyguardBlueprintRepository import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint @@ -59,8 +58,8 @@ import org.mockito.MockitoAnnotations class KeyguardBlueprintInteractorTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val underTest = kosmos.keyguardBlueprintInteractor - private val keyguardBlueprintRepository = kosmos.keyguardBlueprintRepository + private val underTest by lazy { kosmos.keyguardBlueprintInteractor } + private val keyguardBlueprintRepository by lazy { kosmos.keyguardBlueprintRepository } private val clockRepository by lazy { kosmos.fakeKeyguardClockRepository } private val configurationRepository by lazy { kosmos.fakeConfigurationRepository } private val fingerprintPropertyRepository by lazy { kosmos.fakeFingerprintPropertyRepository } @@ -75,7 +74,7 @@ class KeyguardBlueprintInteractorTest : SysuiTestCase() { sensorId = 1, strength = SensorStrength.STRONG, sensorType = FingerprintSensorType.POWER_BUTTON, - sensorLocations = mapOf() + sensorLocations = mapOf(), ) } @@ -93,7 +92,7 @@ class KeyguardBlueprintInteractorTest : SysuiTestCase() { } @Test - @DisableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) + @DisableSceneContainer fun testAppliesSplitShadeBlueprint() { testScope.runTest { val blueprintId by collectLastValue(underTest.blueprintId) @@ -107,7 +106,7 @@ class KeyguardBlueprintInteractorTest : SysuiTestCase() { } @Test - @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) + @EnableSceneContainer fun testDoesNotApplySplitShadeBlueprint() { testScope.runTest { val blueprintId by collectLastValue(underTest.blueprintId) @@ -122,7 +121,7 @@ class KeyguardBlueprintInteractorTest : SysuiTestCase() { } @Test - @DisableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) + @DisableSceneContainer fun fingerprintPropertyInitialized_updatesBlueprint() { testScope.runTest { underTest.start() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt index 41c5b7332a4f..ff6ea3a14ff2 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt @@ -25,6 +25,8 @@ import androidx.test.filters.SmallTest import com.android.systemui.Flags as AConfigFlags import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.DisableSceneContainer +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.BurnInInteractor @@ -44,6 +46,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.mockito.Answers @@ -71,10 +74,8 @@ class AodBurnInViewModelTest : SysuiTestCase() { private val burnInFlow = MutableStateFlow(BurnInModel()) @Before - @DisableFlags( - AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT, - AConfigFlags.FLAG_COMPOSE_LOCKSCREEN - ) + @DisableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) + @DisableSceneContainer fun setUp() { MockitoAnnotations.initMocks(this) whenever(burnInInteractor.burnIn(anyInt(), anyInt())).thenReturn(burnInFlow) @@ -112,18 +113,13 @@ class AodBurnInViewModelTest : SysuiTestCase() { from = KeyguardState.AOD, to = KeyguardState.LOCKSCREEN, value = 1f, - transitionState = TransitionState.FINISHED + transitionState = TransitionState.FINISHED, ), validateStep = false, ) // Trigger a change to the burn-in model - burnInFlow.value = - BurnInModel( - translationX = 20, - translationY = 30, - scale = 0.5f, - ) + burnInFlow.value = BurnInModel(translationX = 20, translationY = 30, scale = 0.5f) assertThat(movement?.translationX).isEqualTo(0) assertThat(movement?.translationY).isEqualTo(0) @@ -143,17 +139,12 @@ class AodBurnInViewModelTest : SysuiTestCase() { from = KeyguardState.GONE, to = KeyguardState.AOD, value = 1f, - transitionState = TransitionState.FINISHED + transitionState = TransitionState.FINISHED, ), validateStep = false, ) // Trigger a change to the burn-in model - burnInFlow.value = - BurnInModel( - translationX = 20, - translationY = 30, - scale = 0.5f, - ) + burnInFlow.value = BurnInModel(translationX = 20, translationY = 30, scale = 0.5f) assertThat(movement?.translationX).isEqualTo(20) assertThat(movement?.translationY).isEqualTo(30) @@ -166,7 +157,7 @@ class AodBurnInViewModelTest : SysuiTestCase() { from = KeyguardState.GONE, to = KeyguardState.AOD, value = 0f, - transitionState = TransitionState.STARTED + transitionState = TransitionState.STARTED, ), validateStep = false, ) @@ -180,11 +171,7 @@ class AodBurnInViewModelTest : SysuiTestCase() { @DisableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) fun translationAndScale_whenFullyDozing_MigrationFlagOff_staysOutOfTopInset() = testScope.runTest { - burnInParameters = - burnInParameters.copy( - minViewY = 100, - topInset = 80, - ) + burnInParameters = burnInParameters.copy(minViewY = 100, topInset = 80) val movement by collectLastValue(underTest.movement(burnInParameters)) // Set to dozing (on AOD) @@ -193,18 +180,13 @@ class AodBurnInViewModelTest : SysuiTestCase() { from = KeyguardState.GONE, to = KeyguardState.AOD, value = 1f, - transitionState = TransitionState.FINISHED + transitionState = TransitionState.FINISHED, ), validateStep = false, ) // Trigger a change to the burn-in model - burnInFlow.value = - BurnInModel( - translationX = 20, - translationY = -30, - scale = 0.5f, - ) + burnInFlow.value = BurnInModel(translationX = 20, translationY = -30, scale = 0.5f) assertThat(movement?.translationX).isEqualTo(20) // -20 instead of -30, due to inset of 80 assertThat(movement?.translationY).isEqualTo(-20) @@ -217,7 +199,7 @@ class AodBurnInViewModelTest : SysuiTestCase() { from = KeyguardState.GONE, to = KeyguardState.AOD, value = 0f, - transitionState = TransitionState.STARTED + transitionState = TransitionState.STARTED, ), validateStep = false, ) @@ -231,11 +213,7 @@ class AodBurnInViewModelTest : SysuiTestCase() { @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) fun translationAndScale_whenFullyDozing_MigrationFlagOn_staysOutOfTopInset() = testScope.runTest { - burnInParameters = - burnInParameters.copy( - minViewY = 100, - topInset = 80, - ) + burnInParameters = burnInParameters.copy(minViewY = 100, topInset = 80) val movement by collectLastValue(underTest.movement(burnInParameters)) // Set to dozing (on AOD) @@ -244,18 +222,13 @@ class AodBurnInViewModelTest : SysuiTestCase() { from = KeyguardState.GONE, to = KeyguardState.AOD, value = 1f, - transitionState = TransitionState.FINISHED + transitionState = TransitionState.FINISHED, ), validateStep = false, ) // Trigger a change to the burn-in model - burnInFlow.value = - BurnInModel( - translationX = 20, - translationY = -30, - scale = 0.5f, - ) + burnInFlow.value = BurnInModel(translationX = 20, translationY = -30, scale = 0.5f) assertThat(movement?.translationX).isEqualTo(20) // -20 instead of -30, due to inset of 80 assertThat(movement?.translationY).isEqualTo(-20) @@ -268,7 +241,7 @@ class AodBurnInViewModelTest : SysuiTestCase() { from = KeyguardState.GONE, to = KeyguardState.AOD, value = 0f, - transitionState = TransitionState.STARTED + transitionState = TransitionState.STARTED, ), validateStep = false, ) @@ -291,18 +264,13 @@ class AodBurnInViewModelTest : SysuiTestCase() { from = KeyguardState.GONE, to = KeyguardState.AOD, value = 1f, - transitionState = TransitionState.FINISHED + transitionState = TransitionState.FINISHED, ), validateStep = false, ) // Trigger a change to the burn-in model - burnInFlow.value = - BurnInModel( - translationX = 20, - translationY = 30, - scale = 0.5f, - ) + burnInFlow.value = BurnInModel(translationX = 20, translationY = 30, scale = 0.5f) assertThat(movement?.translationX).isEqualTo(20) assertThat(movement?.translationY).isEqualTo(30) @@ -311,9 +279,9 @@ class AodBurnInViewModelTest : SysuiTestCase() { } @Test - @DisableFlags(AConfigFlags.FLAG_COMPOSE_LOCKSCREEN) + @DisableSceneContainer @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) - fun translationAndScale_composeFlagOff_weatherLargeClock() = + fun translationAndScale_sceneContainerOff_weatherLargeClock() = testBurnInViewModelForClocks( isSmallClock = false, isWeatherClock = true, @@ -321,9 +289,9 @@ class AodBurnInViewModelTest : SysuiTestCase() { ) @Test - @DisableFlags(AConfigFlags.FLAG_COMPOSE_LOCKSCREEN) + @DisableSceneContainer @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) - fun translationAndScale_composeFlagOff_weatherSmallClock() = + fun translationAndScale_sceneContainerOff_weatherSmallClock() = testBurnInViewModelForClocks( isSmallClock = true, isWeatherClock = true, @@ -331,9 +299,9 @@ class AodBurnInViewModelTest : SysuiTestCase() { ) @Test - @DisableFlags(AConfigFlags.FLAG_COMPOSE_LOCKSCREEN) + @DisableSceneContainer @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) - fun translationAndScale_composeFlagOff_nonWeatherLargeClock() = + fun translationAndScale_sceneContainerOff_nonWeatherLargeClock() = testBurnInViewModelForClocks( isSmallClock = false, isWeatherClock = false, @@ -341,9 +309,9 @@ class AodBurnInViewModelTest : SysuiTestCase() { ) @Test - @DisableFlags(AConfigFlags.FLAG_COMPOSE_LOCKSCREEN) + @DisableSceneContainer @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) - fun translationAndScale_composeFlagOff_nonWeatherSmallClock() = + fun translationAndScale_sceneContainerOff_nonWeatherSmallClock() = testBurnInViewModelForClocks( isSmallClock = true, isWeatherClock = false, @@ -351,11 +319,9 @@ class AodBurnInViewModelTest : SysuiTestCase() { ) @Test - @EnableFlags( - AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT, - AConfigFlags.FLAG_COMPOSE_LOCKSCREEN - ) - fun translationAndScale_composeFlagOn_weatherLargeClock() = + @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) + @EnableSceneContainer + fun translationAndScale_sceneContainerOn_weatherLargeClock() = testBurnInViewModelForClocks( isSmallClock = false, isWeatherClock = true, @@ -363,11 +329,9 @@ class AodBurnInViewModelTest : SysuiTestCase() { ) @Test - @EnableFlags( - AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT, - AConfigFlags.FLAG_COMPOSE_LOCKSCREEN - ) - fun translationAndScale_composeFlagOn_weatherSmallClock() = + @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) + @EnableSceneContainer + fun translationAndScale_sceneContainerOn_weatherSmallClock() = testBurnInViewModelForClocks( isSmallClock = true, isWeatherClock = true, @@ -375,11 +339,9 @@ class AodBurnInViewModelTest : SysuiTestCase() { ) @Test - @EnableFlags( - AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT, - AConfigFlags.FLAG_COMPOSE_LOCKSCREEN - ) - fun translationAndScale_composeFlagOn_nonWeatherLargeClock() = + @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) + @EnableSceneContainer + fun translationAndScale_sceneContainerOn_nonWeatherLargeClock() = testBurnInViewModelForClocks( isSmallClock = false, isWeatherClock = false, @@ -387,11 +349,10 @@ class AodBurnInViewModelTest : SysuiTestCase() { ) @Test - @EnableFlags( - AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT, - AConfigFlags.FLAG_COMPOSE_LOCKSCREEN - ) - fun translationAndScale_composeFlagOn_nonWeatherSmallClock() = + @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) + @EnableSceneContainer + @Ignore("b/367659687") + fun translationAndScale_sceneContainerOn_nonWeatherSmallClock() = testBurnInViewModelForClocks( isSmallClock = true, isWeatherClock = false, @@ -421,18 +382,13 @@ class AodBurnInViewModelTest : SysuiTestCase() { from = KeyguardState.LOCKSCREEN, to = KeyguardState.AOD, value = 1f, - transitionState = TransitionState.FINISHED + transitionState = TransitionState.FINISHED, ), validateStep = false, ) // Trigger a change to the burn-in model - burnInFlow.value = - BurnInModel( - translationX = 20, - translationY = 30, - scale = 0.5f, - ) + burnInFlow.value = BurnInModel(translationX = 20, translationY = 30, scale = 0.5f) assertThat(movement?.translationX).isEqualTo(20) assertThat(movement?.translationY).isEqualTo(30) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt index 17e1b53a3ba9..05a6b8785daf 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt @@ -16,14 +16,13 @@ package com.android.systemui.keyguard.ui.viewmodel -import android.platform.test.annotations.DisableFlags -import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization import androidx.test.filters.SmallTest -import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.BrokenWithSceneContainer +import com.android.systemui.flags.DisableSceneContainer +import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.flags.andSceneContainer import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository import com.android.systemui.keyguard.data.repository.keyguardClockRepository @@ -229,8 +228,8 @@ class KeyguardClockViewModelTest(flags: FlagsParameterization) : SysuiTestCase() } @Test - @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) - fun testSmallClockTop_splitShade_composeLockscreenOn() = + @EnableSceneContainer + fun testSmallClockTop_splitShade_sceneContainerOn() = testScope.runTest { with(kosmos) { shadeRepository.setShadeLayoutWide(true) @@ -244,8 +243,8 @@ class KeyguardClockViewModelTest(flags: FlagsParameterization) : SysuiTestCase() } @Test - @DisableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) - fun testSmallClockTop_splitShade_composeLockscreenOff() = + @DisableSceneContainer + fun testSmallClockTop_splitShade_sceneContainerOff() = testScope.runTest { with(kosmos) { shadeRepository.setShadeLayoutWide(true) @@ -257,8 +256,8 @@ class KeyguardClockViewModelTest(flags: FlagsParameterization) : SysuiTestCase() } @Test - @EnableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) - fun testSmallClockTop_nonSplitShade_composeLockscreenOn() = + @EnableSceneContainer + fun testSmallClockTop_nonSplitShade_sceneContainerOn() = testScope.runTest { with(kosmos) { shadeRepository.setShadeLayoutWide(false) @@ -270,8 +269,8 @@ class KeyguardClockViewModelTest(flags: FlagsParameterization) : SysuiTestCase() } @Test - @DisableFlags(Flags.FLAG_COMPOSE_LOCKSCREEN) - fun testSmallClockTop_nonSplitShade_composeLockscreenOff() = + @DisableSceneContainer + fun testSmallClockTop_nonSplitShade_sceneContainerOff() = testScope.runTest { with(kosmos) { shadeRepository.setShadeLayoutWide(false) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt index 69ccc58cadbf..7da2e9a8a283 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt @@ -35,6 +35,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS import com.android.systemui.flags.fakeFeatureFlagsClassic +import com.android.systemui.graphics.ImageLoader import com.android.systemui.graphics.imageLoader import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope @@ -45,12 +46,18 @@ import com.android.systemui.res.R import com.android.systemui.statusbar.SbnBuilder import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyInt import org.mockito.kotlin.any import org.mockito.kotlin.mock +import org.mockito.kotlin.times +import org.mockito.kotlin.verify import org.mockito.kotlin.whenever private const val KEY = "KEY" @@ -88,12 +95,13 @@ class MediaDataLoaderTest : SysuiTestCase() { mediaControllerFactory, mediaFlags, kosmos.imageLoader, - statusBarManager + statusBarManager, ) @Before fun setUp() { mediaControllerFactory.setControllerForToken(session.sessionToken, mediaController) + whenever(mediaController.metadata).then { metadataBuilder.build() } } @Test @@ -115,7 +123,7 @@ class MediaDataLoaderTest : SysuiTestCase() { 0, 0, AudioAttributes.Builder().build(), - null + null, ) ) whenever(mediaController.metadata) @@ -126,7 +134,7 @@ class MediaDataLoaderTest : SysuiTestCase() { .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, albumArt) .putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, - MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT + MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT, ) .build() ) @@ -161,12 +169,12 @@ class MediaDataLoaderTest : SysuiTestCase() { val extras = Bundle() extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, - MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED + MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED, ) extras.putDouble(MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.3) extras.putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, - MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT + MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT, ) val description = @@ -189,7 +197,7 @@ class MediaDataLoaderTest : SysuiTestCase() { session.sessionToken, APP_NAME, intent, - PACKAGE_NAME + PACKAGE_NAME, ) assertThat(result).isNotNull() assertThat(result?.appName).isEqualTo(APP_NAME) @@ -372,9 +380,37 @@ class MediaDataLoaderTest : SysuiTestCase() { assertThat(result).isNotNull() } + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun testLoadMediaDataInBg_cancelMultipleScheduledTasks() = + testScope.runTest { + val mockImageLoader = mock<ImageLoader>() + val mediaDataLoader = + MediaDataLoader( + context, + testDispatcher, + testScope, + mediaControllerFactory, + mediaFlags, + mockImageLoader, + statusBarManager, + ) + metadataBuilder.putString( + MediaMetadata.METADATA_KEY_ALBUM_ART_URI, + "content://album_art_uri", + ) + + testScope.launch { mediaDataLoader.loadMediaData(KEY, createMediaNotification()) } + testScope.launch { mediaDataLoader.loadMediaData(KEY, createMediaNotification()) } + testScope.launch { mediaDataLoader.loadMediaData(KEY, createMediaNotification()) } + testScope.advanceUntilIdle() + + verify(mockImageLoader, times(1)).loadBitmap(any(), anyInt(), anyInt(), anyInt()) + } + private fun createMediaNotification( mediaSession: MediaSession? = session, - applicationInfo: ApplicationInfo? = null + applicationInfo: ApplicationInfo? = null, ): StatusBarNotification = SbnBuilder().run { setPkg(PACKAGE_NAME) @@ -385,7 +421,7 @@ class MediaDataLoaderTest : SysuiTestCase() { val bundle = Bundle() bundle.putParcelable( Notification.EXTRA_BUILDER_APPLICATION_INFO, - applicationInfo + applicationInfo, ) it.addExtras(bundle) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/GridConsistencyInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/GridConsistencyInteractorTest.kt deleted file mode 100644 index 42db96e917ee..000000000000 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/GridConsistencyInteractorTest.kt +++ /dev/null @@ -1,183 +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.qs.panels.domain.interactor - -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.qs.panels.data.repository.DefaultLargeTilesRepository -import com.android.systemui.qs.panels.data.repository.defaultLargeTilesRepository -import com.android.systemui.qs.panels.data.repository.gridLayoutTypeRepository -import com.android.systemui.qs.panels.shared.model.GridLayoutType -import com.android.systemui.qs.panels.shared.model.InfiniteGridLayoutType -import com.android.systemui.qs.pipeline.data.repository.tileSpecRepository -import com.android.systemui.qs.pipeline.domain.interactor.currentTilesInteractor -import com.android.systemui.qs.pipeline.shared.TileSpec -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.Before -import org.junit.Test -import org.junit.runner.RunWith - -@OptIn(ExperimentalCoroutinesApi::class) -@SmallTest -@RunWith(AndroidJUnit4::class) -class GridConsistencyInteractorTest : SysuiTestCase() { - - data object NoopGridLayoutType : GridLayoutType - - private val kosmos = - testKosmos().apply { - defaultLargeTilesRepository = - object : DefaultLargeTilesRepository { - override val defaultLargeTiles = - setOf( - TileSpec.create("largeA"), - TileSpec.create("largeB"), - TileSpec.create("largeC"), - TileSpec.create("largeD"), - ) - } - gridConsistencyInteractorsMap = - mapOf( - Pair(NoopGridLayoutType, noopGridConsistencyInteractor), - Pair(InfiniteGridLayoutType, infiniteGridConsistencyInteractor) - ) - } - - private val underTest = with(kosmos) { gridConsistencyInteractor } - - @Before - fun setUp() { - // Mostly testing InfiniteGridConsistencyInteractor because it reorders tiles - with(kosmos) { gridLayoutTypeRepository.setLayout(InfiniteGridLayoutType) } - underTest.start() - } - - @OptIn(ExperimentalCoroutinesApi::class) - @Test - fun changeLayoutType_usesCorrectGridConsistencyInteractor() = - with(kosmos) { - testScope.runTest { - // Using the no-op grid consistency interactor - gridLayoutTypeRepository.setLayout(NoopGridLayoutType) - - // Setting an invalid layout with holes - // [ Large A ] [ sa ] - // [ Large B ] [ Large C ] - // [ sb ] [ Large D ] - val newTiles = - listOf( - TileSpec.create("largeA"), - TileSpec.create("smallA"), - TileSpec.create("largeB"), - TileSpec.create("largeC"), - TileSpec.create("smallB"), - TileSpec.create("largeD"), - ) - tileSpecRepository.setTiles(0, newTiles) - - runCurrent() - - val tiles = currentTilesInteractor.currentTiles.value - val tileSpecs = tiles.map { it.spec } - - // Saved tiles should be unchanged - assertThat(tileSpecs).isEqualTo(newTiles) - } - } - - @Test - fun validTilesWithInfiniteGridConsistencyInteractor_unchangedList() = - with(kosmos) { - testScope.runTest { - // Setting a valid layout with holes - // [ Large A ] [ sa ][ sb ] - // [ Large B ] [ Large C ] - // [ Large D ] - val newTiles = - listOf( - TileSpec.create("largeA"), - TileSpec.create("smallA"), - TileSpec.create("smallB"), - TileSpec.create("largeB"), - TileSpec.create("largeC"), - TileSpec.create("largeD"), - ) - tileSpecRepository.setTiles(0, newTiles) - - runCurrent() - - val tiles = currentTilesInteractor.currentTiles.value - val tileSpecs = tiles.map { it.spec } - - // Saved tiles should be unchanged - assertThat(tileSpecs).isEqualTo(newTiles) - } - } - - @Test - fun invalidTilesWithInfiniteGridConsistencyInteractor_savesNewList() = - with(kosmos) { - testScope.runTest { - // Setting an invalid layout with holes - // [ sa ] [ Large A ] - // [ Large B ] [ sb ] [ sc ] - // [ sd ] [ se ] [ Large C ] - val newTiles = - listOf( - TileSpec.create("smallA"), - TileSpec.create("largeA"), - TileSpec.create("largeB"), - TileSpec.create("smallB"), - TileSpec.create("smallC"), - TileSpec.create("smallD"), - TileSpec.create("smallE"), - TileSpec.create("largeC"), - ) - tileSpecRepository.setTiles(0, newTiles) - - runCurrent() - - val tiles = currentTilesInteractor.currentTiles.value - val tileSpecs = tiles.map { it.spec } - - // Expected grid - // [ sa ] [ Large A ] [ sb ] - // [ Large B ] [ sc ] [ sd ] - // [ se ] [ Large C ] - val expectedTiles = - listOf( - TileSpec.create("smallA"), - TileSpec.create("largeA"), - TileSpec.create("smallB"), - TileSpec.create("largeB"), - TileSpec.create("smallC"), - TileSpec.create("smallD"), - TileSpec.create("smallE"), - TileSpec.create("largeC"), - ) - - // Saved tiles should be unchanged - assertThat(tileSpecs).isEqualTo(expectedTiles) - } - } -} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridConsistencyInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridConsistencyInteractorTest.kt deleted file mode 100644 index ea51398e6256..000000000000 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridConsistencyInteractorTest.kt +++ /dev/null @@ -1,187 +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.qs.panels.domain.interactor - -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.qs.panels.data.repository.DefaultLargeTilesRepository -import com.android.systemui.qs.panels.data.repository.defaultLargeTilesRepository -import com.android.systemui.qs.pipeline.shared.TileSpec -import com.android.systemui.testKosmos -import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.test.runTest -import org.junit.Test -import org.junit.runner.RunWith - -@SmallTest -@RunWith(AndroidJUnit4::class) -class InfiniteGridConsistencyInteractorTest : SysuiTestCase() { - - private val kosmos = - testKosmos().apply { - defaultLargeTilesRepository = - object : DefaultLargeTilesRepository { - override val defaultLargeTiles: Set<TileSpec> = - setOf( - TileSpec.create("largeA"), - TileSpec.create("largeB"), - TileSpec.create("largeC"), - TileSpec.create("largeD"), - ) - } - } - private val underTest = with(kosmos) { infiniteGridConsistencyInteractor } - - @Test - fun validTiles_returnsUnchangedList() = - with(kosmos) { - testScope.runTest { - // Original grid - // [ Large A ] [ sa ][ sb ] - // [ Large B ] [ Large C ] - // [ Large D ] - val tiles = - listOf( - TileSpec.create("largeA"), - TileSpec.create("smallA"), - TileSpec.create("smallB"), - TileSpec.create("largeB"), - TileSpec.create("largeC"), - TileSpec.create("largeD"), - ) - - val newTiles = underTest.reconcileTiles(tiles) - - assertThat(newTiles).isEqualTo(tiles) - } - } - - @Test - fun invalidTiles_moveIconTileForward() = - with(kosmos) { - testScope.runTest { - // Original grid - // [ Large A ] [ sa ] - // [ Large B ] [ Large C ] - // [ sb ] [ Large D ] - val tiles = - listOf( - TileSpec.create("largeA"), - TileSpec.create("smallA"), - TileSpec.create("largeB"), - TileSpec.create("largeC"), - TileSpec.create("smallB"), - TileSpec.create("largeD"), - ) - // Expected grid - // [ Large A ] [ sa ][ sb ] - // [ Large B ] [ Large C ] - // [ Large D ] - val expectedTiles = - listOf( - TileSpec.create("largeA"), - TileSpec.create("smallA"), - TileSpec.create("smallB"), - TileSpec.create("largeB"), - TileSpec.create("largeC"), - TileSpec.create("largeD"), - ) - - val newTiles = underTest.reconcileTiles(tiles) - - assertThat(newTiles).isEqualTo(expectedTiles) - } - } - - @Test - fun invalidTiles_moveIconTileBack() = - with(kosmos) { - testScope.runTest { - // Original grid - // [ sa ] [ Large A ] - // [ Large B ] [ Large C ] - // [ Large D ] - val tiles = - listOf( - TileSpec.create("smallA"), - TileSpec.create("largeA"), - TileSpec.create("largeB"), - TileSpec.create("largeC"), - TileSpec.create("largeD"), - ) - // Expected grid - // [ Large A ] [ Large B ] - // [ Large C ] [ Large D ] - // [ sa ] - val expectedTiles = - listOf( - TileSpec.create("largeA"), - TileSpec.create("largeB"), - TileSpec.create("largeC"), - TileSpec.create("largeD"), - TileSpec.create("smallA"), - ) - - val newTiles = underTest.reconcileTiles(tiles) - - assertThat(newTiles).isEqualTo(expectedTiles) - } - } - - @Test - fun invalidTiles_multipleCorrections() = - with(kosmos) { - testScope.runTest { - // Original grid - // [ sa ] [ Large A ] - // [ Large B ] [ sb ] [ sc ] - // [ sd ] [ se ] [ Large C ] - val tiles = - listOf( - TileSpec.create("smallA"), - TileSpec.create("largeA"), - TileSpec.create("largeB"), - TileSpec.create("smallB"), - TileSpec.create("smallC"), - TileSpec.create("smallD"), - TileSpec.create("smallE"), - TileSpec.create("largeC"), - ) - // Expected grid - // [ sa ] [ Large A ] [ sb ] - // [ Large B ] [ sc ] [ sd ] - // [ se ] [ Large C ] - val expectedTiles = - listOf( - TileSpec.create("smallA"), - TileSpec.create("largeA"), - TileSpec.create("smallB"), - TileSpec.create("largeB"), - TileSpec.create("smallC"), - TileSpec.create("smallD"), - TileSpec.create("smallE"), - TileSpec.create("largeC"), - ) - - val newTiles = underTest.reconcileTiles(tiles) - - assertThat(newTiles).isEqualTo(expectedTiles) - } - } -} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayoutTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayoutTest.kt index 53384afb66be..9e90090549dd 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayoutTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayoutTest.kt @@ -22,6 +22,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.kosmos.testScope import com.android.systemui.qs.panels.data.repository.DefaultLargeTilesRepository import com.android.systemui.qs.panels.data.repository.defaultLargeTilesRepository +import com.android.systemui.qs.panels.ui.compose.infinitegrid.InfiniteGridLayout import com.android.systemui.qs.panels.ui.viewmodel.MockTileViewModel import com.android.systemui.qs.panels.ui.viewmodel.fixedColumnsSizeViewModel import com.android.systemui.qs.panels.ui.viewmodel.iconTilesViewModel @@ -44,12 +45,7 @@ class InfiniteGridLayoutTest : SysuiTestCase() { } private val underTest = - with(kosmos) { - InfiniteGridLayout( - iconTilesViewModel, - fixedColumnsSizeViewModel, - ) - } + with(kosmos) { InfiniteGridLayout(iconTilesViewModel, fixedColumnsSizeViewModel) } @Test fun correctPagination_underOnePage_sameOrder() = @@ -65,7 +61,7 @@ class InfiniteGridLayoutTest : SysuiTestCase() { smallTile(), largeTile(), largeTile(), - smallTile() + smallTile(), ) val pages = underTest.splitIntoPages(tiles, rows = rows, columns = columns) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt index 763a1a943bf8..385089122fc4 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt @@ -27,6 +27,7 @@ import android.view.Display import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState +import com.android.compose.animation.scene.OverlayKey import com.android.compose.animation.scene.SceneKey import com.android.internal.logging.uiEventLoggerFake import com.android.internal.policy.IKeyguardDismissCallback @@ -88,9 +89,11 @@ import com.android.systemui.scene.data.model.asIterable import com.android.systemui.scene.data.repository.Transition import com.android.systemui.scene.domain.interactor.sceneBackInteractor import com.android.systemui.scene.domain.interactor.sceneInteractor +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.shade.domain.interactor.shadeInteractor +import com.android.systemui.shade.shared.flag.DualShade import com.android.systemui.shared.system.QuickStepContract import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor @@ -161,6 +164,7 @@ class SceneContainerStartableTest : SysuiTestCase() { } @Test + @DisableFlags(DualShade.FLAG_NAME) fun hydrateVisibility() = testScope.runTest { val currentDesiredSceneKey by collectLastValue(sceneInteractor.currentScene) @@ -221,6 +225,87 @@ class SceneContainerStartableTest : SysuiTestCase() { } @Test + @EnableFlags(DualShade.FLAG_NAME) + fun hydrateVisibility_dualShade() = + testScope.runTest { + val currentDesiredSceneKey by collectLastValue(sceneInteractor.currentScene) + val currentDesiredOverlays by collectLastValue(sceneInteractor.currentOverlays) + val isVisible by collectLastValue(sceneInteractor.isVisible) + val transitionStateFlow = + prepareState( + authenticationMethod = AuthenticationMethodModel.Pin, + isDeviceUnlocked = true, + initialSceneKey = Scenes.Gone, + ) + assertThat(currentDesiredSceneKey).isEqualTo(Scenes.Gone) + assertThat(currentDesiredOverlays).isEmpty() + assertThat(isVisible).isTrue() + + underTest.start() + assertThat(isVisible).isFalse() + + // Expand the notifications shade. + fakeSceneDataSource.pause() + sceneInteractor.showOverlay(Overlays.NotificationsShade, "reason") + transitionStateFlow.value = + ObservableTransitionState.Transition.ShowOrHideOverlay( + overlay = Overlays.NotificationsShade, + fromContent = Scenes.Gone, + toContent = Overlays.NotificationsShade, + currentScene = Scenes.Gone, + currentOverlays = flowOf(emptySet()), + progress = flowOf(0.5f), + isInitiatedByUserInput = false, + isUserInputOngoing = flowOf(false), + previewProgress = flowOf(0f), + isInPreviewStage = flowOf(false), + ) + assertThat(isVisible).isTrue() + fakeSceneDataSource.unpause(expectedScene = Scenes.Gone) + transitionStateFlow.value = + ObservableTransitionState.Idle( + currentScene = Scenes.Gone, + currentOverlays = setOf(Overlays.NotificationsShade), + ) + assertThat(isVisible).isTrue() + + // Collapse the notifications shade. + fakeSceneDataSource.pause() + sceneInteractor.hideOverlay(Overlays.NotificationsShade, "reason") + transitionStateFlow.value = + ObservableTransitionState.Transition.ShowOrHideOverlay( + overlay = Overlays.NotificationsShade, + fromContent = Overlays.NotificationsShade, + toContent = Scenes.Gone, + currentScene = Scenes.Gone, + currentOverlays = flowOf(setOf(Overlays.NotificationsShade)), + progress = flowOf(0.5f), + isInitiatedByUserInput = false, + isUserInputOngoing = flowOf(false), + previewProgress = flowOf(0f), + isInPreviewStage = flowOf(false), + ) + assertThat(isVisible).isTrue() + fakeSceneDataSource.unpause(expectedScene = Scenes.Gone) + transitionStateFlow.value = + ObservableTransitionState.Idle( + currentScene = Scenes.Gone, + currentOverlays = emptySet(), + ) + assertThat(isVisible).isFalse() + + kosmos.headsUpNotificationRepository.setNotifications( + buildNotificationRows(isPinned = true) + ) + assertThat(isVisible).isTrue() + + kosmos.headsUpNotificationRepository.setNotifications( + buildNotificationRows(isPinned = false) + ) + assertThat(isVisible).isFalse() + } + + @Test fun hydrateVisibility_basedOnDeviceProvisioning() = testScope.runTest { val isVisible by collectLastValue(sceneInteractor.isVisible) @@ -1621,6 +1706,7 @@ class SceneContainerStartableTest : SysuiTestCase() { } @Test + @DisableFlags(DualShade.FLAG_NAME) fun hydrateInteractionState_whileLocked() = testScope.runTest { val transitionStateFlow = prepareState(initialSceneKey = Scenes.Lockscreen) @@ -1707,6 +1793,7 @@ class SceneContainerStartableTest : SysuiTestCase() { } @Test + @DisableFlags(DualShade.FLAG_NAME) fun hydrateInteractionState_whileUnlocked() = testScope.runTest { val transitionStateFlow = @@ -1795,6 +1882,186 @@ class SceneContainerStartableTest : SysuiTestCase() { } @Test + @EnableFlags(DualShade.FLAG_NAME) + fun hydrateInteractionState_dualShade_whileLocked() = + testScope.runTest { + val currentDesiredOverlays by collectLastValue(sceneInteractor.currentOverlays) + val transitionStateFlow = prepareState(initialSceneKey = Scenes.Lockscreen) + underTest.start() + runCurrent() + verify(centralSurfaces).setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true) + assertThat(currentDesiredOverlays).isEmpty() + + clearInvocations(centralSurfaces) + emulateSceneTransition( + transitionStateFlow = transitionStateFlow, + toScene = Scenes.Bouncer, + verifyBeforeTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyDuringTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyAfterTransition = { + verify(centralSurfaces) + .setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false) + }, + ) + + clearInvocations(centralSurfaces) + emulateSceneTransition( + transitionStateFlow = transitionStateFlow, + toScene = Scenes.Lockscreen, + verifyBeforeTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyDuringTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyAfterTransition = { + verify(centralSurfaces).setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true) + }, + ) + + clearInvocations(centralSurfaces) + emulateOverlayTransition( + transitionStateFlow = transitionStateFlow, + toOverlay = Overlays.NotificationsShade, + verifyBeforeTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyDuringTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyAfterTransition = { + verify(centralSurfaces) + .setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false) + }, + ) + + clearInvocations(centralSurfaces) + emulateSceneTransition( + transitionStateFlow = transitionStateFlow, + toScene = Scenes.Lockscreen, + verifyBeforeTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyDuringTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyAfterTransition = { + verify(centralSurfaces).setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true) + }, + ) + + clearInvocations(centralSurfaces) + emulateOverlayTransition( + transitionStateFlow = transitionStateFlow, + toOverlay = Overlays.QuickSettingsShade, + verifyBeforeTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyDuringTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyAfterTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + ) + } + + @Test + @EnableFlags(DualShade.FLAG_NAME) + fun hydrateInteractionState_dualShade_whileUnlocked() = + testScope.runTest { + val currentDesiredOverlays by collectLastValue(sceneInteractor.currentOverlays) + val transitionStateFlow = + prepareState( + authenticationMethod = AuthenticationMethodModel.Pin, + isDeviceUnlocked = true, + initialSceneKey = Scenes.Gone, + ) + underTest.start() + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + assertThat(currentDesiredOverlays).isEmpty() + + clearInvocations(centralSurfaces) + emulateSceneTransition( + transitionStateFlow = transitionStateFlow, + toScene = Scenes.Bouncer, + verifyBeforeTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyDuringTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyAfterTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + ) + + clearInvocations(centralSurfaces) + emulateSceneTransition( + transitionStateFlow = transitionStateFlow, + toScene = Scenes.Lockscreen, + verifyBeforeTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyDuringTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyAfterTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + ) + + clearInvocations(centralSurfaces) + emulateSceneTransition( + transitionStateFlow = transitionStateFlow, + toScene = Scenes.Shade, + verifyBeforeTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyDuringTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyAfterTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + ) + + clearInvocations(centralSurfaces) + emulateSceneTransition( + transitionStateFlow = transitionStateFlow, + toScene = Scenes.Lockscreen, + verifyBeforeTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyDuringTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyAfterTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + ) + + clearInvocations(centralSurfaces) + emulateSceneTransition( + transitionStateFlow = transitionStateFlow, + toScene = Scenes.QuickSettings, + verifyBeforeTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyDuringTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + verifyAfterTransition = { + verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean()) + }, + ) + } + + @Test fun respondToFalsingDetections() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene) @@ -2131,19 +2398,40 @@ class SceneContainerStartableTest : SysuiTestCase() { verifyAfterTransition: (() -> Unit)? = null, ) { val fromScene = sceneInteractor.currentScene.value + val fromOverlays = sceneInteractor.currentOverlays.value sceneInteractor.changeScene(toScene, "reason") runCurrent() verifyBeforeTransition?.invoke() transitionStateFlow.value = - ObservableTransitionState.Transition( - fromScene = fromScene, - toScene = toScene, - currentScene = flowOf(fromScene), - progress = flowOf(0.5f), - isInitiatedByUserInput = true, - isUserInputOngoing = flowOf(true), - ) + if (fromOverlays.isEmpty()) { + // Regular scene-to-scene transition. + ObservableTransitionState.Transition.ChangeScene( + fromScene = fromScene, + toScene = toScene, + currentScene = flowOf(fromScene), + currentOverlays = fromOverlays, + progress = flowOf(0.5f), + isInitiatedByUserInput = true, + isUserInputOngoing = flowOf(true), + previewProgress = flowOf(0f), + isInPreviewStage = flowOf(false), + ) + } else { + // An overlay is present; hide it. + ObservableTransitionState.Transition.ShowOrHideOverlay( + overlay = fromOverlays.first(), + fromContent = fromOverlays.first(), + toContent = toScene, + currentScene = fromScene, + currentOverlays = sceneInteractor.currentOverlays, + progress = flowOf(0.5f), + isInitiatedByUserInput = true, + isUserInputOngoing = flowOf(true), + previewProgress = flowOf(0f), + isInPreviewStage = flowOf(false), + ) + } runCurrent() verifyDuringTransition?.invoke() @@ -2152,6 +2440,60 @@ class SceneContainerStartableTest : SysuiTestCase() { verifyAfterTransition?.invoke() } + private fun TestScope.emulateOverlayTransition( + transitionStateFlow: MutableStateFlow<ObservableTransitionState>, + toOverlay: OverlayKey, + verifyBeforeTransition: (() -> Unit)? = null, + verifyDuringTransition: (() -> Unit)? = null, + verifyAfterTransition: (() -> Unit)? = null, + ) { + val fromScene = sceneInteractor.currentScene.value + val fromOverlays = sceneInteractor.currentOverlays.value + sceneInteractor.showOverlay(toOverlay, "reason") + runCurrent() + verifyBeforeTransition?.invoke() + + transitionStateFlow.value = + if (fromOverlays.isEmpty()) { + // Show a new overlay. + ObservableTransitionState.Transition.ShowOrHideOverlay( + overlay = toOverlay, + fromContent = fromScene, + toContent = toOverlay, + currentScene = fromScene, + currentOverlays = sceneInteractor.currentOverlays, + progress = flowOf(0.5f), + isInitiatedByUserInput = true, + isUserInputOngoing = flowOf(true), + previewProgress = flowOf(0f), + isInPreviewStage = flowOf(false), + ) + } else { + // Overlay-to-overlay transition. + ObservableTransitionState.Transition.ReplaceOverlay( + fromOverlay = fromOverlays.first(), + toOverlay = toOverlay, + currentScene = fromScene, + currentOverlays = sceneInteractor.currentOverlays, + progress = flowOf(0.5f), + isInitiatedByUserInput = true, + isUserInputOngoing = flowOf(true), + previewProgress = flowOf(0f), + isInPreviewStage = flowOf(false), + ) + } + runCurrent() + verifyDuringTransition?.invoke() + + transitionStateFlow.value = + ObservableTransitionState.Idle( + currentScene = fromScene, + currentOverlays = setOf(toOverlay), + ) + runCurrent() + verifyAfterTransition?.invoke() + } + private fun TestScope.prepareState( isDeviceUnlocked: Boolean = false, isBypassEnabled: Boolean = false, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt index 4d69f0ddc4b7..f86337ec63dc 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt @@ -19,8 +19,8 @@ package com.android.systemui.scene.shared.flag import android.platform.test.flag.junit.FlagsParameterization import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import com.android.systemui.Flags.FLAG_COMPOSE_LOCKSCREEN import com.android.systemui.Flags.FLAG_EXAMPLE_FLAG +import com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR import com.android.systemui.Flags.FLAG_SCENE_CONTAINER import com.android.systemui.SysuiTestCase import com.android.systemui.flags.andSceneContainer @@ -66,7 +66,7 @@ internal class SceneContainerFlagParameterizationTest : SysuiTestCase() { @Test fun oneDependencyAndSceneContainer() { - val dependentFlag = FLAG_COMPOSE_LOCKSCREEN + val dependentFlag = FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR val result = FlagsParameterization.allCombinationsOf(dependentFlag).andSceneContainer() Truth.assertThat(result).hasSize(3) Truth.assertThat(result[0].mOverrides[dependentFlag]).isFalse() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java index 40fb7691c0c2..614d51e7ac99 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java @@ -39,6 +39,7 @@ import static org.mockito.Mockito.when; import android.app.IActivityManager; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.graphics.Rect; import android.platform.test.flag.junit.FlagsParameterization; import android.testing.TestableLooper.RunWithLooper; import android.view.View; @@ -53,6 +54,7 @@ import com.android.systemui.biometrics.AuthController; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.communal.domain.interactor.CommunalInteractor; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.EnableSceneContainer; import com.android.systemui.flags.SceneContainerFlagParameterizationKt; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.kosmos.KosmosJavaAdapter; @@ -466,6 +468,32 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { assertThat(lp.preferredMinDisplayRefreshRate).isEqualTo(0); } + @Test + @EnableSceneContainer + public void configChanged_boundsUpdate() { + when(mNotificationShadeWindowView.getWidth()).thenReturn(1600); + when(mNotificationShadeWindowView.getHeight()).thenReturn(800); + when(mNotificationShadeWindowView.getVisibility()).thenReturn(View.INVISIBLE); + Configuration newConfig = new Configuration(); + // swap width and height in new bounds to simulate auto-rotate + newConfig.windowConfiguration.setBounds(new Rect(0, 0, 800, 1600)); + mNotificationShadeWindowController.onConfigChanged(newConfig); + verify(mWindowManager, atLeastOnce()).updateViewLayout(any(), any()); + } + + @Test + @EnableSceneContainer + public void configChanged_boundsDontUpdate() { + when(mNotificationShadeWindowView.getWidth()).thenReturn(1600); + when(mNotificationShadeWindowView.getHeight()).thenReturn(800); + when(mNotificationShadeWindowView.getVisibility()).thenReturn(View.INVISIBLE); + Configuration newConfig = new Configuration(); + // same bounds as view's current bounds + newConfig.windowConfiguration.setBounds(new Rect(0, 0, 1600, 800)); + mNotificationShadeWindowController.onConfigChanged(newConfig); + verify(mWindowManager, never()).updateViewLayout(any(), any()); + } + private void setKeyguardShowing() { mNotificationShadeWindowController.setKeyguardShowing(true); mNotificationShadeWindowController.setKeyguardGoingAway(false); diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt index fb32855ee2b7..0f6dc0723f42 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt @@ -17,7 +17,9 @@ package com.android.systemui.statusbar.policy.domain.interactor import android.app.AutomaticZenRule +import android.app.Flags import android.app.NotificationManager.Policy +import android.platform.test.annotations.EnableFlags import android.provider.Settings import android.provider.Settings.Secure.ZEN_DURATION import android.provider.Settings.Secure.ZEN_DURATION_FOREVER @@ -32,6 +34,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope import com.android.systemui.shared.settings.data.repository.secureSettingsRepository +import com.android.systemui.statusbar.policy.data.repository.fakeDeviceProvisioningRepository import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat @@ -50,10 +53,31 @@ class ZenModeInteractorTest : SysuiTestCase() { private val testScope = kosmos.testScope private val zenModeRepository = kosmos.fakeZenModeRepository private val settingsRepository = kosmos.secureSettingsRepository + private val deviceProvisioningRepository = kosmos.fakeDeviceProvisioningRepository private val underTest = kosmos.zenModeInteractor @Test + fun isZenAvailable_off() = + testScope.runTest { + val isZenAvailable by collectLastValue(underTest.isZenAvailable) + deviceProvisioningRepository.setDeviceProvisioned(false) + runCurrent() + + assertThat(isZenAvailable).isFalse() + } + + @Test + fun isZenAvailable_on() = + testScope.runTest { + val isZenAvailable by collectLastValue(underTest.isZenAvailable) + deviceProvisioningRepository.setDeviceProvisioned(true) + runCurrent() + + assertThat(isZenAvailable).isTrue() + } + + @Test fun isZenModeEnabled_off() = testScope.runTest { val enabled by collectLastValue(underTest.isZenModeEnabled) @@ -337,4 +361,22 @@ class ZenModeInteractorTest : SysuiTestCase() { runCurrent() assertThat(mainActiveMode).isNull() } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + fun dndMode_flows() = + testScope.runTest { + val dndMode by collectLastValue(underTest.dndMode) + + zenModeRepository.addMode(TestModeBuilder.MANUAL_DND_INACTIVE) + runCurrent() + + assertThat(dndMode!!.isActive).isFalse() + + zenModeRepository.removeMode(TestModeBuilder.MANUAL_DND_INACTIVE.id) + zenModeRepository.addMode(TestModeBuilder.MANUAL_DND_ACTIVE) + runCurrent() + + assertThat(dndMode!!.isActive).isTrue() + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt index 21a45ecb5922..9dcbe1b591e5 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt @@ -616,6 +616,71 @@ class DeviceFoldStateProviderTest : SysuiTestCase() { } @Test + fun angleDecreaseAfterCancelAnimation_emitsStartClosingEvent() { + setFoldState(folded = true) + sendHingeAngleEvent(0) + foldUpdates.clear() + + setFoldState(folded = false) + rotationListener.value.onRotationChanged(1) + sendHingeAngleEvent(180) + screenOnStatusProvider.notifyScreenTurningOn() + screenOnStatusProvider.notifyScreenTurnedOn() + + // Start folding + (180 downTo 60).forEach { + sendHingeAngleEvent(it) + } + // Stopped folding and simulate timeout in this posture + simulateTimeout() + + assertThat(foldUpdates) + .containsExactly( + FOLD_UPDATE_START_OPENING, // unfolded + FOLD_UPDATE_FINISH_HALF_OPEN, // force-finished the animation because of rotation + FOLD_UPDATE_START_CLOSING, // start closing the device + FOLD_UPDATE_FINISH_HALF_OPEN, // finished closing and timed-out in this state + ) + + } + + @Test + fun angleIncreaseDecreaseAfterHalfUnfold_emitsStartClosingEvent() { + setFoldState(folded = true) + sendHingeAngleEvent(0) + foldUpdates.clear() + + setFoldState(folded = false) + sendHingeAngleEvent(90) + screenOnStatusProvider.notifyScreenTurningOn() + screenOnStatusProvider.notifyScreenTurnedOn() + + // Stopped folding and simulate timeout in this posture + simulateTimeout() + + // Unfold further + (90 until 180).forEach { + sendHingeAngleEvent(it) + } + // Start folding + (180 downTo 90).forEach { + sendHingeAngleEvent(it) + } + + // Stopped folding and simulate timeout in this posture + simulateTimeout() + + assertThat(foldUpdates) + .containsExactly( + FOLD_UPDATE_START_OPENING, // unfolded + FOLD_UPDATE_FINISH_HALF_OPEN, // force-finished the animation because of rotation + FOLD_UPDATE_START_CLOSING, // start closing the device + FOLD_UPDATE_FINISH_HALF_OPEN, // finished closing and timed-out in this state + ) + + } + + @Test fun onUnfold_onSmallScreen_emitsStartOpening() { // the new display state might arrive later, so it shouldn't be used to decide to send the // start opening event, but only for the closing. diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 0fb0aaf20fe2..900c11e53a1f 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Voeg by nota"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Sluit skakel in"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Skakels kan nie vanaf jou ander profiele bygevoeg word nie"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Skermopnemer"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Verwerk tans skermopname"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Deurlopende kennisgewing vir \'n skermopnamesessie"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Voeg by"</string> <string name="manage_users" msgid="1823875311934643849">"Bestuur gebruikers"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Sleep na verdeelde skerm word nie vir hierdie kennisgewing gesteun nie"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑fi onbeskikbaar"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioriteitmodus"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Wekker gestel"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Pasmaak sluitskerm"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Ontsluit om sluitskerm te pasmaak"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-fi is nie beskikbaar nie"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera is geblokkeer"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera en mikrofoon is geblokkeer"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofoon is geblokkeer"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Handelingsleutel"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swiep op en hou met drie vingers. Tik om meer gebare te leer."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gebruik jou sleutelbord om alle apps te bekyk"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Druk enige tyd die handelingsleutel. Tik om meer gebare te leer."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Ekstra donker is nou deel van die helderheidbalk"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Jy kan nou die skerm ekstra donker maak deur die helderheidvlak vanaf die bokant van jou skerm nog laer te maak.\n\nDit werk die beste wanneer jy in ’n donker omgewing is."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Verwyder kortpad vir ekstra donker"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Kortpad vir ekstra donker is verwyder. Gebruik die gewone helderheidbalk om jou helderheid te verlaag."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Konnektiwiteit"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Toeganklikheid"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Nutsdienste"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privaatheid"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Verskaf deur apps"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Vertoon"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Onbekend"</string> </resources> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 286acea48dd3..6a68dd9cafec 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"አክል"</string> <string name="manage_users" msgid="1823875311934643849">"ተጠቃሚዎችን ያስተዳድሩ"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"ይህ ማሳወቂያ ወደ የተከፈለ ማያ ገፅ መጎተትን አይደግፍም"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi አይገኝም"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"የቅድሚያ ሁነታ"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ማንቂያ ተቀናብሯል"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"ማያ ገፅ ቁልፍን አብጅ"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"የማያ ገጽ ቁልፍን ለማበጀት ይክፈቱ"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi አይገኝም"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ካሜራ ታግዷል"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ካሜራ እና ማይክሮፎን ታግደዋል"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ማይክሮፎን ታግዷል"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"የተግባር ቁልፍ"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"ተጨማሪ ደብዛዛ አሁን የብሩህነት አሞሌ ክፍል ነው"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"አሁን ከማያ ገፅዎ በላይ የብሩህነት ደረጃውን ይበልጥ በመቀነስ ማያ ገፁን ተጨማሪ ደብዛዛ ማድረግ ይችላሉ።\n\nይህ በጨለማ አካባቢ ውስጥ ሲሆኑ በተሻለ ይሠራል።"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"ተጨማሪ ደብዛዛ አቋራጭን አስወግድ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"የተጨማሪ ደብዛዛ አቋራጭን ያስወግዱ። የእርስዎን ብሩሃማነት ለመቀነስ መደበኛ የብሩሃማነት አሞሌውን ይጠቀሙ።"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"ግላዊነት"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"በመተግበሪያዎች የቀረበ"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ማሳያ"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"ያልታወቀ"</string> </resources> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 5b844f238028..12732215a0b4 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"إضافة إلى الملاحظة"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"تضمين الرابط"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"لا يمكن إضافة روابط من ملفات شخصية أخرى"</string> <string name="screenrecord_title" msgid="4257171601439507792">"مسجّل الشاشة"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"جارٍ معالجة تسجيل الشاشة"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"إشعار مستمر لجلسة تسجيل شاشة"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"إضافة"</string> <string name="manage_users" msgid="1823875311934643849">"إدارة المستخدمين"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"لا يتيح هذا الإشعار إمكانية السحب لتقسيم الشاشة."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"شبكة Wi‑Fi غير متاحة"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"وضع الأولوية"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"تم ضبط المنبه."</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"تخصيص شاشة القفل"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"الفتح لتخصيص شاشة القفل"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"لا يتوفّر اتصال Wi-Fi."</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"استخدام الكاميرا محظور."</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"استخدام الكاميرا والميكروفون محظور."</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"استخدام الميكروفون محظور."</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"مفتاح الإجراء"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"مرِّر سريعًا للأعلى مع استمرار الضغط باستخدام 3 أصابع. انقر للتعرّف على المزيد من الإيماءات."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"استخدِم لوحة المفاتيح لعرض جميع التطبيقات"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"اضغط على مفتاح الإجراء في أي وقت. انقر للتعرّف على المزيد من الإيماءات."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"ميزة \"زيادة تعتيم الشاشة\" أصبحت الآن ضمن شريط مستوى السطوع"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"يمكنك الآن زيادة تعتيم الشاشة عن طريق خفض مستوى السطوع بشكل أكبر من أعلى الشاشة.\n\nيُعد هذا الخيار مناسبًا عندما تكون في مكان مظلم."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"إزالة اختصار \"زيادة تعتيم الشاشة\""</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"تمت إزالة اختصار \"زيادة تعتيم الشاشة\". لخفض مستوى سطوع شاشتك، استخدِم شريط مستوى السطوع العادي."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"الخصوصية"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"مقدَّمة من التطبيقات"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"العرض"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"غير معروفة"</string> </resources> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 06f28f11f3a4..76431a0a2d57 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"যোগ দিয়ক"</string> <string name="manage_users" msgid="1823875311934643849">"পৰিচালনা কৰক"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"এই জাননীটোৱে বিভাজিত স্ক্ৰীনলৈ টানি আনি এৰাৰ সুবিধাটো সমৰ্থন নকৰে"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ৱাই-ফাই উপলব্ধ নহয়"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"অগ্ৰাধিকাৰ ম’ড"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"এলাৰ্ম ছেট কৰা হ’ল"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"লক স্ক্ৰীন কাষ্টমাইজ কৰক"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"লক স্ক্ৰীন কাষ্টমাইজ কৰিবলৈ আনলক কৰক"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ৱাই-ফাই উপলব্ধ নহয়"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"কেমেৰা অৱৰোধ কৰা আছে"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"কেমেৰা আৰু মাইক্ৰ’ফ’ন অৱৰোধ কৰা আছে"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"মাইক্ৰ’ফ’ন অৱৰোধ কৰা আছে"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"কাৰ্য কী"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"এক্সট্ৰা ডিম এতিয়া উজ্জ্বলতা বাৰৰ অংশ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"আপুনি এতিয়া আপোনাৰ স্ক্ৰীনৰ একেবাৰে ওপৰৰ পৰা উজ্জ্বলতাৰ স্তৰ আৰু অধিক হ্ৰাস কৰি স্ক্ৰীনখন এক্সট্ৰা ডিম কৰিব পাৰে।\n\nআপুনি অন্ধকাৰ পৰিৱেশত থাকিলে এই সুবিধাটোৱে আটাইতকৈ ভাল কাম কৰে।"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"এক্সট্ৰা ডিম শ্বৰ্টকাট আঁতৰাওক"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"এক্সট্ৰা ডিম শ্বৰ্টকাট আঁতৰোৱা হৈছে। আপোনাৰ উজ্জ্বলতা হ্ৰাস কৰিবলৈ, নিয়মীয়া উজ্জ্বলতা বাৰ ব্যৱহাৰ কৰক।"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"গোপনীয়তা"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"এপে প্ৰদান কৰা"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ডিছপ্লে’"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"অজ্ঞাত"</string> </resources> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 24ab6aecaff0..7c33d3b34837 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Qeydə əlavə edin"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Keçid daxil edin"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g><xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Başqa profillərdən link əlavə etmək mümkün deyil"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Ekran yazıcısı"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran çəkilişi emal edilir"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekranın video çəkimi ərzində silinməyən bildiriş"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Əlavə edin"</string> <string name="manage_users" msgid="1823875311934643849">"İstifadəçiləri idarə edin"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Bu bildiriş bölünmüş ekrana sürüşdürməyi dəstəkləmir"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi əlçatan deyil"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritet rejimi"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Siqnal ayarlanıb"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Kilid ekranını fərdiləşdirin"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Kilid ekranını fərdiləşdirmək üçün kiliddən çıxarın"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi əlçatan deyil"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera bloklanıb"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera və mikrofon bloklanıb"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon bloklanıb"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Əməliyyat düyməsi"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Üç barmaq ilə yuxarı çəkib saxlayın. Daha çox jest öyrənmək üçün toxunun."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Bütün tətbiqlərə baxmaq üçün klaviatura istifadə edin"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"İstənilən vaxt fəaliyyət açarını basın. Daha çox jest öyrənmək üçün toxunun."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Əlavə qaraltma artıq parlaqlıq panelinin bir hissəsidir"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"İndi ekranın yuxarısında parlaqlıq səviyyəsini daha da aşağı salaraq ekranı əlavə qaralda bilərsiniz.\n\nTünd mühitdə olduqda nəticə yaxşı olur."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Əlavə qaraltma qısayolunu silin"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Əlavə qaraltma qısayolu silindi. Parlaqlığı aşağı salmaq üçün adi parlaqlıq panelindən istifadə edin."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Bağlantı"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Xüsusi imkanlar"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Kommunal xidmətlər"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Məxfilik"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Tətbiqlər tərəfindən təmin edilir"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Displey"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Naməlum"</string> </resources> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 5efa223dcd9a..bc6037a28415 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Dodaj"</string> <string name="manage_users" msgid="1823875311934643849">"Upravljaj korisnicima"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Ovo obaveštenje ne podržava prevlačenje na podeljeni ekran"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WiFi nije dostupan"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritetni režim"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm je podešen"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Prilagodi zaključani ekran"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Otključajte da biste prilagodili zaključani ekran"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi nije dostupan"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokirana"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon su blokirani"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokiran"</string> @@ -1400,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Taster radnji"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Prevucite nagore i zadržite sa tri prsta. Dodirnite da biste videli više pokreta."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Koristite tastaturu da biste pregledali sve aplikacije"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pritisnite taster radnji u bilo kom trenutku. Dodirnite da biste videli više pokreta."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Dodatno zatamnjivanje je sada deo trake za osvetljenost"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Sada možete dodatno da zatamnite ekran smanjivanjem nivoa osvetljenosti pri vrhu ekrana. \n\nOvo najbolje funkcioniše kada ste u tamnom okruženju."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Ukloni prečicu za dodatno zatamnjivanje"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Uklonjena je prečica za dodatno zatamnjivanje. Da biste smanjili osvetljenost, koristite uobičajenu traku za osvetljenost."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Povezivanje"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Pristupačnost"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Uslužne aplikacije"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privatnost"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Obezbeđuju aplikacije"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Ekran"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Nepoznato"</string> </resources> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 435d8339f943..1f0c127f1ed9 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Дадаць"</string> <string name="manage_users" msgid="1823875311934643849">"Кіраванне карыстальнікамі"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Гэта апавяшчэнне нельга перацягнуць на падзелены экран."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Сетка Wi‑Fi недаступная"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Прыярытэтны рэжым"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Будзільнік зададзены"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Наладзіць экран блакіроўкі"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Разблакіруйце, каб наладзіць экран блакіроўкі"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Сетка Wi-Fi недаступная"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера заблакіравана"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера і мікрафон заблакіраваны"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Мікрафон заблакіраваны"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Клавіша дзеяння"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"Цяпер кіраваць дадатковым памяншэннем яркасці можна на панэлі яркасці"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Цяпер вы можаце дадаткова зацямніць экран, яшчэ больш панізіўшы ўзровень яркасці праз налады ўверсе экрана.\n\nГэта функцыя працуе лепш за ўсё ў цёмным асяроддзі."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Выдаліць хуткую каманду для дадатковага памяншэння яркасці"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Хуткая каманда для дадатковага памяншэння яркасці выдалена. Каб паменшыць яркасць, выкарыстоўвайце звычайную панэль яркасці."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Прыватнасць"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Забяспечваюцца праграмамі"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Экран"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Невядома"</string> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index adbc13ab590f..affe2607395b 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Добавяне към бележката"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Включване на връзката"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Не могат да се добавят връзки от други потребителски профили"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Запис на екрана"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Записът на екрана се обработва"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущо известие за сесия за записване на екрана"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Добавяне"</string> <string name="manage_users" msgid="1823875311934643849">"Потребители"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Това известие не поддържа плъзгане за разделяне на екрана"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi не е налице"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Приоритетен режим"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Будилникът е зададен"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Персонализ. на заключения екран"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Отключете, за да персонализирате заключения екран"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi не е налице"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Достъпът до камерата е блокиран"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Достъпът до камерата и микрофона е блокиран"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Достъпът до микрофона е блокиран"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Клавиш за действия"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"Функцията за допълнителнително затъмняване вече е част от лентата за яркостта"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Вече можете да затъмнявате екрана допълнително, като намалявате яркостта още повече от лентата в горната му част.\n\nТова е най-полезно, когато сте на тъмно място."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Премахване на прекия път за допълнително затъмняване"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Прекият път за допълнително затъмняване е премахнат. За да намалите яркостта, използвайте обикновената лента за управлението ѝ."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Поверителност"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Предоставено от приложения"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Екран"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Неизвестно"</string> </resources> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 2aa7786774f9..497730c49b67 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"নোটে যোগ করুন"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"লিঙ্ক যোগ করুন"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"অন্যান্য প্রোফাইল থেকে লিঙ্ক যোগ করা যাবে না"</string> <string name="screenrecord_title" msgid="4257171601439507792">"স্ক্রিন রেকর্ডার"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রিন রেকর্ডিং প্রসেস হচ্ছে"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রিন রেকর্ডিং সেশন চলার বিজ্ঞপ্তি"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"যোগ করুন"</string> <string name="manage_users" msgid="1823875311934643849">"ব্যবহারকারীদের ম্যানেজ করুন"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"\'স্প্লিটস্ক্রিন\' মোডে এই বিজ্ঞপ্তি টেনে আনা যাবে না"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ওয়াই-ফাই উপলভ্য নেই"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"প্রায়োরিটি মোড"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"অ্যালার্ম সেট করা হয়েছে"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"লক স্ক্রিন কাস্টমাইজ করুন"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"লক স্ক্রিন কাস্টমাইজ করতে আনলক করুন"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ওয়াই-ফাই উপলভ্য নয়"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ক্যামেরার অ্যাক্সেস ব্লক করা আছে"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ক্যামেরা এবং মাইক্রোফোনের অ্যাক্সেস ব্লক করা আছে"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"মাইক্রোফোনের অ্যাক্সেস ব্লক করা আছে"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"অ্যাকশন কী"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"\'অতিরিক্ত কম ব্রাইটনেস\' ফিচার এখন ব্রাইটনেস বারের একটি অংশ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"আপনি এখন স্ক্রিনের উপর থেকে ব্রাইটনেস লেভেল কমিয়েও, স্ক্রিন অতিরিক্ত কম ব্রাইট করতে পারবেন।\n\nআপনি অন্ধকার পরিবেশে থাকলে এটি সবথেকে ভালো কাজ করে।"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"\'অতিরিক্ত কম ব্রাইটনেস\' ফিচারের শর্টকাট সরান"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"\'অতিরিক্ত কম ব্রাইটনেস\' ফিচারের শর্টকাট সরানো হয়েছে। আপনার ব্রাইটনেস কম করতে, সাধারণ ব্রাইটনেস বার ব্যবহার করুন।"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"গোপনীয়তা"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"অ্যাপের তরফ থেকে দেওয়া"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ডিসপ্লে"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"অজানা"</string> </resources> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 4802af846eda..509bf6fbe9e1 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj u bilješku"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Uključi link"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Nije moguće dodati linkove s drugih profila"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Snimač ekrana"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađivanje snimka ekrana"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obavještenje za sesiju snimanja ekrana je u toku"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Dodaj"</string> <string name="manage_users" msgid="1823875311934643849">"Upravljajte korisnicima"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Ovo obavještenje ne podržava prevlačenje na podijeljeni ekran"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WiFi je nedostupan"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Način rada Prioriteti"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm je postavljen"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Prilagodi zaključani ekran"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Otključajte da prilagodite zaključani ekran"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi mreža nije dostupna"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokirana"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon su blokirani"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokiran"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tipka radnji"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Prevucite nagore i zadržite s tri prsta. Dodirnite da saznate za više pokreta."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Koristite tastaturu da pregledate sve aplikacije"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pritisnite tipku radnji bilo kada. Dodirnite da saznate za više pokreta."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Dodatno zatamnjenje je sada dio trake za osvijetljenost"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Sada možete dodatno zatamniti ekran daljnjim smanjenjem nivoa osvijetljenosti s vrha ekrana.\n\nOvo najbolje funkcionira u tamnom okruženju."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Ukloni prečicu za dodatno zatamnjenje"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Prečica za dodatno zatamnjenje je uklonjena. Da smanjite osvijetljenost, koristite običnu traku za osvijetljenost."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Povezivost"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Pristupačnost"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Uslužni programi"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privatnost"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Pružaju aplikacije"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Prikaz"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Nepoznato"</string> </resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 10fedd8ce7a4..8c9c59776c17 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Afegeix a una nota"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Inclou l\'enllaç"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"No es poden afegir enllaços des d\'altres perfils"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Gravació de pantalla"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processant gravació de pantalla"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificació en curs d\'una sessió de gravació de la pantalla"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Afegeix"</string> <string name="manage_users" msgid="1823875311934643849">"Gestiona usuaris"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Aquesta notificació no es pot arrossegar a la pantalla dividida"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi no disponible"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Mode Prioritat"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarma definida"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Personalitza pantalla de bloqueig"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desbloqueja per personalitzar la pantalla de bloqueig"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"No hi ha cap Wi‑Fi disponible"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"La càmera està bloquejada"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"La càmera i el micròfon estan bloquejats"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"El micròfon està bloquejat"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla d\'acció"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Llisca cap amunt amb tres dits i mantén premut. Toca per aprendre més gestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Utilitza el teclat per veure totes les aplicacions"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Prem la tecla d\'acció en qualsevol moment. Toca per aprendre més gestos."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Atenuació extra ara forma part de la barra de brillantor"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Ara pots atenuar encara més la pantalla abaixant-ne el nivell de brillantor des de la part superior.\n\nFunciona millor si et trobes en un lloc fosc."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Suprimeix la drecera d\'atenuació extra"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"S\'ha suprimit la drecera d\'atenuació extra. Per abaixar la brillantor, utilitza la barra de brillantor normal."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Connectivitat"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Accessibilitat"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utilitats"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privadesa"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Proporcionat per aplicacions"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Pantalla"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Desconegut"</string> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index f995b294a477..6d2328e539e9 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Přidat"</string> <string name="manage_users" msgid="1823875311934643849">"Spravovat uživatele"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Toto oznámení nepodporuje přetažení na rozdělenou obrazovku"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Síť Wi‑Fi není k dispozici"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritní režim"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Je nastaven budík"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Přizpůsobit obrazovku uzamčení"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Obrazovku uzamčení upravíte, když zařízení odemknete"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Síť Wi-Fi není dostupná"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokována"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera a mikrofon jsou blokovány"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokován"</string> @@ -1400,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Akční klávesa"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Přejeďte třemi prsty nahoru a podržte je. Další gesta zjistíte klepnutím."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Zobrazení všech aplikací pomocí klávesnice"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Kdykoli stiskněte akční klávesu. Další gesta zjistíte klepnutím."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Na sloupci jasu lze nově nastavit velmi tmavou obrazovku"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Obrazovku můžete v horní části nastavit jako velmi tmavou tím, že ještě víc snížíte jas.\n\nNejlépe to funguje ve tmavém prostředí."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Odstranit zkratku pro velmi tmavou obrazovku"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Zkratka pro velmi tmavou obrazovku byla odstraněna. Jas můžete snížit pomocí standardního sloupce jasu."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Připojení"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Přístupnost"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Nástroje"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Ochrana soukromí"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Poskytováno aplikacemi"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Displej"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Neznámé"</string> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 3b74a6db4bdd..261cf33388ca 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Føj til note"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Inkluder link"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Der kan ikke tilføjes links fra andre profiler"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Skærmoptagelse"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skærmoptagelse"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Konstant notifikation om skærmoptagelse"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Tilføj"</string> <string name="manage_users" msgid="1823875311934643849">"Administrer brugere"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Denne notifikation kan ikke trækkes til en opdelt skærm"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Ingen tilgængelig Wi-Fi-forbindelse"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Tilstanden Prioritet"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarmen er indstillet"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Tilpas låseskærm"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Lås op for at tilpasse låseskærmen"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ikke tilgængeligt"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kameraet er blokeret"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Der er blokeret for kameraet og mikrofonen"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonen er blokeret"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Handlingstast"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Stryg opad, og hold tre fingre nede. Tryk for at lære flere bevægelser."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Brug dit tastatur til at se alle apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tryk på handlingstasten når som helst. Tryk for at lære flere bevægelser."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Ekstra dæmpet belysning er nu en del af lysstyrkebjælken"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Du kan nu dæmpe skærmens belysning ekstra meget ved at reducere lysstyrken endnu mere fra toppen af skærmen.\n\nDette fungerer bedst i mørke omgivelser."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Fjern genvejen til ekstra dæmpet belysning"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Genvejen til ekstra dæmpet belysning er fjernet. Brug den almindelige lysstyrkebjælke til at reducere lysstyrken."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Forbindelse"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Hjælpefunktioner"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Værktøjer"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privatliv"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Fra apps"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Skærm"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Ukendt"</string> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index fa7ad567e0b9..f0e1871cab28 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Zu Notiz hinzufügen"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Link einschließen"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Es dürfen keine Links aus anderen Profilen hinzugefügt werden"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Bildschirmaufzeichnung"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Bildschirmaufzeichnung…"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Fortlaufende Benachrichtigung für eine Bildschirmaufzeichnung"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Hinzufügen"</string> <string name="manage_users" msgid="1823875311934643849">"Nutzer verwalten"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Diese Benachrichtigung lässt sich nicht auf einen Splitscreen ziehen"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WLAN nicht verfügbar"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritätsmodus"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Wecker gestellt"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Sperrbildschirm personalisieren"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Zum Anpassen des Sperrbildschirms entsperren"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Kein WLAN verfügbar"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera blockiert"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera und Mikrofon blockiert"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon blockiert"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Aktionstaste"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,10 +1446,14 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Wische mit 3 Fingern nach oben und halte das Touchpad gedrückt. Tippe für mehr Infos zu Touch-Gesten."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Über die Tastatur alle Apps aufrufen"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Du kannst jederzeit die Aktionstaste drücken. Tippe für mehr Infos zu Touch-Gesten."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"„Extradunkel“ jetzt auf Helligkeitsleiste verfügbar"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Du kannst das Display jetzt extradunkel machen, indem du die Helligkeit vom oberen Displayrand aus noch weiter senkst.\n\nDas funktioniert in dunklen Umgebungen am besten."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Verknüpfung für „Extradunkel“ entfernen"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Verknüpfung für „Extradunkel“ wurde entfernt. Wenn du die Helligkeit reduzieren möchtest, verwende einfach die normale Helligkeitsleiste."</string> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> + <skip /> <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> <skip /> <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 26f1c5666c9c..16082cbba77c 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Προσθήκη σε σημείωση"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Συμπερίληψη συνδέσμου"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Δεν είναι δυνατή η προσθήκη συνδέσμων από άλλα προφίλ"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Εγγραφή οθόνης"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Επεξεργασία εγγραφής οθόνης"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ειδοποίηση σε εξέλιξη για μια περίοδο λειτουργίας εγγραφής οθόνης"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Προσθήκη"</string> <string name="manage_users" msgid="1823875311934643849">"Διαχ. χρηστών"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Αυτή η ειδοποίηση δεν υποστηρίζει τη μεταφορά με σύρσιμο για τον διαχωρισμό οθόνης"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Το Wi‑Fi δεν είναι διαθέσιμο"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Λειτουργία προτεραιότητας"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Το ξυπνητήρι ρυθμίστηκε"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Προσαρμογή οθόνης κλειδώματος"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Ξεκλειδώστε για προσαρμογή της οθόνης κλειδώματος"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Δεν υπάρχει διαθέσιμο δίκτυο Wi-Fi"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Η κάμερα έχει αποκλειστεί"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Η κάμερα και το μικρόφωνο έχουν αποκλειστεί"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Το μικρόφωνο έχει αποκλειστεί"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Πλήκτρο ενέργειας"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"Η επιπλέον μείωση φωτεινότητας είναι τώρα μέρος της γραμμής φωτεινότητας"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Τώρα μπορείτε να μειώσετε επιπλέον τη φωτεινότητα της οθόνης, χαμηλώνοντας το επίπεδο φωτεινότητας ακόμα περισσότερο από το επάνω μέρος της οθόνης.\n\nΑυτό λειτουργεί καλύτερα όταν βρίσκεστε σε σκοτεινό περιβάλλον."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Κατάργηση συντόμευσης επιπλέον μείωσης φωτεινότητας"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Η συντόμευση της επιπλέον μείωσης φωτεινότητας καταργήθηκε. Για να χαμηλώσετε τη φωτεινότητα, χρησιμοποιήστε την κανονική γραμμή φωτεινότητας."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Απόρρητο"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Παρέχεται από εφαρμογές"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Προβολή"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Άγνωστο"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 24922ac29c7e..e0bf0d67faa5 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Include link"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Links can\'t be added from other profiles"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Screen recorder"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Add"</string> <string name="manage_users" msgid="1823875311934643849">"Manage users"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"This notification does not support dragging to split screen"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi unavailable"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm set"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Customise lock screen"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Unlock to customise lock screen"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera is blocked"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone is blocked"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Action key"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extra dim is now part of the brightness bar"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"You can now make the screen extra dim by lowering the brightness level even further from the top of your screen.\n\nThis works best when you\'re in a dark environment."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remove extra dim shortcut"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Extra dim shortcut removed. To lower your brightness, use the regular brightness bar."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Connectivity"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Accessibility"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utilities"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privacy"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Provided by apps"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Display"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Unknown"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 88f175393e0c..6f626e94dd1f 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -1289,6 +1289,7 @@ <string name="add" msgid="81036585205287996">"Add"</string> <string name="manage_users" msgid="1823875311934643849">"Manage users"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"This notification does not support dragging to split screen"</string> + <string name="dream_overlay_location_active" msgid="6484763493158166618">"Location active"</string> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi unavailable"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm set"</string> @@ -1345,6 +1346,7 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Customize lock screen"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Unlock to customize lock screen"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string> + <string name="location_active_dream_overlay_content_description" msgid="6208885541020673916">"Location active"</string> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera blocked"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone blocked"</string> @@ -1400,7 +1402,7 @@ <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_action_key_button" msgid="3220074511852927267">"Action key"</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> @@ -1410,6 +1412,10 @@ <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_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_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> @@ -1433,10 +1439,10 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extra dim is now part of the brightness bar"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"You can now make the screen extra dim by lowering the brightness level even further from the top of your screen.\n\nThis works best when you\'re in a dark environment."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remove extra dim shortcut"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Extra dim shortcut removed. To lower your brightness, use the regular brightness bar."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"Extra dim is now part of the brightness slider"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"You can now make the screen extra dim by lowering the brightness level even further.\n\nSince this feature is now part of the brightness slider, extra dim shortcuts are being removed."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"Remove extra dim shortcuts"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"Extra dim shortcuts removed"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Connectivity"</string> <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Accessibility"</string> <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utilities"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 24922ac29c7e..e0bf0d67faa5 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Include link"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Links can\'t be added from other profiles"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Screen recorder"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Add"</string> <string name="manage_users" msgid="1823875311934643849">"Manage users"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"This notification does not support dragging to split screen"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi unavailable"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm set"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Customise lock screen"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Unlock to customise lock screen"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera is blocked"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone is blocked"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Action key"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extra dim is now part of the brightness bar"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"You can now make the screen extra dim by lowering the brightness level even further from the top of your screen.\n\nThis works best when you\'re in a dark environment."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remove extra dim shortcut"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Extra dim shortcut removed. To lower your brightness, use the regular brightness bar."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Connectivity"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Accessibility"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utilities"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privacy"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Provided by apps"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Display"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Unknown"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 24922ac29c7e..e0bf0d67faa5 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Include link"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Links can\'t be added from other profiles"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Screen recorder"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Add"</string> <string name="manage_users" msgid="1823875311934643849">"Manage users"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"This notification does not support dragging to split screen"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi unavailable"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm set"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Customise lock screen"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Unlock to customise lock screen"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera is blocked"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone is blocked"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Action key"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extra dim is now part of the brightness bar"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"You can now make the screen extra dim by lowering the brightness level even further from the top of your screen.\n\nThis works best when you\'re in a dark environment."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remove extra dim shortcut"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Extra dim shortcut removed. To lower your brightness, use the regular brightness bar."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Connectivity"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Accessibility"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utilities"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privacy"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Provided by apps"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Display"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Unknown"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index e8b32060b03f..936b64dfc575 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -1289,6 +1289,7 @@ <string name="add" msgid="81036585205287996">"Add"</string> <string name="manage_users" msgid="1823875311934643849">"Manage users"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"This notification does not support dragging to split screen"</string> + <string name="dream_overlay_location_active" msgid="6484763493158166618">"Location active"</string> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi unavailable"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm set"</string> @@ -1345,6 +1346,7 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Customize lock screen"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Unlock to customize lock screen"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string> + <string name="location_active_dream_overlay_content_description" msgid="6208885541020673916">"Location active"</string> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera blocked"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone blocked"</string> @@ -1400,7 +1402,7 @@ <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_action_key_button" msgid="3220074511852927267">"Action key"</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> @@ -1410,6 +1412,10 @@ <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_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_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> @@ -1433,10 +1439,10 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe up and hold using three fingers. Tap to learn more gestures."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use your keyboard to view all apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Press the action key at any time. Tap to learn more gestures."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extra dim is now part of the brightness bar"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"You can now make the screen extra dim by lowering the brightness level even further from the top of your screen.\n\nThis works best when you\'re in a dark environment."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remove extra dim shortcut"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Extra dim shortcut removed. To lower your brightness, use the regular brightness bar."</string> + <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="910988771011857460">"Extra dim is now part of the brightness slider"</string> + <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="4453123359258743230">"You can now make the screen extra dim by lowering the brightness level even further.\n\nSince this feature is now part of the brightness slider, extra dim shortcuts are being removed."</string> + <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="3947537827396916005">"Remove extra dim shortcuts"</string> + <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="165474092660941104">"Extra dim shortcuts removed"</string> <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Connectivity"</string> <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Accessibility"</string> <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utilities"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 42c35109be8a..96af732e3a40 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Agregar a la nota"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Incluir vínculo"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"No se pueden agregar vínculos desde otros perfiles"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Grabadora de pantalla"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación pantalla"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación constante para una sesión de grabación de pantalla"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Agregar"</string> <string name="manage_users" msgid="1823875311934643849">"Administrar usuarios"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Esta notificación no admite arrastrar entre pantallas divididas"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"La red Wi-Fi no está disponible"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modo prioridad"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Se estableció la alarma"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar pantalla de bloqueo"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desbloquea para personalizar la pantalla de bloqueo"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi no disponible"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"La cámara está bloqueada"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"La cámara y el micrófono están bloqueados"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"El micrófono está bloqueado"</string> @@ -1393,21 +1396,16 @@ <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícono de contraer"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícono de expandir"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string> - <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) --> - <skip /> - <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) --> - <skip /> - <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) --> - <skip /> - <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) --> - <skip /> - <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) --> - <skip /> - <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) --> - <skip /> + <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"Navega con el teclado"</string> + <string name="launch_keyboard_tutorial_notification_content" msgid="2880339951512757918">"Aprende combinaciones de teclas"</string> + <string name="launch_touchpad_tutorial_notification_title" msgid="2243780062772196901">"Navega con el panel táctil"</string> + <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de acción"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1417,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1440,10 +1446,14 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Desliza hacia arriba con tres dedos y mantenlos presionados. Presiona para aprender más gestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa el teclado para ver todas las apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Presiona la tecla de acción en cualquier momento. Presiona para aprender más gestos."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"La atenuación extra ahora es parte de la barra de brillo"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Ahora puedes bajar el nivel del brillo desde la parte superior de la pantalla para atenuarla aún más.\n\nEsto funciona mejor si estás en un ambiente oscuro."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Quitar la combinación de teclas de atenuación extra"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Se quitó el atajo de atenuación extra. Para bajar el brillo, usa la barra de brillo normal."</string> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> + <skip /> <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> <skip /> <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 6595258bc8e8..fb8ceeccf442 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Añadir"</string> <string name="manage_users" msgid="1823875311934643849">"Gestionar usuarios"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Esta notificación no se puede arrastrar a la pantalla dividida"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi no disponible"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modo prioritario"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarma añadida"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar pantalla de bloqueo"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desbloquea para personalizar la pantalla de bloqueo"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Red Wi-Fi no disponible"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Cámara bloqueada"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Cámara y micrófono bloqueados"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micrófono bloqueado"</string> @@ -1392,21 +1396,16 @@ <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icono de contraer"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icono de desplegar"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string> - <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) --> - <skip /> - <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) --> - <skip /> - <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) --> - <skip /> - <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) --> - <skip /> - <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) --> - <skip /> - <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) --> - <skip /> + <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"Desplázate con el teclado"</string> + <string name="launch_keyboard_tutorial_notification_content" msgid="2880339951512757918">"Aprende combinaciones de teclas"</string> + <string name="launch_touchpad_tutorial_notification_title" msgid="2243780062772196901">"Desplázate con el panel táctil"</string> + <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de acción"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1416,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1439,10 +1446,14 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Desliza hacia arriba y mantén pulsado con tres dedos. Toca para aprender a usar más gestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa el teclado para ver todas las aplicaciones"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pulsa la tecla de acción en cualquier momento. Toca para aprender a usar más gestos."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"La atenuación extra ahora forma parte de la barra de brillo"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Ahora puedes atenuar aún más tu pantalla reduciendo el nivel de brillo desde la parte superior.\n\nFunciona mejor cuando estás en un lugar con poca luz."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Eliminar acceso directo a la atenuación extra"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Acceso directo a la atenuación extra eliminado. Para reducir el brillo, usa la barra de brillo normal."</string> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> + <skip /> <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> <skip /> <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 7042ac136845..430fcf0e16cf 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Lisa märkmesse"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Kaasa link"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Teistelt profiilidelt ei saa linke lisada"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Ekraanisalvesti"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekraanisalvestuse töötlemine"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pooleli märguanne ekraanikuva salvestamise seansi puhul"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Lisa"</string> <string name="manage_users" msgid="1823875311934643849">"Kasutajate haldamine"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"See märguanne ei toeta jagatud ekraanikuvale lohistamist."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WiFi pole saadaval"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Režiim Prioriteetne"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm on määratud"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Kohanda lukustuskuva"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Lukustuskuva kohandamiseks avage"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi pole saadaval"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kaamera on blokeeritud"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kaamera ja mikrofon on blokeeritud"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon on blokeeritud"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Toiminguklahv"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pühkige kolme sõrmega üles ja hoidke sõrmi plaadil. Puudutage žestide kohta lisateabe saamiseks."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Klaviatuuri kasutamine kõigi rakenduste kuvamiseks"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Vajutage soovitud ajal toiminguklahvi. Puudutage žestide kohta lisateabe saamiseks."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Funktsioon „Eriti tume“ on nüüd osa ereduse reguleerimise ribast"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Nüüd saate muuta ekraani eriti tumedaks, vähendades ereduse taset ekraani ülaosast veelgi rohkem.\n\nSee toimib kõige paremini hämaras keskkonnas."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Eemalda funktsiooni „Eriti tume“ otsetee"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Funktsiooni „Eriti tume“ otsetee eemaldati. Kasutage ereduse vähendamiseks tavapärast ereduse reguleerimise riba."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Ühenduvus"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Juurdepääsetavus"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utiliidid"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privaatsus"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Rakendustelt"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Kuva"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Teadmata"</string> </resources> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index e51e37530751..ef6990c260cd 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Gehitu oharrean"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Sartu esteka"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Ezin da beste profiletako estekarik gehitu"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Pantaila-grabagailua"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pantaila-grabaketa prozesatzen"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pantailaren grabaketa-saioaren jakinarazpen jarraitua"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Gehitu"</string> <string name="manage_users" msgid="1823875311934643849">"Kudeatu erabiltzaileak"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Jakinarazpen hau ezin da arrastatu pantaila zatitura"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wifi-konexioa ez dago erabilgarri"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Lehentasun modua"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarma ezarrita dago"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Pertsonalizatu pantaila blokeatua"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desblokeatu eta pertsonalizatu pantaila blokeatua"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi-konexioa ez dago erabilgarri"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera blokeatuta dago"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera eta mikrofonoa blokeatuta daude"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonoa blokeatuta dago"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Ekintza-tekla"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pasatu 3 hatz gora eta eduki sakatuta. Sakatu keinu gehiago ikasteko."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Erabili teklatua aplikazio guztiak ikusteko"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Sakatu ekintza-tekla edonoiz. Sakatu keinu gehiago ikasteko."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Orain, argitasun-barran agertzen da Are ilunago"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Orain, pantaila are ilunago jar dezakezu, pantailaren goialdetik argitasun-maila are gehiago jaitsita.\n\nIngurune ilun batean zaudenean funtzionatzen du ondoen."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Kendu Are ilunago eginbidearen lasterbidea"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Kendu da Are ilunago eginbidearen lasterbidea. Argitasuna murrizteko, erabili argitasun-barra arrunta."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Konexioa"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Erabilerraztasuna"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Zerbitzu-aplikazioak"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Pribatutasuna"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Aplikazioenak"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Pantaila"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Ezezagunak"</string> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 13d403b1d274..7239b9b73928 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"افزودن"</string> <string name="manage_users" msgid="1823875311934643849">"مدیریت کاربران"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"این اعلان از عملکرد کشیدن به صفحهٔ دونیمه پشتیبانی نمیکند"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi دردسترس نیست"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"حالت اولویت"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"زنگ ساعت تنظیم شد"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"سفارشیسازی صفحه قفل"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"برای سفارشیسازی صفحه قفل، قفل را باز کنید"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi دردسترس نیست"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"دوربین مسدود شده است"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"دوربین و میکروفون مسدود شدهاند"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"میکروفون مسدود شده است"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"دکمه کنش"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"«بسیار کمنور» اکنون بخشی از نوار روشنایی است"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ازاینپس میتوانید با پایینتر آوردن سطح روشنایی از بالای صفحهنمایش، صفحهنمایش را بسیار کمنور کنید.\n\nاین ویژگی زمانی بهترین عملکرد را دارد که در محیطی تاریک باشید."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"حذف میانبر «بسیار کمنور»"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"میانبر «بسیار کمنور» حذف شد. برای کم کردن روشنایی، از نوار معمول روشنایی استفاده کنید."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"حریم خصوصی"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"ارائهشده از برنامهها"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"نمایشگر"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"نامشخص"</string> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index ab31329cf26c..d0133c73c227 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Lisää muistiinpanoon"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Lisää linkki"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Linkkejä ei voi lisätä muista profiileista"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Näytön tallentaja"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Näytön tallennusta käsitellään"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pysyvä ilmoitus näytön tallentamisesta"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Lisää"</string> <string name="manage_users" msgid="1823875311934643849">"Ylläpidä käyttäjiä"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Ilmoitus ei tue jaetulle näytölle vetämistä"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi ei ole saatavilla"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Tärkeät-tila"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Hälytys asetettu"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Muokkaa lukitusnäyttöä"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Voit muokata lukitusnäyttöä, kun avaat lukituksen"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi-yhteys ei ole käytettävissä"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera estetty"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera ja mikrofoni estetty"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofoni estetty"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Toimintonäppäin"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pyyhkäise ylös ja pidä kosketuslevyä painettuna kolmella sormella. Lue lisää eleistä napauttamalla."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Kaikkien sovellusten näkeminen näppäimistön avulla"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Voit painaa toimintonäppäintä milloin tahansa. Lue lisää eleistä napauttamalla."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Erittäin himmeä on nyt osa kirkkauspalkkia"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Voit nyt tehdä näytöstä erittäin himmeän vähentämällä kirkkautta vieläkin enemmän näytön yläreunasta.\n\nTämä toimii parhaiten pimeässä ympäristössä."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Poista erittäin himmeä ‑pikakomento"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Erittäin himmeä ‑pikakomento poistettu. Voit vähentää kirkkautta tavallisesta kirkkauspalkista."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Yhteydet"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Saavutettavuus"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Apusovellukset"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Yksityisyys"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Sovellusten tarjoama"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Näyttö"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Tuntematon"</string> </resources> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index ecb17f9ca1ed..95d7707b8151 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ajouter à une note"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Inclure le lien"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Des liens ne peuvent pas être ajoutés à partir d\'autres profils"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Enregistreur d\'écran"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Trait. de l\'enregist. d\'écran…"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement d\'écran"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Ajouter"</string> <string name="manage_users" msgid="1823875311934643849">"Gérer utilisateurs"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Cette notification ne prend pas en charge l\'écran partagé par glissement"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi-Fi non disponible"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Mode priorité"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"L\'alarme a été réglée"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Personn. l\'écran de verrouillage"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Déverrouiller pour personnaliser l\'écran de verrouillage"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non accessible"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Appareil photo bloqué"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Appareil photo et microphone bloqués"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone bloqué"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Touche d\'action"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,10 +1446,14 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Balayez l\'écran vers le haut avec trois doigts et maintenez-les en place. Touchez pour apprendre d\'autres gestes."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Utiliser votre clavier pour afficher toutes les applis"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Appuyez sur la touche d\'action à tout moment. Touchez pour apprendre d\'autres gestes."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"La réduction supplémentaire de la luminosité fait désormais partie de la barre de luminosité"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Vous pouvez désormais rendre l\'écran encore plus sombre en réduisant davantage le niveau de luminosité à partir du haut de l\'écran.\n\nCela fonctionne mieux lorsque vous êtes dans un environnement sombre."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Retirer le raccourci de réduction supplémentaire de la luminosité"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Le raccourci de réduction supplémentaire de la luminosité à été retiré. Pour réduire la luminosité, utilisez la barre de luminosité habituelle."</string> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> + <skip /> <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> <skip /> <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index c023f1b0f42e..ee0f98728cbc 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ajouter à la note"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Inclure le lien"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Impossible d\'ajouter des liens depuis d\'autres profils"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Enregistreur d\'écran"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Enregistrement de l\'écran…"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement de l\'écran"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Ajouter"</string> <string name="manage_users" msgid="1823875311934643849">"Gérer utilisateurs"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Impossible de faire glisser cette notification vers l\'écran partagé"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi non disponible"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Mode Prioritaire"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarme réglée"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Personnaliser écran verrouillage"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Déverrouillez pour personnaliser l\'écran de verrouillage"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponible"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Caméra bloquée"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Caméra et micro bloqués"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micro bloqué"</string> @@ -1393,21 +1396,16 @@ <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icône Réduire"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icône Développer"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string> - <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) --> - <skip /> - <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) --> - <skip /> - <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) --> - <skip /> - <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) --> - <skip /> - <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) --> - <skip /> - <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) --> - <skip /> + <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"Naviguer à l\'aide du clavier"</string> + <string name="launch_keyboard_tutorial_notification_content" msgid="2880339951512757918">"Découvrir les raccourcis clavier"</string> + <string name="launch_touchpad_tutorial_notification_title" msgid="2243780062772196901">"Naviguer à l\'aide de votre pavé tactile"</string> + <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Touche d\'action"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1417,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1440,10 +1446,14 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Balayez vers le haut en utilisant trois doigts et maintenez. Appuyez pour apprendre d\'autres gestes."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Utilisez votre clavier pour afficher toutes les applis"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Appuyez sur la touche d\'action à tout moment. Appuyez pour apprendre d\'autres gestes."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Luminosité ultra-réduite fait désormais partie de la barre de luminosité"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Désormais, vous pouvez rendre l\'écran encore plus sombre en abaissant davantage le niveau de luminosité en haut de l\'écran.\n\nCela fonctionne mieux lorsque vous êtes dans un environnement sombre."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Supprimer le raccourci Luminosité ultra-réduite"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Raccourci Luminosité ultra-réduite supprimé. Pour diminuer la luminosité, utilisez la barre de luminosité habituelle."</string> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> + <skip /> <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> <skip /> <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index b525bb8f1234..921409500172 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Engadir a unha nota"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Incluír ligazón"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Non se poden engadir ligazóns desde outros perfís"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Gravadora da pantalla"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando gravación pantalla"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación de actividade en curso sobre unha sesión de gravación de pantalla"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Engadir"</string> <string name="manage_users" msgid="1823875311934643849">"Usuarios"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Esta notificación non pode arrastrarse á pantalla dividida"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"A wifi non está dispoñible"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modo de prioridade"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarma definida"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar pantalla de bloqueo"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Para personalizar a pantalla de bloqueo, primeiro desbloquea o dispositivo"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi non dispoñible"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"A cámara está bloqueada"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"A cámara e o micrófono están bloqueados"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"O micrófono está bloqueado"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de acción"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Pasa tres dedos cara arriba e mantenos premidos. Toca para obter máis información sobre os xestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa o teclado para ver todas as aplicacións"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Preme a tecla de acción cando queiras. Toca para obter máis información sobre os xestos."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"A atenuación extra agora está incluída na barra de brillo"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Agora podes aumentar a atenuación da pantalla: só tes que baixar o nivel de brillo aínda máis desde a parte superior.\n\nEsta opción funciona mellor se estás nun ambiente escuro."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Quitar atallo de atenuación extra"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Quitouse o atallo de atenuación extra. Para reducir o brillo, usa a barra de brillo normal."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Conectividade"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Accesibilidade"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utilidades"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privacidade"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Provenientes de aplicacións"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Visualización"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Categoría descoñecida"</string> </resources> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 9afbf8e4f857..f4de6cadc3aa 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"ઉમેરો"</string> <string name="manage_users" msgid="1823875311934643849">"વપરાશકર્તાઓને મેનેજ કરો"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"આ નોટિફિકેશન તેને વિભાજિત સ્ક્રીનમાં ખેંચવાની સુવિધાને સપોર્ટ કરતું નથી"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"વાઇ-ફાઇ ઉપલબ્ધ નથી"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"પ્રાધાન્યતા મોડ"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"અલાર્મ સેટ"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"લૉક સ્ક્રીન કસ્ટમાઇઝ કરો"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"લૉક સ્ક્રીનને કસ્ટમાઇઝ કરવા માટે અનલૉક કરો"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"વાઇ-ફાઇ ઉપલબ્ધ નથી"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"કૅમેરા બ્લૉક કરેલો છે"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"કૅમેરા અને માઇક્રોફોન બ્લૉક કરેલા છે"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"માઇક્રોફોન બ્લૉક કરેલો છે"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"ઍક્શન કી"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"બ્રાઇટનેસ બાર હવે એક્સ્ટ્રા ડિમનો ભાગ છે"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"તમે હવે તમારી સ્ક્રીનના સૌથી ઉપરના ભાગમાંથી બ્રાઇટનેસ લેવલને હજી પણ ઘટાડીને સ્ક્રીનને એક્સ્ટ્રા ડિમ બનાવી શકો છો.\n\nતમે ડાર્ક વાતાવરણમાં હો, ત્યારે આ શ્રેષ્ઠ રીતે કામ કરે છે."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"એક્સ્ટ્રા ડિમ શૉર્ટકટ કાઢી નાખો"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"એક્સ્ટ્રા ડિમ શૉર્ટકટ કાઢી નાખ્યો. તમારી બ્રાઇટનેસ ઘટાડવા માટે, નિયમિત બ્રાઇટનેસ બારનો ઉપયોગ કરો."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"પ્રાઇવસી"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"ઍપ દ્વારા પ્રદાન કરવામાં આવેલી"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ડિસ્પ્લે"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"અજાણ"</string> </resources> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 2b28b7a12522..b9af7739e817 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -253,7 +253,7 @@ <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN चालू."</string> <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> प्रतिशत बैटरी."</string> <string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"बैटरी <xliff:g id="PERCENTAGE">%1$d</xliff:g> प्रतिशत चार्ज है, जो कि <xliff:g id="TIME">%2$s</xliff:g> चल जाएगी"</string> - <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"बैटरी चार्ज हो रही है, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> प्रतिशत."</string> + <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"बैटरी चार्ज हो रही है, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string> <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"बैटरी <xliff:g id="PERCENTAGE">%d</xliff:g> प्रतिशत चार्ज हुई. बैटरी खराब होने से बचाने के लिए, चार्जिंग रोक दी गई है."</string> <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"बैटरी <xliff:g id="PERCENTAGE">%1$d</xliff:g> प्रतिशत चार्ज हुई, जो कि <xliff:g id="TIME">%2$s</xliff:g> चल जाएगी. बैटरी खराब होने से बचाने के लिए, चार्जिंग रोक दी गई है."</string> <string name="accessibility_overflow_action" msgid="8555835828182509104">"पूरी सूचनाएं देखें"</string> @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"जोड़ें"</string> <string name="manage_users" msgid="1823875311934643849">"उपयोगकर्ताओं को मैनेज करें"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"इस सूचना को स्प्लिट स्क्रीन मोड में, खींचा और छोड़ा नहीं जा सकता"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"वाई-फ़ाई उपलब्ध नहीं है"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"प्राथमिकता मोड"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"अलार्म सेट किया गया"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"लॉक स्क्रीन को पसंद के मुताबिक बनाएं"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"लॉक स्क्रीन को पसंद के मुताबिक बनाने के लिए अनलॉक करें"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"वाई-फ़ाई उपलब्ध नहीं है"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"कैमरे का ऐक्सेस नहीं है"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"कैमरे और माइक्रोफ़ोन का ऐक्सेस नहीं है"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"माइक्रोफ़ोन का ऐक्सेस नहीं है"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"ऐक्शन बटन"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"स्क्रीन की रोशनी को सामान्य लेवल से और कम करने की सुविधा, अब ब्राइटनेस बार का हिस्सा है"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"अब स्क्रीन के सबसे ऊपरी हिस्से से, स्क्रीन की रोशनी सामान्य लेवल से और कम की जा सकती है.\n\nयह सुविधा, अंधेरे वाली जगह पर बेहतर तरीके से काम करती है."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"स्क्रीन की रोशनी को सामान्य लेवल से और कम करने की सुविधा का शॉर्टकट हटाएं"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"स्क्रीन की रोशनी को सामान्य लेवल से और कम करने की सुविधा का शॉर्टकट हटा दिया गया. स्क्रीन की रोशनी कम करने के लिए, ब्राइटनेस बार का इस्तेमाल करें."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"निजता"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"ऐप्लिकेशन से मिली जानकारी"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"डिसप्ले"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"कोई जानकारी नहीं है"</string> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 34bccbd6229e..c34c07e52d10 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj bilješci"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Uključi vezu"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Veze se ne mogu dodati s drugih profila"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Snimač zaslona"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrada snimanja zaslona"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Tekuća obavijest za sesiju snimanja zaslona"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Dodaj"</string> <string name="manage_users" msgid="1823875311934643849">"Upravljanje korisnicima"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Ova obavijest ne podržava povlačenje na podijeljeni zaslon."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi nije dostupan"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritetni način rada"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm je postavljen"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Prilagodite zaključavanje zaslona"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Otključajte da biste prilagodili zaključani zaslon"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nije dostupan"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokirana"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Blokirani su kamera i mikrofon"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokiran"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tipka za radnju"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Prijeđite prema gore trima prstima i zadržite pritisak. Dodirnite da biste naučili više pokreta."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Upotrijebite tipkovnicu za prikaz svih aplikacija"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pritisnite tipku za radnju u bilo kojem trenutku. Dodirnite da biste naučili više pokreta."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Dodatno zatamnjenje sada je dio trake za svjetlinu"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Zaslon možete dodatno zatamniti daljnjim smanjivanjem razine svjetline na vrhu zaslona.\n\nTo najbolje funkcionira kada ste u tamnom okruženju."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Ukloni prečac za dodatno zatamnjenje"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Prečac za dodatno zatamnjenje je uklonjen. Da biste smanjili svjetlinu, upotrijebite regularnu traku za svjetlinu."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Povezivost"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Pristupačnost"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Uslužni programi"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privatnost"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Pružaju aplikacije"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Prikaz"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Nepoznato"</string> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index cc2f66e1a04a..abc7bd0d5bba 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Hozzáadás jegyzethez"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Linkkel együtt"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Más profilokból nem lehet linkeket hozzáadni"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Képernyőrögzítő"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Képernyőrögzítés feldolgozása"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Folyamatban lévő értesítés képernyőrögzítési munkamenethez"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Hozzáadás"</string> <string name="manage_users" msgid="1823875311934643849">"Kezelés"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Az értesítés nem támogatja az osztott képernyőre való áthúzást."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"A Wi‑Fi nem áll rendelkezésre"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritás mód"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Ébresztő beállítva"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Lezárási képernyő testreszabása"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Oldja fel a zárolást a lezárási képernyő testreszabásához"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Nem áll rendelkezésre Wi-Fi"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera letiltva"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera és mikrofon letiltva"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon letiltva"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Műveletbillentyű"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Gyúsztason felfelé három ujjal, és tartsa lenyomva az ujjait. Koppintson a további kézmozdulatokért."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"A billentyűzet használatával valamennyi alkalmazás megtekinthető"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"A műveletbillentyű bármikor használható. Koppintson a további kézmozdulatokért."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Az extrasötét funkció mostantól része a fényerő-beállítási sávnak"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"A képernyő tetején mostantól extrasötétre állíthatja a képernyőt, amivel a korábbinál még jobban csökkentheti a fényerőt.\n\nA funkció sötét környezetben használható a legjobban."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Az extrasötét funkció gyorsparancsának eltávolítása"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Eltávolította az extrasötét funkció gyorsparancsát. A fényerő csökkentéséhez használja a fényerő-beállítási sávot."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Kapcsolódás"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Kisegítő lehetőségek"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Segédprogramok"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Adatvédelem"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Alkalmazás által biztosított"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Kijelző"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Ismeretlen"</string> </resources> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index c017263b2810..d25cb52389a1 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ավելացնել նշմանը"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Ներառել հղումը"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Այլ պրոֆիլներից հնարավոր չէ հղումներ ավելացնել"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Էկրանի տեսագրում"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Էկրանի տեսագրության մշակում"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Էկրանի տեսագրման աշխատաշրջանի ընթացիկ ծանուցում"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Ավելացնել"</string> <string name="manage_users" msgid="1823875311934643849">"Կառավարել"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Այս ծանուցումը հնարավոր չէ քաշել տրոհված էկրանի մեկ հատվածից մյուսը"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi-ը հասանելի չէ"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Առաջնահերթության ռեժիմ"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Զարթուցիչը դրված է"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Անհատականացնել կողպէկրանը"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Ապակողպեք սարքը՝ կողպէկրանը կարգավորելու համար"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ցանց հասանելի չէ"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Տեսախցիկն արգելափակված է"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Տեսախցիկն ու խոսափողը արգելափակված են"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Խոսափողն արգելափակված է"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Գործողության ստեղն"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"Հավելյալ խամրեցումն այժմ պայծառության գոտում է"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Էկրանը հավելյալ խամրեցնելու համար բացեք կարգավորումները էկրանի վերևի մասից։\n\nԽորհուրդ ենք տալիս օգտագործել այս գործառույթը, երբ շուրջը մութ է։"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Հեռացնել հավելյալ խամրեցման դյուրանցումը"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Հավելյալ խամրեցման դյուրանցումը հեռացվեց։ Պայծառության մակարդակը նվազեցնելու համար օգտագործեք պայծառության գոտին։"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Գաղտնիություն"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Տրամադրվել են հավելվածների կողմից"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Էկրան"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Անհայտ"</string> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index a3ea9b26c49e..bf1085d2f387 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Tambahkan ke catatan"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Sertakan link"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Link tidak dapat ditambahkan dari profil lain"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Perekam Layar"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses perekaman layar"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifikasi yang sedang berjalan untuk sesi rekaman layar"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Tambahkan"</string> <string name="manage_users" msgid="1823875311934643849">"Kelola pengguna"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Notifikasi ini tidak mendukung fitur tarik ke layar terpisah"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi tidak tersedia"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Mode prioritas"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm disetel"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Sesuaikan layar kunci"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Buka kunci untuk menyesuaikan layar kunci"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi tidak tersedia"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera diblokir"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera dan mikrofon diblokir"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon diblokir"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tombol tindakan"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Geser ke atas dan tahan menggunakan tiga jari. Ketuk untuk mempelajari gestur lainnya."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gunakan keyboard untuk melihat semua aplikasi"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tekan tombol tindakan kapan saja. Ketuk untuk mempelajari gestur lainnya."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Ekstra redup kini menjadi bagian dari panel kecerahan"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Anda kini dapat membuat layar menjadi ekstra redup dengan menurunkan tingkat kecerahan lebih banyak lagi dari bagian atas layar.\n\nFitur ini berfungsi optimal saat Anda berada di tempat yang gelap."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Hapus pintasan ekstra redup"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Pintasan ekstra redup dihapus. Untuk menurunkan kecerahan, gunakan panel kecerahan biasa."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Konektivitas"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Aksesibilitas"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utilitas"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privasi"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Disediakan oleh aplikasi"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Tampilan"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Tidak diketahui"</string> </resources> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 2468bcc9f2c1..987a51de62aa 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Bæta við"</string> <string name="manage_users" msgid="1823875311934643849">"Stjórna notendum"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Þessi tilkynning styður ekki að draga yfir á skiptan skjá."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WiFi ekki tiltækt"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Forgangsstilling"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Vekjari stilltur"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Sérsníða lásskjá"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Taktu úr lás til að sérsníða lásskjá"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ekki til staðar"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Lokað fyrir myndavél"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Lokað fyrir myndavél og hljóðnema"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Lokað fyrir hljóðnema"</string> @@ -1400,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Aðgerðalykill"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Strjúktu upp og haltu með þremur fingrum. Ýttu til að læra fleiri bendingar."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Notaðu lyklaborðið til að sjá öll forrit"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Ýttu hvenær sem er á aðgerðalykilinn. Ýttu til að læra fleiri bendingar."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Nú er stillingin „mjög dökkt“ hluti af birtustigsstikunni"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Nú geturðu gert skjáinn mjög dökkan með því að lækka birtustigið enn frekar efst á skjánum.\n\nÞetta virkar best þegar umhverfi þitt er mjög dimmt."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Fjarlægja flýtilykil á mjög dökka stillingu"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Flýtilykill á mjög dökka stillingu fjarlægður. Notaðu hefðbundnu birtustigsstikuna til að lækka birtustigið."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Tengigeta"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Aðgengileiki"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Aukabúnaður"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Persónuvernd"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Frá forritum"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Skjár"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Óþekkt"</string> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 5ea4486f35af..e2733b1b51a6 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Aggiungi alla nota"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Includi link"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Impossibile aggiungere link da altri profili"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Registrazione dello schermo"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Elaborazione registrazione…"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifica costante per una sessione di registrazione dello schermo"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Aggiungi"</string> <string name="manage_users" msgid="1823875311934643849">"Gestisci utenti"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Non è possibile trascinare questa notifica tra le due parti dello schermo diviso"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi non disponibile"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modalità Priorità"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Sveglia impostata"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizza schermata di blocco"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Sblocca per personalizzare la schermata di blocco"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponibile"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Videocamera bloccata"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Videocamera e microfono bloccati"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfono bloccato"</string> @@ -1393,21 +1396,16 @@ <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icona Comprimi"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icona Espandi"</string> <string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"oppure"</string> - <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) --> - <skip /> - <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) --> - <skip /> - <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) --> - <skip /> - <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) --> - <skip /> - <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) --> - <skip /> - <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) --> - <skip /> + <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"Naviga usando la tastiera"</string> + <string name="launch_keyboard_tutorial_notification_content" msgid="2880339951512757918">"Informazioni sulle scorciatoie da tastiera"</string> + <string name="launch_touchpad_tutorial_notification_title" msgid="2243780062772196901">"Naviga usando il touchpad"</string> + <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tasto azione"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1417,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1440,10 +1446,14 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Scorri verso l\'alto e tieni premuto con tre dita. Tocca per scoprire altri gesti."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Usa la tastiera per visualizzare tutte le app"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Premi il tasto azione in qualsiasi momento. Tocca per scoprire altri gesti."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Ora l\'attenuazione extra è nella barra della luminosità"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Ora puoi usare l\'attenuazione extra per lo schermo abbassando il livello di luminosità ancora di più dalla parte superiore della schermata.\n\nQuesta funzionalità opera in modo ottimale quando ti trovi in un ambiente buio."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Rimuovi scorciatoia attenuazione extra"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Scorciatoia attenuazione extra rimossa. Per diminuire la luminosità, usa la normale barra della luminosità."</string> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> + <skip /> <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> <skip /> <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 5fd5ca6fcaf3..2a006a85c863 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"הוספה לפתק"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"הכנסת הקישור"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"לא ניתן להוסיף קישורים מפרופילים אחרים"</string> <string name="screenrecord_title" msgid="4257171601439507792">"מקליט המסך"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"מתבצע עיבוד של הקלטת מסך"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"התראה מתמשכת לסשן הקלטת מסך"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"הוספה"</string> <string name="manage_users" msgid="1823875311934643849">"ניהול משתמשים"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"ההתראה הזו לא תומכת בגרירה למסך מפוצל"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi לא זמין"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"מצב עדיפות"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ההתראה מוגדרת"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"התאמה אישית של מסך הנעילה"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"כדי להתאים אישית את מסך הנעילה, יש לבטל את הנעילה"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ה-Wi-Fi לא זמין"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"המצלמה חסומה"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"המצלמה והמיקרופון חסומים"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"המיקרופון חסום"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"מקש הפעולה"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,10 +1446,14 @@ <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="4369307638184799742">"התכונה \'מעומעם במיוחד\' נוספה לסרגל הבהירות"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"עכשיו אפשר להפוך את המסך למעומעם במיוחד באמצעות הפחתה נוספת של רמת הבהירות דרך החלק העליון במסך.\n\nהפעולה הזו עובדת הכי טוב בסביבה חשוכה."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"הסרה של קיצור הדרך לתכונה \'מעומעם במיוחד\'"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"קיצור הדרך לתכונה \'מעומעם במיוחד\' הוסר. כדי להפחית את הבהירות, אפשר להשתמש בסרגל הבהירות הרגיל."</string> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> + <skip /> <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> <skip /> <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 7897f4826155..780254f04131 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"追加"</string> <string name="manage_users" msgid="1823875311934643849">"ユーザーの管理"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"この通知は、分割画面へのドラッグをサポートしていません"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi-Fi を利用できません"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"優先順位モード"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"アラームを設定しました"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"ロック画面のカスタマイズ"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"ロック画面をカスタマイズするにはロックを解除してください"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi は利用できません"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"カメラはブロックされています"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"カメラとマイクはブロックされています"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"マイクはブロックされています"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"アクションキー"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"3 本の指で上にスワイプして長押しします。ジェスチャーの詳細を確認するにはタップしてください。"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"キーボードを使用して、すべてのアプリを表示する"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"アクションキーを押せばいつでも機能します。ジェスチャーの詳細を確認するにはタップしてください。"</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"「さらに輝度を下げる」機能が明るさのバーの追加されました"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"画面の上部で明るさを大幅に低く設定することで、画面の輝度をさらに下げられるようになりました。\n\nこの設定は暗い場所での操作に最適です。"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"「さらに輝度を下げる」のショートカットを削除する"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"「さらに輝度を下げる」のショートカットを削除しました。明るさを下げるには、通常の明るさのバーを使用してください。"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"プライバシー"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"アプリから提供"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ディスプレイ"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"不明"</string> </resources> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 5550a63ad9a2..dab26198eff2 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"დამატება"</string> <string name="manage_users" msgid="1823875311934643849">"მართვა"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"ამ შეტყობინების გადათრევა გაყოფილ ეკრანებს შორის არ არის მხარდაჭერილი."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi მიუწვდომელია"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"პრიორიტეტული რეჟიმი"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"მაღვიძარა დაყენებულია"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"ჩაკეთილი ეკრანის მორგება"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"ჩაკეტილი ეკრანის მოსარგებად გაბლოკეთ"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi მიუწვდომელია"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"კამერა დაბლოკილია"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"კამერა და მიკროფონი დაბლოკილია"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"მიკროფონი დაბლოკილია"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"მოქმედების კლავიში"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"დამატებითი დაბინდვის ფუქნცია ახლა განთავსებულია სიკაშკაშის პანელზე"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ახლა თქვენ შეგიძლიათ დამატებით დაბინდოთ ეკრანი მის ზედა ნაწილში სიკაშკაშის დონის კიდევ უფრო შემცირების გზით.\n\nეს ყველაზე უკეთ ბნელ გარემოში ყოფნისას მუშაობს."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"დამატებითი დაბინდვის მალსახმობის ამოშლა"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"დამატებითი დაბინდვის მალსახმობი ამოშლილია. სიკაშკაშის შესამცირებლად გამოიყენეთ სიკაშკაშის ჩვეულებრივი პანელი."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"კონფიდენციალურობა"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"მოწოდებულია აპების მიერ"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ეკრანი"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"უცნობი"</string> </resources> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index d8b454218ac2..53ef57ee8f08 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ескертпеге қосу"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Сілтеме қосу"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Сілтемелерді басқа профильдерден қосу мүмкін емес."</string> <string name="screenrecord_title" msgid="4257171601439507792">"Экран жазғыш"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экран жазғыш бейнесін өңдеу"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды бейнеге жазудың ағымдағы хабарландыруы"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Қосу"</string> <string name="manage_users" msgid="1823875311934643849">"Параметрлер"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Бұл хабарландыруды бөлінген экранға сүйреп апару мүмкін емес."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi қолжетімсіз"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Басымдық режимі"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Оятқыш орнатылды"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Құлып экранын бейімдеу"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Құлып экранын бейімдеу үшін құлыпты ашыңыз"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi қолжетімсіз."</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера блокталған."</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера мен микрофон блокталған."</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон блокталған."</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Әрекет пернесі"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"Экранды қарайту функциясын енді жарықтық панелінің бөлшегі болады"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Енді экранның жоғарғы бөлігінде жарықтық деңгейін түсіру арқылы экранды одан сайын қарайтуға болады.\n\nБұл мүмкіндіктің артықшылығын қараңғы жерде көруге болады."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Экранды қарайту жылдам пәрменін өшіру"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Экранды қарайту жылдам пәрмені өшірілді. Жарықтықты азайту үшін әдеттегі жарықтық панелін пайдаланыңыз."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Құпиялық"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Қолданбалар ұсынған"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Дисплей"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Белгісіз"</string> </resources> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index f2fc313a4bb2..e2bba53aed84 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"បញ្ចូល"</string> <string name="manage_users" msgid="1823875311934643849">"គ្រប់គ្រងអ្នកប្រើប្រាស់"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"ការជូនដំណឹងនេះមិនអាចឱ្យអូសដើម្បីបំបែកអេក្រង់បានទេ"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi ត្រូវបានបិទ"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"មុខងារអាទិភាព"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"រូបកំណត់ម៉ោងរោទ៍"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"ប្ដូរអេក្រង់ចាក់សោតាមបំណង"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"ដោះសោ ដើម្បីប្ដូរអេក្រង់ចាក់សោតាមបំណង"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"មិនមាន Wi-Fi ទេ"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"បានទប់ស្កាត់កាមេរ៉ា"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"បានទប់ស្កាត់កាមេរ៉ា និងមីក្រូហ្វូន"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"បានទប់ស្កាត់មីក្រូហ្វូន"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"គ្រាប់ចុចសកម្មភាព"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"ឥឡូវនេះ មុខងារងងឹតខ្លាំងក្លាយជាផ្នែកមួយនៃរបារពន្លឺ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ឥឡូវនេះ អ្នកអាចធ្វើឱ្យអេក្រង់ងងឹតខ្លាំងបានដោយបន្ថយកម្រិតពន្លឺបន្ថែមទៀតដោយចូលទៅកាន់ផ្នែកខាងលើនៃអេក្រង់របស់អ្នក។\n\nការធ្វើបែបនេះទទួលបានលទ្ធផលប្រសើរបំផុត ពេលអ្នកស្ថិតនៅកន្លែងងងឹត។"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"ដកផ្លូវកាត់មុខងារងងឹតខ្លាំងចេញ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"ផ្លូវកាត់មុខងារងងឹតខ្លាំងត្រូវបានដកចេញ។ ដើម្បីបន្ថយពន្លឺរបស់អ្នក សូមប្រើរបារពន្លឺធម្មតា។"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"ឯកជនភាព"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"ផ្ដល់ជូនដោយកម្មវិធី"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ផ្ទាំងបង្ហាញ"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"មិនស្គាល់"</string> </resources> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 6f6333299129..0b87cbb89b4d 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"ಸೇರಿಸಿ"</string> <string name="manage_users" msgid="1823875311934643849">"ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಹಿಸಿ"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ಗೆ ಡ್ರ್ಯಾಗ್ ಮಾಡುವುದನ್ನು ಈ ನೋಟಿಫಿಕೇಶನ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ವೈ-ಫೈ ಲಭ್ಯವಿಲ್ಲ"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ಆದ್ಯತೆ ಮೋಡ್"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ಅಲಾರಾಂ ಹೊಂದಿಸಲಾಗಿದೆ"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ ಕಸ್ಟಮೈಸ್ ಮಾಡಿ"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ವೈ-ಫೈ ಲಭ್ಯವಿಲ್ಲ"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ಕ್ಯಾಮರಾವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ರೊಫೋನ್ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"ಆ್ಯಕ್ಷನ್ ಕೀ"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"ಇನ್ನಷ್ಟು ಮಬ್ಬು ಈಗ ಬ್ರೈಟ್ನೆಸ್ ಬಾರ್ನ ಭಾಗವಾಗಿದೆ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲ್ಭಾಗದಿಂದ ಬ್ರೈಟ್ನೆಸ್ ಮಟ್ಟವನ್ನು ಇನ್ನಷ್ಟು ಕಡಿಮೆ ಮಾಡುವ ಮೂಲಕ ನೀವು ಈಗ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಇನ್ನಷ್ಟು ಮಬ್ಬುಗೊಳಿಸಬಹುದು.\n\nನೀವು ಕತ್ತಲೆಯ ವಾತಾವರಣದಲ್ಲಿರುವಾಗ ಇದು ಉತ್ತಮವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"ಇನ್ನಷ್ಟು ಮಬ್ಬು ಶಾರ್ಟ್ಕಟ್ ಅನ್ನು ತೆಗೆದುಹಾಕಿ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"ಇನ್ನಷ್ಟು ಮಬ್ಬು ಶಾರ್ಟ್ಕಟ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ. ನಿಮ್ಮ ಬ್ರೈಟ್ನೆಸ್ ಅನ್ನು ಕಡಿಮೆ ಮಾಡಲು, ಸಾಮಾನ್ಯ ಬ್ರೈಟ್ನೆಸ್ ಬಾರ್ ಬಳಸಿ."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"ಗೌಪ್ಯತೆ"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"ಆ್ಯಪ್ಗಳಿಂದ ಒದಗಿಸಲಾಗಿದೆ"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ಡಿಸ್ಪ್ಲೇ"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"ಅಪರಿಚಿತ"</string> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 75bc3b26f61c..4f4c5b99e5fa 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"메모에 추가"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"링크 포함"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g><xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"다른 프로필의 링크를 추가할 수 없습니다."</string> <string name="screenrecord_title" msgid="4257171601439507792">"화면 녹화"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"화면 녹화 처리 중"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"화면 녹화 세션에 관한 지속적인 알림"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"추가"</string> <string name="manage_users" msgid="1823875311934643849">"사용자 관리"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"드래그하여 화면을 분할하는 기능이 지원되지 않는 알림입니다."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi를 이용할 수 없습니다."</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"우선순위 모드입니다."</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"알람이 설정되었습니다."</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"잠금 화면 맞춤 설정"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"잠금 화면 맞춤설정을 위해 잠금 해제"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi를 사용할 수 없음"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"카메라 차단됨"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"카메라 및 마이크 차단됨"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"마이크 차단됨"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"작업 키"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"이제 \'더 어둡게\' 기능이 밝기 막대에 추가되었습니다"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"이제 화면 상단에서 밝기 수준을 더 낮춰 화면을 더 어둡게 만들 수 있습니다\n\n이 기능은 어두운 환경에서 가장 잘 작동합니다."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"\'더 어둡게\' 단축키 삭제"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"\'더 어둡게\' 단축키가 삭제되었습니다. 밝기를 낮추려면 일반 밝기 막대를 사용하세요."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"개인 정보 보호"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"앱에서 제공"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"디스플레이"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"알 수 없음"</string> </resources> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 9bf427c0bfb9..023d69ecbe04 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -243,7 +243,7 @@ <string name="accessibility_bluetooth_device_settings_gear" msgid="3314916468105272540">"Түзмөктүн чоо-жайын конфигурациялоо үчүн чыкылдатыңыз"</string> <string name="accessibility_bluetooth_device_settings_see_all" msgid="9111952496905423543">"Бардык түзмөктөрдү көрүү үчүн чыкылдатыңыз"</string> <string name="accessibility_bluetooth_device_settings_pair_new_device" msgid="2435184865793496966">"Жаңы түзмөк кошуу үчүн чыкылдатыңыз"</string> - <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарея кубатынын деңгээли белгисиз."</string> + <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батареянын деңгээли белгисиз."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> менен туташкан."</string> <string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> менен туташты."</string> <string name="accessibility_not_connected" msgid="4061305616351042142">"Интернет жок."</string> @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Кошуу"</string> <string name="manage_users" msgid="1823875311934643849">"Колдонуучуларды башкаруу"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Бул билдирмени бөлүнгөн экранда сүйрөөгө болбойт."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi жеткиликсиз"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Маанилүү сүйлөшүүлөр режими"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Ойготкуч коюлду"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Кулпу экранын тууралоо"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Кулпуланган экранды тууралоо үчүн кулпусун ачыңыз"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi жеткиликтүү эмес"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера бөгөттөлдү"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера менен микрофон бөгөттөлдү"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон бөгөттөлдү"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Аракет баскычы"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"Кошумча караңгылатуу эми жарыктык тилкесинде жайгашкан"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Эми экраныңыздын өйдө жагынан жарыктыктын деңгээлин азайтып, экранды кошумча караңгылата аласыз.\n\nМуну караңгы жерде турганыңызда колдонуу сунушталат."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Кошумча караңгылатуу ыкчам баскычын өчүрүү"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Кошумча караңгылатуу ыкчам баскычы өчүрүлдү. Жарыктыкты азайтуу үчүн кадимки жарыктык тилкесин колдонуңуз."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Купуялык"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Колдонмолор сунуштады"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Экран"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Белгисиз"</string> </resources> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index bc0c22d92373..67a11d4717f5 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"ເພີ່ມ"</string> <string name="manage_users" msgid="1823875311934643849">"ຈັດການຜູ້ໃຊ້"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"ການແຈ້ງເຕືອນນີ້ບໍ່ຮອງຮັບການລາກເພື່ອແບ່ງໜ້າຈໍ"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ບໍ່ສາມາດໃຊ້ Wi‑Fi ໄດ້"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ໂໝດຄວາມສຳຄັນ"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ຕັ້ງໂມງປຸກແລ້ວ"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"ປັບແຕ່ງໜ້າຈໍລັອກ"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"ປົດລັອກເພື່ອປັບແຕ່ງໜ້າຈໍລັອກ"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ບໍ່ພ້ອມໃຫ້ນຳໃຊ້"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ກ້ອງຖ່າຍຮູບຖືກບລັອກຢູ່"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ກ້ອງຖ່າຍຮູບ ແລະ ໄມໂຄຣໂຟນຖືກບລັອກຢູ່"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ໄມໂຄຣໂຟນຖືກບລັອກຢູ່"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"ປຸ່ມຄຳສັ່ງ"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ໃຊ້ 3 ນິ້ວປັດຂຶ້ນ ແລ້ວຄ້າງໄວ້. ແຕະເພື່ອສຶກສາທ່າທາງເພີ່ມເຕີມ."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ໃຊ້ແປ້ນພິມຂອງທ່ານເພື່ອເບິ່ງແອັບທັງໝົດ"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"ກົດປຸ່ມຄຳສັ່ງໄດ້ທຸກເວລາ. ແຕະເພື່ອສຶກສາທ່າທາງເພີ່ມເຕີມ."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"ຕອນນີ້ການຫຼຸດແສງເປັນພິເສດເປັນສ່ວນໜຶ່ງຂອງແຖບຄວາມສະຫວ່າງແລ້ວ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ຕອນນີ້ທ່ານສາມາດເຮັດໃຫ້ໜ້າຈໍມືດລົງເປັນພິເສດໄດ້ໂດຍການຫຼຸດລະດັບຄວາມສະຫວ່າງລົງໃຫ້ຫຼາຍຂຶ້ນຈາກເທິງສຸດຂອງໜ້າຈໍຂອງທ່ານ.\n\nຄຸນສົມບັດນີ້ຈະເຮັດວຽກໄດ້ດີທີ່ສຸດເມື່ອທ່ານຢູ່ໃນສະພາບແວດລ້ອມທີ່ມືດ."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"ລຶບທາງລັດທີ່ຫຼຸດແສງເປັນພິເສດອອກ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"ລຶບທາງລັດທີ່ຫຼຸດແສງເປັນພິເສດອອກແລ້ວ. ເພື່ອຫຼຸດຄວາມສະຫວ່າງຂອງທ່ານລົງ, ໃຫ້ໃຊ້ແຖບຄວາມສະຫວ່າງປົກກະຕິ."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"ຄວາມເປັນສ່ວນຕົວ"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"ສະໜອງໃຫ້ໂດຍແອັບ"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ການສະແດງຜົນ"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"ບໍ່ຮູ້ຈັກ"</string> </resources> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 91f8398c8e16..c8134169c9c2 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Pridėti prie užrašo"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Įtraukti nuorodą"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"„<xliff:g id="APPNAME">%1$s</xliff:g>“ <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Nuorodų negalima pridėti iš kitų profilių"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Ekrano vaizdo įrašytuvas"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Apdorojam. ekrano vaizdo įraš."</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Šiuo metu rodomas ekrano įrašymo sesijos pranešimas"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Pridėti"</string> <string name="manage_users" msgid="1823875311934643849">"Tvarkyti naudotojus"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Šio pranešimo vilkimas išskaidyto ekrano režimu nepalaikomas"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"„Wi‑Fi“ ryšys nepasiekiamas"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioriteto režimas"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Signalas nustatytas"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Užrakinimo ekrano tinkinimas"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Atrakinę tinkinkite užrakinimo ekraną"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"„Wi-Fi“ ryšys nepasiekiamas"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Fotoaparatas užblokuotas"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Fotoaparatas ir mikrofonas užblokuoti"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonas užblokuotas"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Veiksmų klavišas"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Perbraukite aukštyn trimis pirštais ir palaikykite. Palieskite, kad sužinotumėte daugiau gestų."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Naudokite klaviatūrą, kad peržiūrėtumėte visas programas"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Bet kuriuo metu paspauskite veiksmų klavišą. Palieskite, kad sužinotumėte daugiau gestų."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Funkcija „Itin blanku“ dabar yra ryškumo juostos dalis"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Dabar galite padaryti ekraną itin blankų, dar labiau sumažindami ryškumo lygį nuo ekrano viršaus.\n\nŠi funkcija geriausiai veikia, kai esate tamsioje aplinkoje."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Pašalinti funkcijos „Itin blanku“ spartųjį klavišą"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Funkcijos „Itin blanku“ spartusis klavišas pašalintas. Jei norite sumažinti ryškumą, naudokite įprastą ryškumo juostą."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Ryšiai"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Pritaikomumas"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Paslaugų programos"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privatumas"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Teikia programos"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Ekranas"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Nežinoma"</string> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 29af399aaf94..a2e4130c5a88 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Pievienot piezīmei"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Iekļaut saiti"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Nevar pievienot saites no citiem profiliem."</string> <string name="screenrecord_title" msgid="4257171601439507792">"Ekrāna ierakstītājs"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekrāna ieraksta apstrāde"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Aktīvs paziņojums par ekrāna ierakstīšanas sesiju"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Pievienot"</string> <string name="manage_users" msgid="1823875311934643849">"Pārvaldīt"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Šis paziņojums neatbalsta vilkšanu uz sadalīto ekrānu."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi nav pieejams"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritātes režīms"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Signāls ir iestatīts"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Pielāgot bloķēšanas ekrānu"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Bloķēšanas ekrāna pielāgošana pēc atbloķēšanas"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nav pieejams"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera ir bloķēta"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kameras un mikrofona lietošana ir bloķēta"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofons ir bloķēts"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Darbību taustiņš"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,10 +1446,14 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Ar trīs pirkstiem velciet augšup un turiet. Lai apgūtu citus žestus, pieskarieties šeit."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Visu lietotņu skatīšana, izmantojot tastatūru"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Jebkurā laikā varat nospiest darbību taustiņu. Lai apgūtu citus žestus, pieskarieties šeit."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Papildu aptumšošana tagad ir iekļauta spilgtuma joslā"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Tagad varat veikt ekrāna papildu aptumšošanu, vēl vairāk samazinot spilgtumu ekrāna augšdaļā.\n\nTas darbojas vislabāk, ja esat tumšā vietā."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Noņemt papildu aptumšošanas saīsni"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Papildu aptumšošanas saīsne ir noņemta. Lai samazinātu spilgtumu, izmantojiet parasto spilgtuma joslu."</string> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> + <skip /> <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> <skip /> <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 11fb67c759e0..d4b066e55104 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Додај во белешка"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Опфати линк"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Не може да се додаваат линкови од други профили"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Снимач на екран"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Се обработува снимка од екран"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Тековно известување за сесија за снимање на екранот"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Додај"</string> <string name="manage_users" msgid="1823875311934643849">"Управувајте со корисниците"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Известувањево не поддржува влечење на поделен екран"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi е недостапна"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Приоритетен режим"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Алармот е наместен"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Приспособете го заклучениот екран"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Отклучување за приспособување на заклучениот екран"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi не е достапно"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камерата е блокирана"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камерата и микрофонот се блокирани"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофонот е блокиран"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Копче за дејство"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"Отсега „Дополнително затемнување“ е дел од лентата за осветленост"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Отсега може да го затемнувате екранот дополнително со намалување на нивото на осветленост од горниот дел на екранот.\n\nОва функционира најдобро кога сте во темна средина."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Отстрани ја кратенката за „Дополнително затемнување“"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Кратенката за „Дополнително затемнување“ е отстранета. Користете ја стандардната лента за осветленост за да ја намалите осветленоста."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Приватност"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Обезбедено од апликации"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Екран"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Непознато"</string> </resources> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 720275e3a6a4..fbb36b158cdb 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"ചേർക്കുക"</string> <string name="manage_users" msgid="1823875311934643849">"ഉപയോക്താക്കളെ മാനേജ് ചെയ്യുക"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"സ്പ്ലിറ്റ് സ്ക്രീനിലേക്ക് വലിച്ചിടുന്നതിനെ ഈ അറിയിപ്പ് പിന്തുണയ്ക്കുന്നില്ല"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"വൈഫൈ ലഭ്യമല്ല"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"മുൻഗണനാ മോഡ്"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"അലാറം സജ്ജീകരിച്ചു"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"ലോക്ക് സ്ക്രീൻ ഇഷ്ടാനുസൃതമാക്കൂ"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"ലോക്ക് സ്ക്രീൻ ഇഷ്ടാനുസൃതമാക്കാൻ അൺലോക്ക് ചെയ്യുക"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"വൈഫൈ ലഭ്യമല്ല"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ക്യാമറ ബ്ലോക്ക് ചെയ്തിരിക്കുന്നു"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ക്യാമറയും മൈക്രോഫോണും ബ്ലോക്ക് ചെയ്തിരിക്കുന്നു"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"മൈക്രോഫോൺ ബ്ലോക്ക് ചെയ്തിരിക്കുന്നു"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"ആക്ഷൻ കീ"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"കൂടുതൽ ഡിം ചെയ്യൽ, ഇപ്പോൾ തെളിച്ചം ബാറിന്റെ ഭാഗമാണ്"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"മുകളിൽ നിന്ന് തെളിച്ചം കുറയ്ക്കുന്നതിലൂടെ നിങ്ങൾക്ക് ഇപ്പോൾ സ്ക്രീൻ കൂടുതൽ മങ്ങിക്കാൻ കഴിയും.\n\nനിങ്ങൾ ഇരുണ്ട മുറിയിലായിരിക്കുമ്പോൾ ഇത് മികച്ച രീതിയിൽ പ്രവർത്തിക്കുന്നു."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"കൂടുതൽ ഡിം ചെയ്യൽ കുറുക്കുവഴി നീക്കം ചെയ്യുക"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"കൂടുതൽ ഡിം ചെയ്യാനുള്ള കുറുക്കുവഴി നീക്കം ചെയ്തു. തെളിച്ചം കുറയ്ക്കാൻ, സാധാരണ \'തെളിച്ചം ബാർ\' ഉപയോഗിക്കുക."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"സ്വകാര്യത"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"ആപ്പുകൾ നൽകുന്നത്"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ഡിസ്പ്ലേ"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"അജ്ഞാതം"</string> </resources> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 50a942e4a2c8..57948a2713bc 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Тэмдэглэлд нэмэх"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Холбоосыг оруулах"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Бусад профайлаас холбоос нэмэх боломжгүй"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Дэлгэцийн үйлдэл бичигч"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Дэлгэц бичлэг боловсруулж байна"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Дэлгэц бичих горимын үргэлжилж буй мэдэгдэл"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Нэмэх"</string> <string name="manage_users" msgid="1823875311934643849">"Хэрэглэгчдийг удирдах"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Энэ мэдэгдэл нь дэлгэцийг хуваах горим руу чирэхийг дэмждэггүй"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi боломжгүй"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Чухал горим"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Сэрүүлгийг тохируулсан"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Түгжээтэй дэлгэцийг өөрчлөх"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Түгжээтэй дэлгэцийг өөрчлөхийн тулд түгжээг тайлна уу"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi боломжгүй байна"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камерыг блоклосон"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камер болон микрофоныг блоклосон"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофоныг блоклосон"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Тусгай товчлуур"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"Хэт бүүдгэр онцлог одоо гэрэлтүүлгийн самбарын нэг хэсэг боллоо"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Та одоо дэлгэцийнхээ дээд талаас гэрэлтүүлгийн түвшнийг бүр илүү багасгаснаар дэлгэцийг хэт бүүдгэр болгох боломжтой.\n\nЭнэ нь таныг харанхуй орчинд байхад хамгийн сайн ажилладаг."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Хэт бүүдгэр онцлогийн товчлолыг хасах"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Хэт бүүдгэр онцлогийн товчлолыг хассан. Гэрэлтүүлгээ багасгахын тулд энгийн гэрэлтүүлгийн самбарыг ашиглана уу."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Нууцлал"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Аппуудаас өгсөн"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Дэлгэц"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Тодорхойгүй"</string> </resources> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 75ef6e0394ac..0f3b051e0aed 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"जोडा"</string> <string name="manage_users" msgid="1823875311934643849">"वापरकर्ते व्यवस्थापित करा"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"ही सूचना स्प्लिट स्क्रीनवर ड्रॅग करण्याला सपोर्ट करत नाही"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"वाय-फाय उपलब्ध नाही"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"प्राधान्य मोड"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"अलार्म सेट केला"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"कस्टमाइझ लॉक स्क्रीन"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"लॉक स्क्रीन कस्टमाइझ करण्यासाठी अनलॉक करा"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"वाय-फाय उपलब्ध नाही"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"कॅमेरा ब्लॉक केला"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"कॅमेरा आणि मायक्रोफोन ब्लॉक केले आहेत"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"मायक्रोफोन ब्लॉक केला"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"अॅक्शन की"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"आणखी डिम हे आता ब्राइटनेस बारचा भाग आहे"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"तुम्ही आता तुमच्या स्क्रीनच्या सर्वात वरून ब्राइटनेसची पातळी आणखी कमी करून स्क्रीनला आणखी डिम करू शकता.\n\nतुम्ही गडद वातावरणात असता, तेव्हा हे सर्वोत्तम कार्य करते."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"आणखी डिमचा शॉर्टकट काढून टाका"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"आणखी डिमचा शॉर्टकट काढून टाकला आहे. तुमचा ब्राइटनेस कमी करण्यासाठी, नेहमीचा ब्राइटनेस बार वापरा."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"गोपनीयता"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"अॅप्सद्वारे पुरवलेले"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"डिस्प्ले"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"अज्ञात"</string> </resources> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index e8213ba5f74c..38434c58cd3d 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Tambah"</string> <string name="manage_users" msgid="1823875311934643849">"Urus pengguna"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Pemberitahuan ini tidak menyokong penyeretan kepada skrin pisah"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi dimatikan"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Mod keutamaan"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Penggera ditetapkan"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Sesuaikan skrin kunci"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Buka kunci untuk menyesuaikan skrin kunci"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi tidak tersedia"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera disekat"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera dan mikrofon disekat"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon disekat"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Kekunci tindakan"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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> + <!-- no translation found for touchpad_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"Kini ciri amat malap merupakan sebahagian daripada bar kecerahan"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Kini anda boleh menjadikan skrin amat malap dengan merendahkan tahap kecerahan lebih jauh daripada bahagian atas skrin anda.\n\nCiri ini berfungsi paling baik apabila anda berada dalam persekitaran yang gelap."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Alih keluar pintasan amat malap"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Pintasan amat malap dialih keluar. Untuk mengurangkan kecerahan anda, gunakan bar kecerahan biasa."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Kesambungan"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Kebolehaksesan"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utiliti"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privasi"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Disediakan oleh apl"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Paparan"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Tidak diketahui"</string> </resources> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 8abb63da1b3a..ef4b04dd7a8e 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"ထည့်ရန်"</string> <string name="manage_users" msgid="1823875311934643849">"အသုံးပြုသူများ စီမံရန်"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"ဤအကြောင်းကြားချက်သည် ‘မျက်နှာပြင် ခွဲ၍ပြသခြင်း’ သို့ ဖိဆွဲမှုကို မပံ့ပိုးပါ"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi မရပါ"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ဦးစားပေးမုဒ်"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"နိုးစက် သတ်မှတ်ထားသည်"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"လော့ခ်မျက်နှာပြင်စိတ်ကြိုက်လုပ်ရန်"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"လော့ခ်မျက်နှာပြင် စိတ်ကြိုက်လုပ်ရန် ဖွင့်ပါ"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi မရနိုင်ပါ"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ကင်မရာကို ပိတ်ထားသည်"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ကင်မရာနှင့် မိုက်ခရိုဖုန်းကို ပိတ်ထားသည်"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"မိုက်ခရိုဖုန်းကို ပိတ်ထားသည်"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"လုပ်ဆောင်ချက်ကီး"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"ပိုမှိန်ခြင်းသည် တောက်ပမှုဘားတွင် ပါဝင်လာပြီ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"သင့်စခရင်ထိပ်ဆုံး၌ပင် တောက်ပမှုအဆင့်လျှော့ချခြင်းဖြင့် စခရင်ကို ပိုမှိန်အောင် လုပ်နိုင်ပါပြီ။\n\nသင်သည် မှောင်သောပတ်ဝန်းကျင်၌ရှိချိန် ၎င်းက အကောင်းဆုံးအလုပ်လုပ်သည်။"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"ပိုမှိန်ခြင်း ဖြတ်လမ်း ဖယ်ရှားရန်"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"ပိုမှိန်ခြင်း ဖြတ်လမ်းကို ဖယ်ရှားလိုက်ပြီ။ တောက်ပမှုလျှော့ရန် ပုံမှန် တောက်ပမှုဘားကို အသုံးပြုပါ။"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"ကိုယ်ရေးအချက်အလက် လုံခြုံမှု"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"အက်ပ်များက ပံ့ပိုးထားသည်"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ဖန်သားပြင်"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"အမျိုးအမည်မသိ"</string> </resources> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 8ccb77618fa1..55535dd97942 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Legg til i notat"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Inkluder linken"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Linker kan ikke legges til fra andre profiler"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Skjermopptak"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skjermopptaket"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Vedvarende varsel for et skjermopptak"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Legg til"</string> <string name="manage_users" msgid="1823875311934643849">"Brukervalg"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Dette varselet støtter ikke at du drar det til en delt skjerm"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi er utilgjengelig"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioriteringsmodus"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarmen er stilt inn"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Tilpass låseskjermen"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Du må låse opp enheten for å tilpasse låseskjermen"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi er ikke tilgjengelig"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kameraet er blokkert"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kameraet og mikrofonen er blokkert"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonen er blokkert"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Handlingstast"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Sveip opp og hold med tre fingre. Trykk for å lære flere bevegelser."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Bruk tastaturet for å se alle apper"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Trykk på handlingstasten når som helst. Trykk for å lære flere bevegelser."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Nå er ekstra dimmet en del av lysstyrkeraden"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Nå kan du gjøre skjermen ekstra dimmet ved å redusere lysstyrkenivået enda mer fra toppen av skjermen.\n\nDette fungerer best i mørke omgivelser."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Fjern hurtigtasten for ekstra dimmet"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Hurtigtasten for ekstra dimmet er fjernet. For å redusere lysstyrken kan du bruke den vanlige lysstyrkeraden."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Tilkobling"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Tilgjengelighet"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Systemverktøy"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Personvern"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Levert av apper"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Skjerm"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Ukjent"</string> </resources> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 60e99eaf48b6..68cca0784c0a 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"हाल्नुहोस्"</string> <string name="manage_users" msgid="1823875311934643849">"प्रयोगकर्ताहरूको व्यवस्थापन गर्नुहोस्"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"यो सूचना ड्र्याग गरेर स्प्लिट स्क्रिनमा लैजान मिल्दैन"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi उपलब्ध छैन"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"प्राथमिकता मोड"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"अलार्म सेट गरिएको छ"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"लक स्क्रिन कस्टमाइज गर्नुहोस्"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"लक स्क्रिन कस्टमाइज गर्न अनलक गर्नुहोस्"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi उपलब्ध छैन"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"क्यामेरा ब्लक गरिएको छ"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"क्यामेरा र माइक्रोफोन ब्लक गरिएको छ"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"माइक्रोफोन ब्लक गरिएको छ"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"एक्सन की"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"\"अझै मधुरो\" सुविधा अब ब्राइटनेस बारमा समावेश गरिएको छ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"तपाईं अब आफ्नो स्क्रिनको सिरानबाट चमकको स्तर घटाएर आफ्नो स्क्रिन अझै मधुरो बनाउन सक्नुहुन्छ।\n\nतपाईं अँध्यारो ठाउँमा भएका बेला यो सुविधाले अझ राम्रोसँग काम गर्छ।"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"\"अझै मधुरो\" सर्टकट हटाउनुहोस्"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"\"अझै मधुरो\" सर्टकट हटाइएको छ। स्क्रिनको चमक घटाउन \"रेगुलर ब्राइटनेस बार\" प्रयोग गर्नुहोस्।"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"गोपनीयता"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"एपले उपलब्ध गराएका"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"डिस्प्ले"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"अज्ञात"</string> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 4b43ab173d3a..2e9fc8e2db01 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Toevoegen"</string> <string name="manage_users" msgid="1823875311934643849">"Gebruikers beheren"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Deze melding biedt geen ondersteuning voor slepen naar het gesplitste scherm"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wifi niet beschikbaar"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioriteitsmodus"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Wekker gezet"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Vergrendelscherm aanpassen"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Ontgrendelen om het vergrendelscherm aan te passen"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi niet beschikbaar"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera geblokkeerd"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera en microfoon geblokkeerd"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfoon geblokkeerd"</string> @@ -1400,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Actietoets"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swipe met 3 vingers omhoog en houd vast. Tik voor meer gebaren."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Je toetsenbord gebruiken om alle apps te bekijken"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Druk op de actietoets wanneer je wilt. Tik voor meer gebaren."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extra dimmen maakt nu deel uit van de helderheidsbalk"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Je kunt het scherm nu extra dimmen door het helderheidsniveau nog verder te verlagen vanaf de bovenkant van het scherm.\n\nDit werkt het beste als je in een donkere omgeving bent."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Snelkoppeling voor extra dimmen verwijderen"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Snelkoppeling voor extra dimmen verwijderd. Als je de helderheid wilt verlagen, gebruik je de gewone helderheidsbalk."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Connectiviteit"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Toegankelijkheid"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Hulpprogramma\'s"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privacy"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Geleverd door apps"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Scherm"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Onbekend"</string> </resources> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index af4ee77c04ed..7eced2615661 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ନୋଟରେ ଯୋଗ କରନ୍ତୁ"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"ଲିଙ୍କକୁ ଅନ୍ତର୍ଭୁକ୍ତ କରନ୍ତୁ"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"ଅନ୍ୟ ପ୍ରୋଫାଇଲରୁ ଲିଙ୍କଗୁଡ଼ିକ ଯୋଗ କରାଯାଇପାରିବ ନାହିଁ"</string> <string name="screenrecord_title" msgid="4257171601439507792">"ସ୍କ୍ରିନ ରେକର୍ଡର"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ସ୍କ୍ରିନ ରେକର୍ଡିଂର ପ୍ରକ୍ରିୟାକରଣ"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"ଏକ ସ୍କ୍ରିନ୍ ରେକର୍ଡ୍ ସେସନ୍ ପାଇଁ ଚାଲୁଥିବା ବିଜ୍ଞପ୍ତି"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"ଯୋଗ କରନ୍ତୁ"</string> <string name="manage_users" msgid="1823875311934643849">"ୟୁଜରମାନଙ୍କୁ ପରିଚାଳନା କରନ୍ତୁ"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"ଏହି ବିଜ୍ଞପ୍ତି ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ଟାଣିବାକୁ ସମର୍ଥନ କରେ ନାହିଁ"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ୱାଇ-ଫାଇ ଉପଲବ୍ଧ ନାହିଁ"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ପ୍ରାଥମିକତା ମୋଡ"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ଆଲାରାମ ସେଟ"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"ଲକ ସ୍କ୍ରିନକୁ କଷ୍ଟମାଇଜ କରନ୍ତୁ"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"ଲକ ସ୍କ୍ରିନକୁ କଷ୍ଟମାଇଜ କରିବା ପାଇଁ ଅନଲକ କରନ୍ତୁ"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ୱାଇ-ଫାଇ ଉପଲବ୍ଧ ନାହିଁ"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"କେମେରାକୁ ବ୍ଲକ କରାଯାଇଛି"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"କେମେରା ଏବଂ ମାଇକ୍ରୋଫୋନକୁ ବ୍ଲକ କରାଯାଇଛି"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ମାଇକ୍ରୋଫୋନକୁ ବ୍ଲକ କରାଯାଇଛି"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"ଆକ୍ସନ କୀ"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"ଅତିରିକ୍ତ ଡିମ ବର୍ତ୍ତମାନ ଉଜ୍ଜ୍ୱଳତା ବାରର ଅଂଶ ଅଟେ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ବର୍ତ୍ତମାନ ଆପଣ ଆପଣଙ୍କ ସ୍କ୍ରିନର ଶୀର୍ଷରୁ ଉଜ୍ଜ୍ୱଳତାର ଲେଭେଲ ହ୍ରାସ କରି ସ୍କ୍ରିନକୁ ଅତିରିକ୍ତ ଡିମ କରିପାରିବେ।\n\nଆପଣ ଏକ ଡାର୍କ ପରିବେଶରେ ଥିଲେ ଏହା ସବୁଠାରୁ ଭଲ କାମ କରେ।"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"ଅତିରିକ୍ତ ଡିମ ସର୍ଟକଟକୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"ଅତିରିକ୍ତ ଡିମର ସର୍ଟକଟ କାଢ଼ି ଦିଆଯାଇଛି। ଆପଣଙ୍କ ଉଜ୍ଜ୍ୱଳତା ହ୍ରାସ କରିବା ପାଇଁ ନିୟମିତ ଉଜ୍ଜ୍ୱଳତା ବାର ବ୍ୟବହାର କରନ୍ତୁ।"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"ଗୋପନୀୟତା"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"ଆପ୍ସ ଦ୍ୱାରା ପ୍ରଦାନ କରାଯାଇଛି"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ଡିସପ୍ଲେ"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"ଅଜଣା"</string> </resources> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index e6b275a5cef0..6a46613f3db9 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ਨੋਟ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"ਲਿੰਕ ਸ਼ਾਮਲ ਕਰੋ"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"ਹੋਰ ਪ੍ਰੋਫਾਈਲਾਂ ਤੋਂ ਲਿੰਕਾਂ ਨੂੰ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string> <string name="screenrecord_title" msgid="4257171601439507792">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਰ"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਜਾਰੀ ਹੈ"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"ਕਿਸੇ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਸੈਸ਼ਨ ਲਈ ਚੱਲ ਰਹੀ ਸੂਚਨਾ"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"ਸ਼ਾਮਲ ਕਰੋ"</string> <string name="manage_users" msgid="1823875311934643849">"ਵਰਤੋਂਕਾਰਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"ਇਹ ਸੂਚਨਾ ਸਪਲਿਟ ਸਕ੍ਰੀਨ \'ਤੇ ਘਸੀਟਣ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ ਹੈ"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ਵਾਈ-ਫਾਈ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ਤਰਜੀਹੀ ਮੋਡ"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ਅਲਾਰਮ ਸੈੱਟ ਹੈ"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"ਲਾਕ ਸਕ੍ਰੀਨ ਨੂੰ ਵਿਉਂਤਬੱਧ ਕਰੋ"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"ਲਾਕ ਸਕ੍ਰੀਨ ਨੂੰ ਵਿਉਂਤਬੱਧ ਕਰਨ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ਵਾਈ-ਫਾਈ ਉਪਲਬਧ ਨਹੀਂ"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ਕੈਮਰਾ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ਕੈਮਰਾ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤੇ ਗਏ"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"ਕਾਰਵਾਈ ਕੁੰਜੀ"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"\'ਜ਼ਿਆਦਾ ਘੱਟ ਚਮਕ\' ਹੁਣ ਚਮਕ ਪੱਟੀ ਦਾ ਹਿੱਸਾ ਹੈ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ਤੁਸੀਂ ਹੁਣ ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਸਿਖਰ ਤੋਂ ਚਕਮ ਦੇ ਪੱਧਰ ਨੂੰ ਹੋਰ ਵੀ ਘੱਟ ਕਰ ਕੇ ਸਕ੍ਰੀਨ ਦੀ ਚਮਕ ਨੂੰ ਜ਼ਿਆਦਾ ਘੱਟ ਕਰ ਸਕਦੇ ਹੋ।\n\nਇਹ ਉਦੋਂ ਬਿਹਤਰੀਨ ਕੰਮ ਕਰਦੀ ਹੈ, ਜਦੋਂ ਤੁਸੀਂ ਹਨੇਰੇ ਵਿੱਚ ਹੁੰਦੇ ਹੋ।"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"\'ਜ਼ਿਆਦਾ ਘੱਟ ਚਮਕ\' ਸ਼ਾਰਟਕੱਟ ਹਟਾਓ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"\'ਜ਼ਿਆਦਾ ਘੱਟ ਚਮਕ\' ਸ਼ਾਰਟਕੱਟ ਹਟਾਇਆ ਗਿਆ। ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੀ ਚਕਮ ਨੂੰ ਘੱਟ ਕਰਨ ਲਈ, ਨਿਯਮਿਤ ਚਮਕ ਪੱਟੀ ਦੀ ਵਰਤੋਂ ਕਰੋ।"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"ਪਰਦੇਦਾਰੀ"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"ਐਪਾਂ ਵੱਲੋਂ ਮੁਹੱਈਆ ਕੀਤਾ ਗਿਆ"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ਡਿਸਪਲੇ"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"ਅਗਿਆਤ"</string> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 0fefcaecbdb6..770d9953d955 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj do notatek"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Dołącz link"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Nie można dodawać linków z innych profili"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Nagrywanie ekranu"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Przetwarzam nagrywanie ekranu"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Stałe powiadomienie o sesji rejestrowania zawartości ekranu"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Dodaj"</string> <string name="manage_users" msgid="1823875311934643849">"Zarządzaj użytkownikami"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"To powiadomienie nie obsługuje dzielenia ekranu przez przeciąganie."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Sieć Wi‑Fi niedostępna"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Tryb priorytetowy"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm ustawiony"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Dostosuj ekran blokady"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Odblokuj, aby dostosować ekran blokady"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Sieć Wi-Fi jest niedostępna"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera jest zablokowana"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon są zablokowane"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon jest zablokowany"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Klawisz działania"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Przesuń w górę za pomocą 3 palców i przytrzymaj. Kliknij, aby poznać więcej gestów."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Wyświetlanie wszystkich aplikacji za pomocą klawiatury"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Naciśnij klawisz działania w dowolnym momencie. Kliknij, aby poznać więcej gestów."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Dodatkowe przyciemnienie jest teraz częścią paska jasności"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Możesz teraz dodatkowo przyciemnić ekran, jeszcze bardziej zmniejszając poziom jasności u góry ekranu.\n\nTa funkcja sprawdza się najlepiej, gdy jesteś w ciemnym otoczeniu."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Usuń skrót do dodatkowego przyciemnienia"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Skrót do dodatkowego przyciemnienia został usunięty. Aby zmniejszyć jasność, użyj standardowego paska jasności."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Łączność"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Ułatwienia dostępu"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Narzędzia"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Prywatność"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Z aplikacji"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Wyświetlacz"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Nieznane"</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 1331ee65a716..0563454d8e00 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Incluir anotação"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Incluir link"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Não é possível adicionar links de outros perfis"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Gravador de tela"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string> @@ -578,7 +577,7 @@ <string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nenhuma notificação nova"</string> <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"O recurso de atenuar notificações está ativo"</string> - <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volume e alertas do disp. são reduzidos por até 2 min quando você recebe muitas notificações juntas."</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volume e alertas são reduzidos por até 2 min quando você recebe muitas notificações juntas."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desativar"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie p/ acessar notificações antigas"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu familiar responsável"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Adicionar"</string> <string name="manage_users" msgid="1823875311934643849">"Gerenciar usuários"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Esta notificação não pode ser arrastada para a tela dividida"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi-Fi indisponível"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modo de prioridade"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarme definido"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar a tela de bloqueio"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desbloqueie para personalizar a tela de bloqueio"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi indisponível"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Câmara bloqueada"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Câmera e microfone bloqueados"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfone bloqueado"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de ação"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Deslize para cima e pressione com três dedos. Toque para aprender outros gestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use o teclado para ver todos os apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pressione a tecla de ação a qualquer momento. Toque para aprender outros gestos."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"O recurso Escurecer a tela agora faz parte da barra de brilho"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Agora, na parte de cima, é possível usar o recurso Escurecer a tela, que diminui ainda mais o nível de brilho.\n\nIsso funciona melhor quando você está em um ambiente escuro."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remover atalho de Escurecer a tela"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Atalho de Escurecer a tela removido. Use a barra normal para diminuir o brilho."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Conectividade"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Acessibilidade"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utilitários"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privacidade"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Fornecidos por apps"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Exibição"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Desconhecidos"</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index e811fff9782b..0b31babeb828 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Adicionar"</string> <string name="manage_users" msgid="1823875311934643849">"Gerir utilizadores"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Esta notificação não pode ser arrastada para o ecrã dividido"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi indisponível"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modo Prioridade"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarme definido"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar ecrã de bloqueio"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desbloqueie para personalizar o ecrã de bloqueio"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi indisponível"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Câmara bloqueada"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Câmara e microfone bloqueados"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfone bloqueado"</string> @@ -1400,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de ação"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Deslize rapidamente para cima e mantenha premido com 3 dedos. Toque para aprender mais gestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use o teclado para ver todas as apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Prima a tecla de ação em qualquer altura. Toque para aprender mais gestos."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Agora, o escurecimento extra faz parte da barra do brilho"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Agora, pode tornar o ecrã ainda mais escuro reduzindo ainda mais o nível de brilho a partir da parte superior do ecrã.\n\nIsto funciona melhor quando está num ambiente escuro."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remover atalho do escurecimento extra"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Atalho do escurecimento extra removido. Para reduzir o brilho, use a barra do brilho normal."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Conetividade"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Acessibilidade"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utilitários"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privacidade"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Disponibilizado por apps"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Ecrã"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Desconhecido"</string> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 1331ee65a716..0563454d8e00 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Incluir anotação"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Incluir link"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Não é possível adicionar links de outros perfis"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Gravador de tela"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string> @@ -578,7 +577,7 @@ <string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string> <string name="no_unseen_notif_text" msgid="395512586119868682">"Nenhuma notificação nova"</string> <string name="adaptive_notification_edu_hun_title" msgid="7790738150177329960">"O recurso de atenuar notificações está ativo"</string> - <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volume e alertas do disp. são reduzidos por até 2 min quando você recebe muitas notificações juntas."</string> + <string name="adaptive_notification_edu_hun_text" msgid="7743367744129536610">"Volume e alertas são reduzidos por até 2 min quando você recebe muitas notificações juntas."</string> <string name="go_to_adaptive_notification_settings" msgid="2423690125178298479">"Desativar"</string> <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie p/ acessar notificações antigas"</string> <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu familiar responsável"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Adicionar"</string> <string name="manage_users" msgid="1823875311934643849">"Gerenciar usuários"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Esta notificação não pode ser arrastada para a tela dividida"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi-Fi indisponível"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modo de prioridade"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarme definido"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar a tela de bloqueio"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Desbloqueie para personalizar a tela de bloqueio"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi indisponível"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Câmara bloqueada"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Câmera e microfone bloqueados"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfone bloqueado"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de ação"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Deslize para cima e pressione com três dedos. Toque para aprender outros gestos."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Use o teclado para ver todos os apps"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pressione a tecla de ação a qualquer momento. Toque para aprender outros gestos."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"O recurso Escurecer a tela agora faz parte da barra de brilho"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Agora, na parte de cima, é possível usar o recurso Escurecer a tela, que diminui ainda mais o nível de brilho.\n\nIsso funciona melhor quando você está em um ambiente escuro."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Remover atalho de Escurecer a tela"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Atalho de Escurecer a tela removido. Use a barra normal para diminuir o brilho."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Conectividade"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Acessibilidade"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utilitários"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privacidade"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Fornecidos por apps"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Exibição"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Desconhecidos"</string> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 35d00254bd09..5edcaf1c17f7 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Adaugă în notă"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Include linkul"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Nu se pot adăuga linkuri din alte profiluri"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Recorder pentru ecran"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Se procesează înregistrarea"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificare în curs pentru o sesiune de înregistrare a ecranului"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Adaugă"</string> <string name="manage_users" msgid="1823875311934643849">"Gestionează"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Notificarea nu acceptă tragerea pe ecranul împărțit"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi indisponibil"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modul Prioritate"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarmă setată"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizează ecranul de blocare"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Deblochează pentru a personaliza ecranul de blocare"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Conexiune Wi-Fi indisponibilă"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera foto a fost blocată"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera foto și microfonul sunt blocate"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfonul a fost blocat"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tastă de acțiuni"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Glisează în sus și ține apăsat cu trei degete. Atinge ca să înveți mai multe gesturi."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Folosește-ți tastatura ca să vezi toate aplicațiile"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Apasă oricând tasta de acțiuni. Atinge ca să înveți mai multe gesturi."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Luminozitatea redusă suplimentar face acum parte din bara de luminozitate"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Poți reduce suplimentar luminozitatea ecranului dacă scazi nivelul de luminozitate din partea de sus a ecranului.\n\nAcest lucru funcționează cel mai bine într-un mediu întunecat."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Elimină comanda rapidă de luminozitate redusă suplimentar"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"S-a eliminat comanda rapidă de luminozitate redusă suplimentar. Ca să reduci luminozitatea, folosește bara obișnuită de luminozitate."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Conectivitate"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Accesibilitate"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utilitare"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Confidențialitate"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Oferite de aplicații"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Ecran"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Necunoscută"</string> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 2174dde011c0..a1f1750261d9 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Добавить"</string> <string name="manage_users" msgid="1823875311934643849">"Управление пользователями"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Это уведомление нельзя перетаскивать между частями разделенного экрана."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Сеть Wi‑Fi недоступна"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Режим приоритета"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Будильник установлен"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Настройки заблок. экрана"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Разблокируйте устройство, чтобы настроить заблокированный экран"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Функция Wi-Fi недоступна"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера заблокирована"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера и микрофон заблокированы"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон заблокирован"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Клавиша действия"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"Дополнительно уменьшать яркость теперь можно через стандартный ползунок"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Чтобы дополнительно понизить яркость экрана, откройте настройки в его верхней части.\n\nРекомендуем использовать эту функцию, когда вокруг темно."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Удалить быструю команду для дополнительного уменьшения яркости"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Быстрая команда для дополнительного уменьшения яркости удалена. Чтобы изменить уровень яркости, воспользуйтесь стандартным ползунком яркости."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Конфиденциальность"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Приложения"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Экран"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Неизвестно"</string> </resources> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 167e9cdeb64e..3dac0c5d601e 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"සටහනට එක් කරන්න"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"සබැඳිය ඇතුළත් කරන්න"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"වෙනත් පැතිකඩවලින් සබැඳි එක් කළ නොහැක"</string> <string name="screenrecord_title" msgid="4257171601439507792">"තිර රෙකෝඩරය"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"තිර පටිගත කිරීම සකසමින්"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"තිර පටිගත කිරීමේ සැසියක් සඳහා කෙරෙන දැනුම් දීම"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"එක් කරන්න"</string> <string name="manage_users" msgid="1823875311934643849">"පරිශීලකයන් කළමනාකරණය කරන්න"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"මෙම දැනුම්දීම බෙදුම් තිරය වෙත ඇද ගෙන යාමට සහාය නොදක්වයි."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi ලබා ගත නොහැකිය"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ප්රමුඛතා ප්රකාරය"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"සීනුව සකසන ලදි"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"අගුළු තිරය අභිරුචිකරණය කරන්න"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"අගුළු තිරය අභිරුචිකරණය කිරීමට අගුළු හරින්න"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ලද නොහැක"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"කැමරාව අවහිරයි"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"කැමරාව සහ මයික්රොෆෝනය අවහිරයි"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"මයික්රොෆෝනය අවහිරයි"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"ක්රියා යතුර"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"තවත් අඳුර දැන් දීප්ත තීරුවේ කොටසකි"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ඔබේ තිරයේ ඉහළ සිට දීප්තියේ මට්ටම තවත් අඩු කිරීමෙන් ඔබට දැන් තිරය තවත් අඳුරු කළ හැක.\n\nඔබ අඳුරු පරිසරයක සිටින විට මෙය වඩාත් හොඳින් ක්රියා කරයි."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"තවත් අඳුරු කෙටිමඟ ඉවත් කරන්න"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"තවත් අඳුරු කෙටිමඟ ඉවත් කරන ලදි. ඔබේ දීප්තිය අඩු කිරීමට, සාමාන්ය දීප්ත තීරුව භාවිත කරන්න."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"රහස්යතාව"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"යෙදුම් මගින් සපයනු ලැබේ"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"සංදර්ශකය"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"නොදනී"</string> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index dd872c25eeb5..166a95cea931 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Pridať"</string> <string name="manage_users" msgid="1823875311934643849">"Spravovať použ."</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Toto upozornenie nepodporuje presun na rozdelenú obrazovku"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi nie je k dispozícii"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Režim priority"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Budík je nastavený"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Prispôsobiť uzamknutú obrazovku"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Uzamknutú obrazovku môžete prispôsobiť po odomknutí"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi‑Fi nie je k dispozícii"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokovaná"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera a mikrofón sú blokované"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofón je blokovaný"</string> @@ -1400,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Akčný kláves"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Potiahnite troma prstami nahor a pridržte ich. Viac o gestách sa dozviete klepnutím."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Zobrazte si všetky aplikácie pomocou klávesnice"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Akčný kláves môžete stlačiť kedykoľvek. Viac o gestách sa dozviete klepnutím."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Mimoriadne stmavenie je teraz súčasťou posúvača na úpravu jasu"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Teraz môžete obrazovku mimoriadne stmaviť ešte ďalším znížením úrovne jasu v hornej časti obrazovky.\n\nNajlepšie to funguje v tmavom prostredí."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Odstrániť skratku mimoriadneho stmavenia"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Skratka mimoriadneho stmavenia bola odstránená. Ak chcete znížiť jas, použite bežný posúvač jasu."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Pripojenie"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Dostupnosť"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Utility"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Ochrana súkromia"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Poskytnuté aplikáciami"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Zobrazovanie"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Neznáme"</string> </resources> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 01ca4e57162d..fa80b3a8d7a4 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Dodaj"</string> <string name="manage_users" msgid="1823875311934643849">"Upravljaj uporabnike"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"To obvestilo ne podpira vlečenja v razdeljen zaslon."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi ni na voljo."</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prednostni način"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm je nastavljen."</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Prilagajanje zaklenjenega zaslona"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Odklenite za prilagajanje zaklenjenega zaslona"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ni na voljo."</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Fotoaparat je blokiran."</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Fotoaparat in mikrofon sta blokirana."</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokiran."</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Gumb za dejanje"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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> + <!-- no translation found for touchpad_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"S tremi prsti povlecite navzgor in pridržite. Dotaknite se, če želite spoznati več potez."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Uporaba tipkovnice za prikaz vseh aplikacij"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Kadar koli pritisnite tipko za dejanja. Dotaknite se, če želite spoznati več potez."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Funkcija Zelo zatemnjeno je zdaj del vrstice za uravnavanje svetlosti"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Zdaj lahko zelo zatemnite zaslon tako, da na vrhu zaslona dodatno zmanjšate raven svetlosti.\n\nTa funkcija najbolje deluje v temnem okolju."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Odstrani bližnjico do funkcije Zelo zatemnjeno"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Bližnjica do funkcije Zelo zatemnjeno je odstranjena. Če želite zmanjšati svetlost, uporabite običajno vrstico za uravnavanje svetlosti."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Povezljivost"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Dostopnost"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Orodja"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Zasebnost"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Zagotavljajo aplikacije"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Zaslon"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Neznano"</string> </resources> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index c4f880877ea2..0b700f8d0b10 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Shto te shënimi"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Përfshi lidhjen"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Lidhjet nuk mund të shtohen nga profilet e tjera"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Regjistruesi i ekranit"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Regjistrimi i ekranit po përpunohet"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Njoftim i vazhdueshëm për një seancë regjistrimi të ekranit"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Shto"</string> <string name="manage_users" msgid="1823875311934643849">"Menaxho përdoruesit"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Ky njoftim nuk mbështet zvarritjen tek ekrani i ndarë"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi nuk ofrohet"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Modaliteti \"Me përparësi\""</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarmi është caktuar"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Personalizo ekranin e kyçjes"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Shkyçe për të personalizuar ekranin e kyçjes"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nuk ofrohet"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera u bllokua"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera dhe mikrofoni u bllokuan"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofoni u bllokua"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tasti i veprimit"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,10 +1446,14 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Rrëshqit shpejt lart dhe mbaj shtypur me tre gishta. Trokit për të mësuar më shumë gjeste."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Përdor tastierën për të shikuar të gjitha aplikacionet"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Shtyp tastin e veprimit në çdo kohë. Trokit për të mësuar më shumë gjeste."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Modaliteti \"Shumë më i zbehtë\" tani është pjesë e shiritit të ndriçimit"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Tani mund ta bësh ekranin shumë më të zbehtë duke e ulur nivelin e ndriçimit edhe më tej nga kreu i ekranit.\n\nKjo funksionon më mirë kur je në një mjedis të errët."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Hiq shkurtoren e modalitetit \"Shumë më i zbehtë\""</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Shkurtorja e modalitetit \"Shumë më i zbehtë\" u hoq. Për të ulur ndriçimin, përdor shiritin e zakonshëm të ndriçimit."</string> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> + <skip /> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> + <skip /> <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> <skip /> <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 66a4915ae3be..b1abb59771f8 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Додај"</string> <string name="manage_users" msgid="1823875311934643849">"Управљаj корисницима"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Ово обавештење не подржава превлачење на подељени екран"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WiFi није доступан"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Приоритетни режим"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Аларм је подешен"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Прилагоди закључани екран"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Откључајте да бисте прилагодили закључани екран"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi није доступан"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера је блокирана"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера и микрофон су блокирани"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон је блокиран"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Тастер радњи"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"Додатно затамњивање је сада део траке за осветљеност"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Сада можете додатно да затамните екран смањивањем нивоа осветљености при врху екрана. \n\nОво најбоље функционише када сте у тамном окружењу."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Уклони пречицу за додатно затамњивање"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Уклоњена је пречица за додатно затамњивање. Да бисте смањили осветљеност, користите уобичајену траку за осветљеност."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Приватност"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Обезбеђују апликације"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Екран"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Непознато"</string> </resources> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 5ec9e963a15f..8817fe8fb23c 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Lägg till i anteckning"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Inkludera länk"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Det går inte att lägga till länkar från andra profiler"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Skärminspelare"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandlar skärminspelning"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Avisering om att skärminspelning pågår"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Lägg till"</string> <string name="manage_users" msgid="1823875311934643849">"Välj användare"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Det går inte att dra den här aviseringen till delad skärm"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wifi är inte tillgängligt"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Prioritetsläge"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarmet är aktiverat"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Anpassa låsskärmen"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Lås upp för att anpassa låsskärmen"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi är inte tillgängligt"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kameran är blockerad"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kameran och mikrofonen är blockerade"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonen är blockerad"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Åtgärdstangent"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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> + <!-- no translation found for touchpad_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Svep uppåt med tre fingrar och håll kvar. Tryck för att lära dig fler rörelser."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Använd tangentbordet för att se alla appar"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Tryck på åtgärdstangenten när som helst. Tryck för att lära dig fler rörelser."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Extradimmat är nu en del av fältet för ljusstyrka"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Nu kan du göra skärmen extradimmad genom att sänka ljusstyrkan ännu mer från överst på skärmen.\n\nDetta fungerar bäst när omgivningen är mörk."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Ta bort kortkommandot för extradimmat"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Kortkommandot för extradimmat har tagits bort. Använd det vanliga fältet för ljusstyrka om du vill sänka ljusstyrkan."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Anslutning"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Tillgänglighet"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Verktyg"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Integritet"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Tillhandahålls av appar"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Skärm"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Okänt"</string> </resources> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index ababf7010302..28f677ab93e1 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ongeza kwenye dokezo"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Jumuisha kiungo"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g> <xliff:g id="APPNAME">%1$s</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Huruhusiwi kuweka viungo kutoka kwenye wasifu mwingine"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Kinasa Skrini"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Inachakata rekodi ya skrini"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Arifa inayoendelea ya kipindi cha kurekodi skrini"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Weka"</string> <string name="manage_users" msgid="1823875311934643849">"Dhibiti watumiaji"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Arifa hii haitumii utaratibu wa kuburuta ili kugawa skrini"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi-Fi haipatikani"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Hali ya kipaumbele"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Kengele imewekwa"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Wekea mapendeleo skrini iliyofungwa"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Fungua ili uweke mapendeleo ya skrini iliyofungwa"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi haipatikani"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera imezuiwa"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera na maikrofoni zimezuiwa"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Maikrofoni imezuiwa"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Kitufe cha vitendo"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Telezesha vidole vitatu juu na ushikilie. Gusa ili upate maelezo kuhusu miguso zaidi."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Kutumia kibodi yako kuangalia programu zote"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Bonyeza kitufe cha vitendo wakati wowote. Gusa ili upate maelezo kuhusu miguso zaidi."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Kipunguza mwangaza zaidi sasa ni sehemu ya upau wa mwangaza"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Sasa unaweza kupunguza mwangaza zaidi kwa kupunguza kabisa kiwango cha mwangaza katika sehemu ya juu ya skrini yako.\n\nMipangilio hii hufanya kazi vyema zaidi ukiwa katika mazingira yenye giza."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Ondoa njia ya mkato ya kipunguza mwangaza zaidi"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Njia ya mkato ya kipunguza mwangaza zaidi imeondolewa. Tumia upau wa kawaida wa mwangaza ili upunguze mwangaza wako."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Muunganisho"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Ufikivu"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Vipengee"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Faragha"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Vinavyotolewa na programu"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Maonyesho"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Visivyojulikana"</string> </resources> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 54ab3c337f94..3b8e3c2aff07 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"சேர்"</string> <string name="manage_users" msgid="1823875311934643849">"பயனர்களை நிர்வகித்தல்"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"பிரிக்கப்பட்ட திரைக்குள் இந்த அறிவிப்பை இழுத்துவிட முடியாது"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"வைஃபை கிடைக்கவில்லை"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"முன்னுரிமைப் பயன்முறை"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"அலாரம் அமைக்கப்பட்டுள்ளது"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"பூட்டுத் திரையை பிரத்தியேகமாக்கு"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"பூட்டுத் திரையைப் பிரத்தியேகப்படுத்த அன்லாக் செய்யுங்கள்"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"வைஃபை கிடைக்கவில்லை"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"கேமரா தடுக்கப்பட்டுள்ளது"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"கேமராவும் மைக்ரோஃபோனும் தடுக்கப்பட்டுள்ளன"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"மைக்ரோஃபோன் தடுக்கப்பட்டுள்ளது"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"ஆக்ஷன் பட்டன்"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"\'மிகக் குறைவான வெளிச்சம்\' அம்சம் இப்போது ஒளிர்வுப் பட்டியின் ஒரு பகுதியாகும்"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"இப்போது உங்கள் திரையின் மேற்பகுதியில் ஒளிர்வு அளவைக் குறைப்பதன் மூலம் திரையை மிகக் குறைவான வெளிச்சத்திற்குக் கொண்டு வரலாம்.\n\nஇருட்டான சூழலில் இருக்கும்போது இது சிறப்பாகச் செயல்படும்."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"மிகக் குறைவான வெளிச்சத்திற்கான ஷார்ட்கட்டை அகற்று"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"மிகக் குறைவான வெளிச்சத்திற்கான ஷார்ட்கட் அகற்றப்பட்டது. உங்கள் ஒளிர்வைக் குறைக்க, வழக்கமான ஒளிர்வுப் பட்டியைப் பயன்படுத்துங்கள்."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"தனியுரிமை"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"ஆப்ஸ் வழங்குபவை"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"டிஸ்ப்ளே"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"தெரியவில்லை"</string> </resources> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 2c4109a8fd9e..84fc147b04b6 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -125,7 +125,7 @@ <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"స్క్రీన్ రికార్డింగ్ చేయబడుతోంది"</string> <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"స్క్రీన్, ఆడియో రికార్డింగ్ చేయబడుతున్నాయి"</string> <string name="screenrecord_taps_label" msgid="1595690528298857649">"స్క్రీన్పై తాకే స్థానాలను చూపండి"</string> - <string name="screenrecord_stop_label" msgid="72699670052087989">"ఆపివేయి"</string> + <string name="screenrecord_stop_label" msgid="72699670052087989">"ఆపివేయండి"</string> <string name="screenrecord_share_label" msgid="5025590804030086930">"షేర్ చేయండి"</string> <string name="screenrecord_save_title" msgid="1886652605520893850">"స్క్రీన్ రికార్డింగ్ సేవ్ చేయబడింది"</string> <string name="screenrecord_save_text" msgid="3008973099800840163">"చూడటానికి ట్యాప్ చేయండి"</string> @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"జోడించండి"</string> <string name="manage_users" msgid="1823875311934643849">"యూజర్లను మేనేజ్ చేయండి"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"ఈ నోటిఫికేషన్ స్ప్లిట్ స్క్రీన్కు లాగడాన్ని సపోర్ట్ చేయదు"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi అందుబాటులో లేదు"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ముఖ్యమైన ఫైల్స్ మోడ్"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"అలారం సెట్ చేశాను"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"లాక్ స్క్రీన్ అనుకూలంగా మార్చండి"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"లాక్ స్క్రీన్ను అనుకూలంగా మార్చుకోవడానికి అన్లాక్ చేయండి"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi అందుబాటులో లేదు"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"కెమెరా బ్లాక్ చేయబడింది"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"కెమెరా, మైక్రోఫోన్ బ్లాక్ చేయబడ్డాయి"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"మైక్రోఫోన్ బ్లాక్ చేయబడింది"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"యాక్షన్ కీ"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"కాంతిని మరింత డిమ్ చేసే ఫీచర్ ఇప్పుడు బ్రైట్నెస్ బార్లో ఒక భాగం"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"మీరు ఇప్పుడు మీ స్క్రీన్ పైభాగం నుండి బ్రైట్నెస్ స్థాయిని తగ్గించడం ద్వారా కూడా స్క్రీన్ కాంతిని మరింత డిమ్ చేయవచ్చు.\n\nమీరు డార్క్ ఎన్విరాన్మెంట్లో ఉన్నప్పుడు కూడా ఇది బాగా పని చేస్తుంది."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"కాంతిని మరింత డిమ్ చేసే షార్ట్కట్ను తీసివేయండి"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"కాంతిని మరింత డిమ్ చేసే షార్ట్కట్ తీసివేయబడింది. మీ బ్రైట్నెస్ను తగ్గించడానికి, సాధారణ బ్రైట్నెస్ బార్ను ఉపయోగించండి."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"కనెక్టివిటీ"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Accessibility"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"యుటిలిటీలు"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"గోప్యత"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"యాప్ల ద్వారా అందించబడినవి"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"డిస్ప్లే"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"తెలియదు"</string> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 20e730c2df57..1d7a782e79bf 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"เพิ่ม"</string> <string name="manage_users" msgid="1823875311934643849">"จัดการผู้ใช้"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"การแจ้งเตือนนี้ไม่รองรับการลากเพื่อแยกหน้าจอ"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"ใช้ Wi‑Fi ไม่ได้"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"โหมดลำดับความสำคัญ"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"ตั้งปลุกแล้ว"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"ปรับแต่งหน้าจอล็อก"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"ปลดล็อกเพื่อปรับแต่งหน้าจอล็อก"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ไม่พร้อมใช้งาน"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"กล้องถูกบล็อกอยู่"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"กล้องและไมโครโฟนถูกบล็อกอยู่"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ไมโครโฟนถูกบล็อกอยู่"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"ปุ่มดำเนินการ"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"ใช้ 3 นิ้วปัดขึ้นแล้วค้างไว้ แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"ใช้แป้นพิมพ์เพื่อดูแอปทั้งหมด"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"กดปุ่มดำเนินการได้ทุกเมื่อ แตะเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับท่าทางสัมผัสต่างๆ"</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"ตอนนี้การหรี่แสงเพิ่มเติมเป็นส่วนหนึ่งของแถบความสว่างแล้ว"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"ตอนนี้คุณสามารถหรี่แสงหน้าจอเพิ่มเติมได้โดยลดระดับความสว่างจากด้านบนของหน้าจอมากขึ้น\n\nฟีเจอร์นี้จะทำงานได้ดีเมื่อคุณอยู่ในที่มืด"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"นำทางลัดหรี่แสงเพิ่มเติมออก"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"นำทางลัดหรี่แสงเพิ่มเติมออกแล้ว หากต้องการลดความสว่าง ให้ใช้แถบความสว่างปกติ"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"ความเป็นส่วนตัว"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"ให้บริการโดยแอป"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"จอแสดงผล"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"ไม่ทราบ"</string> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 0bef7436269c..00be27bb9578 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Magdagdag"</string> <string name="manage_users" msgid="1823875311934643849">"Pamahalaan ang mga user"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Hindi sinusuportahan ng notification na ito ang pag-drag sa split screen"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Hindi available ang Wi‑Fi"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Priority mode"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Nakatakda ang alarm"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"I-customize ang lock screen"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"I-unlock para i-customize ang lock screen"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Hindi available ang Wi-Fi"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Naka-block ang camera"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Naka-block ang camera at mikropono"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Naka-block ang mikropono"</string> @@ -1400,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Mag-swipe pataas at i-hold gamit ang tatlong daliri. I-tap para matuto pa tungkol sa mga galaw."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Gamitin ang iyong keyboard para tingnan ang lahat ng app"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Pindutin ang action key kahit kailan. I-tap para matuto pa tungkol sa mga galaw."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Bahagi na ng brightness bar ang extra dim"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Puwede mo nang gawing extra dim ang screen sa pamamagitan ng pagpapababa ng level ng liwanag nang higit pa mula sa itaas ng iyong screen.\n\nPinakamahusay itong gumagana kapag nasa madilim na kapaligiran ka."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Alisin ang shortcut ng extra dim"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Inalis ang shortcut ng extra dim. Para bawasan ang liwanag, gamitin ang karaniwang bar ng liwanag."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Pagkakonekta"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Accessibility"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Mga Utility"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Privacy"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Ibinibigay ng mga app"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Display"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Hindi Alam"</string> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 060ecd1010eb..0031687c80cb 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Nota ekle"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Bağlantıyı dahil et"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Başka profillerden bağlantı eklenemez"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Ekran Kaydedicisi"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran kaydı işleniyor"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekran kaydı oturumu için devam eden bildirim"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Ekle"</string> <string name="manage_users" msgid="1823875311934643849">"Kullanıcıları yönet"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Bu bildirim bölünmüş ekrana sürüklemeyi desteklemiyor"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Kablosuz kullanılamıyor"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Öncelik modu"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Alarm kuruldu"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Kilit ekranını özelleştir"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Kilit ekranını özelleştirmek için kilidi açın"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Kablosuz bağlantı kullanılamıyor"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera engellendi"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera ve mikrofon engellendi"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon engellendi"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Eylem tuşu"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Üç parmağınızla yukarı kaydırıp basılı tutun. Daha fazla hareket öğrenmek için dokunun."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Tüm uygulamaları görüntülemek için klavyenizi kullanın"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"İstediğiniz zaman eylem tuşuna basın. Daha fazla hareket öğrenmek için dokunun."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Ekstra loş özelliği, parlaklık çubuğuna eklendi"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Artık ekranınızın üst kısmından parlaklık seviyesini daha da düşürerek ekranı ekstra loş hale getirebilirsiniz.\n\nBu özellik, karanlık ortamdayken en iyi sonucu verir."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Ekstra loş kısayolunu kaldır"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Ekstra loş kısayolu kaldırıldı. Parlaklık seviyesini düşürmek için normal parlaklık çubuğunu kullanın."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Bağlantı"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Erişilebilirlik"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Yardımcı programlar"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Gizlilik"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Uygulamalar tarafından sağlanır"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Ekran"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Bilinmiyor"</string> </resources> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index ae07ae26d0f0..715b17939836 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Додати до примітки"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Додати посилання"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Не можна додавати посилання з інших профілів"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Запис відео з екрана"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обробка записування екрана"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Сповіщення про сеанс запису екрана"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Додати"</string> <string name="manage_users" msgid="1823875311934643849">"Керувати користувачами"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Це сповіщення не підтримує режим розділеного екрана"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Мережа Wi-Fi недоступна"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Режим пріоритету"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Будильник установлено"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Налаштувати заблокований екран"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Розблокуйте, щоб налаштувати заблокований екран"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Мережа Wi-Fi недоступна"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камеру заблоковано"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камеру й мікрофон заблоковано"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Мікрофон заблоковано"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"Клавіша дії"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"Тепер на панелі регулювання яскравості є функція додаткового зменшення яскравості"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Тепер ви можете зробити екран ще темнішим, додатково зменшуючи рівень яскравості вгорі екрана.\n\nНайкраще ця функція працює, коли ви перебуваєте в темному місці."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Видалити комбінацію клавіш для додаткового зменшення яскравості"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Комбінацію клавіш для додаткового зменшення яскравості видалено. Щоб зменшити яскравість, використовуйте стандартну панель регулювання."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Конфіденційність"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Надано додатками"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Екран"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Невідомо"</string> </resources> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 5d1f66e364ef..78a7f42867c9 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -1289,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"شامل کریں"</string> <string name="manage_users" msgid="1823875311934643849">"صارفین کا نظم کریں"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"یہ اطلاع اسپلٹ اسکرین پر گھسیٹنے کو سپورٹ نہیں کرتی ہے"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi-Fi دستیاب نہیں ہے"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"ترجیحی وضع"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"الارم سیٹ ہوگیا"</string> @@ -1345,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"مقفل اسکرین کو حسب ضرورت بنائیں"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"مقفل اسکرین کو حسب ضرورت بنانے کے لیے غیر مقفل کریں"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi دستیاب نہیں ہے"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"کیمرا مسدود ہے"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"کیمرا اور مائیکروفون مسدود ہے"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"مائیکروفون مسدود ہے"</string> @@ -1400,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"ایکشن کلید"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1410,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1433,22 +1446,19 @@ <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="4369307638184799742">"اضافی دھندلا اب چمک بار کا حصہ ہے"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"آپ اپنی اسکرین کے اوپری حصے سے چمکیلے پن لیول کو مزید کم کر کے اپنی اسکرین کو اضافی دھندلی بنا سکتے ہیں۔\n\nجب آپ تاریک ماحول میں ہوتے ہیں تو یہ بہتر کام کرتا ہے۔"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"اضافی دھندلا شارٹ کٹ کو ہٹائیں"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"اضافی دھندلا شارٹ کٹ کو ہٹا دیا گیا۔ اپنا چمکیلا پن کم کرنے کیلئے، ریگولر چمک بار کا استعمال کریں"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"رازداری"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"ایپس کے ذریعہ فراہم کردہ"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"ڈسپلے"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"نامعلوم"</string> </resources> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index af35adf0f390..51cf8b5b3313 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Qaydga qoʻshish"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Havolani kiritish"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g>, <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Boshqa profillardan havola kiritish mumkin emas"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Ekranni yozib olish"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran yozib olinmoqda"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekrandan yozib olish seansi uchun joriy bildirishnoma"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Kiritish"</string> <string name="manage_users" msgid="1823875311934643849">"Foyd-ni boshqarish"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Bu bildirishnoma ikkiga ajratilgan ekranda ishlamaydi."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi ishlamayapti"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Imtiyozli rejim"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Signal oʻrnatildi"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Ekran qulfini moslash"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Ekran qulfini sozlash uchun qulfni oching"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi mavjud emas"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera bloklangan"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera va mikrofon bloklangan"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon bloklangan"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Amal tugmasi"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Uchta barmoq bilan tepaga surib, bosib turing. Boshqa ishoralar bilan tanishish uchun bosing."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Klaviatura orqali barcha ilovalarni koʻrish"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Amal tugmasini istalganda bosing. Boshqa ishoralar bilan tanishish uchun bosing."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Juda xira endi yorqinlik panelida joylashgan"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Endi yorqinlik darajasini ekranning yuqori qismidan yanada pasaytirish orqali ekranni yanada xiralashtirishingiz mumkin.\n\nBu qorongʻi muhitda eng yaxshi ishlaydi."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Juda xira yorligʻini olib tashlash"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Juda xira yorligʻi olib tashlandi. Yorqinlikni pasaytirish uchun oddiy yorqinlik panelidan foydalaning."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Maxfiylik"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Ilovalarga tegishli"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Ekran"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Noaniq"</string> </resources> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index b7cd6b0d899f..fb9abd73e8c7 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Thêm vào ghi chú"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Thêm đường liên kết"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Không thể thêm đường liên kết từ các hồ sơ khác"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Trình ghi màn hình"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Đang xử lý video ghi màn hình"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Thông báo đang diễn ra về phiên ghi màn hình"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Thêm"</string> <string name="manage_users" msgid="1823875311934643849">"Quản lý ng.dùng"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Thông báo này không hỗ trợ thao tác kéo để chia đôi màn hình"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Không có Wi‑Fi"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Chế độ ưu tiên"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"Đã đặt chuông báo"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Tuỳ chỉnh màn hình khoá"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Mở khoá để tuỳ chỉnh màn hình khoá"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Không có Wi-Fi"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Máy ảnh bị chặn"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Máy ảnh và micrô bị chặn"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micrô bị chặn"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Phím hành động"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Dùng 3 ngón tay vuốt lên và giữ. Hãy nhấn để tìm hiểu các cử chỉ khác."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Sử dụng bàn phím để xem tất cả ứng dụng"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Nhấn phím hành động bất cứ lúc nào. Hãy nhấn để tìm hiểu các cử chỉ khác."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Chế độ siêu tối hiện đã có trên thanh độ sáng"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Giờ đây, bạn có thể đặt màn hình ở chế độ siêu tối bằng cách giảm thêm độ sáng từ đầu màn hình.\n\nChế độ này hoạt động hiệu quả nhất khi bạn ở trong một môi trường tối."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Xoá lối tắt của chế độ siêu tối"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Đã xoá lối tắt của chế độ siêu tối. Để giảm độ sáng, hãy dùng thanh độ sáng như thông thường."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Khả năng kết nối"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Hỗ trợ tiếp cận"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Phần mềm tiện ích"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Quyền riêng tư"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Do các ứng dụng cung cấp"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Hiển thị"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Không xác định"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index a329965d5714..d311aa300bd5 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"添加到备注中"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"包括链接"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"无法添加来自其他个人资料的链接"</string> <string name="screenrecord_title" msgid="4257171601439507792">"屏幕录制器"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在处理屏幕录制视频"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"持续显示屏幕录制会话通知"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"添加"</string> <string name="manage_users" msgid="1823875311934643849">"管理用户"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"此通知不支持拖动到分屏中"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"WLAN 已关闭"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"优先模式"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"闹钟已设置"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"自定义锁屏"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"解锁以自定义锁定屏幕"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"没有 WLAN 连接"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"已禁用摄像头"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"已禁用摄像头和麦克风"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"已禁用麦克风"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"快捷操作按键"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"“极暗”功能现已在亮度条中"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"现在,您可从屏幕顶部进一步调低亮度,将屏幕调成极暗。\n\n此功能在昏暗环境中效果最佳。"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"移除“极暗”快捷方式"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"已移除“极暗”快捷方式。如要调低亮度,请使用常规亮度条。"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"隐私设置"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"由应用提供"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"显示"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"未知"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 73bfbe6c2be2..91ae846a29e6 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"新增至筆記"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"加入連結"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"無法新增來自其他設定檔的連結"</string> <string name="screenrecord_title" msgid="4257171601439507792">"螢幕錄影機"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在處理螢幕錄影內容"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示錄影畫面工作階段通知"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"新增"</string> <string name="manage_users" msgid="1823875311934643849">"管理使用者"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"此通知無法拖曳到分割螢幕中。"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi 已關閉"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"優先模式"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"已設定鬧鐘"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"自訂上鎖畫面"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"解鎖後即可自訂上鎖畫面"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"無法連線至 Wi-Fi"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"已封鎖相機"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"已封鎖相機和麥克風"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"已封鎖麥克風"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"快捷操作鍵"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"亮度列現已加入超暗功能"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"而家喺螢幕頂部進一步校低亮度,就可以令螢幕變得超暗\n\n呢個功能喺陰暗環境之下嘅效果最好"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"移除超暗功能快速鍵"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"超暗功能快速鍵已移除。如要降低亮度,請使用一般的亮度列。"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"私隱"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"由應用程式提供"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"螢幕"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"不明"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 46847fcf6599..93a99e6ce71c 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"新增至記事本"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"包含連結"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"無法新增其他設定檔中的連結"</string> <string name="screenrecord_title" msgid="4257171601439507792">"螢幕錄影器"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"處理螢幕錄影內容"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示螢幕畫面錄製工作階段通知"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"新增"</string> <string name="manage_users" msgid="1823875311934643849">"管理使用者"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"這項通知無法拖曳到分割畫面中。"</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"Wi‑Fi 已關閉"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"優先模式"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"鬧鐘設定成功"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"自訂螢幕鎖定畫面"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"解鎖後即可自訂螢幕鎖定畫面"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"無法連上 Wi-Fi"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"已封鎖攝影機"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"已封鎖攝影機和麥克風"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"已封鎖麥克風"</string> @@ -1401,7 +1404,8 @@ <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_action_key_button" msgid="3220074511852927267">"快捷操作鍵"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <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="4369307638184799742">"「超暗」已移到亮度列"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"現在只要在螢幕頂端將亮度設定調得更低,就能讓螢幕變得更暗。\n\n這項設定最適合在昏暗環境下使用。"</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"移除「超暗」捷徑"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"「超暗」捷徑已移除。如要調低亮度,請使用一般的亮度列。"</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <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> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"隱私權"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"由應用程式提供"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"螢幕"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"不明"</string> </resources> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index dbfb926b867c..9fc11661f88c 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -105,8 +105,7 @@ <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Engeza kunothi"</string> <string name="backlinks_include_link" msgid="4562093591148248158">"Faka ilinki"</string> <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string> - <!-- no translation found for backlinks_cross_profile_error (1355798585727802282) --> - <skip /> + <string name="backlinks_cross_profile_error" msgid="1355798585727802282">"Amalinki awakwazi ukufakwa ukusuka kwamanye amaphrofayela"</string> <string name="screenrecord_title" msgid="4257171601439507792">"Okokuqopha iskrini"</string> <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Icubungula okokuqopha iskrini"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"Isaziso esiqhubekayo seseshini yokurekhoda isikrini"</string> @@ -1290,6 +1289,8 @@ <string name="add" msgid="81036585205287996">"Faka"</string> <string name="manage_users" msgid="1823875311934643849">"Phatha abasebenzisi"</string> <string name="drag_split_not_supported" msgid="7173481676120546121">"Lesi saziso asikusekeli ukuhudulela ekuhlukaniseni isikrini."</string> + <!-- no translation found for dream_overlay_location_active (6484763493158166618) --> + <skip /> <string name="dream_overlay_status_bar_wifi_off" msgid="4497069245055003582">"I-Wi-Fi ayitholakali"</string> <string name="dream_overlay_status_bar_priority_mode" msgid="5428462123314728739">"Imodi ebalulekile"</string> <string name="dream_overlay_status_bar_alarm_set" msgid="566707328356590886">"I-alamu isethiwe"</string> @@ -1346,6 +1347,8 @@ <string name="lock_screen_settings" msgid="6152703934761402399">"Yenza ngokwezifiso ukukhiya isikrini"</string> <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Vula ukuze wenze ukuvala isikrini ngendlela oyifisayo"</string> <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"I-Wi-Fi ayitholakali"</string> + <!-- no translation found for location_active_dream_overlay_content_description (6208885541020673916) --> + <skip /> <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Ikhamera ivinjiwe"</string> <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Ikhamera nemakrofoni zivinjiwe"</string> <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Imakrofoni ivinjiwe"</string> @@ -1401,7 +1404,8 @@ <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> - <string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Inkinobho yokufinyelela"</string> + <!-- no translation found for touchpad_tutorial_recent_apps_gesture_button (8919227647650347359) --> + <skip /> <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> @@ -1411,6 +1415,14 @@ <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_recent_apps_gesture_action_title (934906836867137906) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_guidance (6012057247259983871) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_title (8481920554139332593) --> + <skip /> + <!-- no translation found for touchpad_recent_apps_gesture_success_body (4334263906697493273) --> + <skip /> <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> @@ -1434,22 +1446,19 @@ <string name="overview_edu_notification_content" msgid="3578204677648432500">"Swayiphela phezulu bese uyabamba usebenzisa iminwe emithathu. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string> <string name="all_apps_edu_notification_title" msgid="372262997265569063">"Sebenzisa ikhibhodi yakho ukubuka wonke ama-app"</string> <string name="all_apps_edu_notification_content" msgid="3255070575694025585">"Cindezela inkinobho yokufinyelela noma kunini. Thepha ukuze ufunde kabanzi ngokunyakazisa umzimba."</string> - <string name="accessibility_deprecate_extra_dim_dialog_title" msgid="4369307638184799742">"Ukufiphala okwengeziwe manje sekuyingxenye yebha yokukhanya"</string> - <string name="accessibility_deprecate_extra_dim_dialog_description" msgid="7513137763024327538">"Manje ungenza isikrini sifiphale ngokwengeziwe ngokwehlisa izinga lokukhanya nakakhulu kusukela phezulu kwesikrini sakho.\n\nLokhu kusebenza kahle kakhulu uma usendaweni emnyama."</string> - <string name="accessibility_deprecate_extra_dim_dialog_button" msgid="1782147201534669800">"Susa isinqamuleli esifiphele esengeziwe"</string> - <string name="accessibility_deprecate_extra_dim_dialog_toast" msgid="4070696910424515757">"Isinqamuleli esifiphele ngokwengeziwe sikhishiwe. Ukuze wehlise ukukhanya kwakho, sebenzisa ibha yokukhanya evamile."</string> - <!-- no translation found for qs_edit_mode_category_connectivity (4559726936546032672) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_accessibility (7969091385071475922) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_utilities (8123080090108420095) --> - <skip /> - <!-- no translation found for qs_edit_mode_category_privacy (6577774443194551775) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_title (910988771011857460) --> <skip /> - <!-- no translation found for qs_edit_mode_category_providedByApps (8346112074897919019) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_description (4453123359258743230) --> <skip /> - <!-- no translation found for qs_edit_mode_category_display (4749511439121053942) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_button (3947537827396916005) --> <skip /> - <!-- no translation found for qs_edit_mode_category_unknown (509314252124053550) --> + <!-- no translation found for accessibility_deprecate_extra_dim_dialog_toast (165474092660941104) --> <skip /> + <string name="qs_edit_mode_category_connectivity" msgid="4559726936546032672">"Ukuxhumana"</string> + <string name="qs_edit_mode_category_accessibility" msgid="7969091385071475922">"Ukufinyeleleka"</string> + <string name="qs_edit_mode_category_utilities" msgid="8123080090108420095">"Okusetshenziswayo"</string> + <string name="qs_edit_mode_category_privacy" msgid="6577774443194551775">"Ubumfihlo"</string> + <string name="qs_edit_mode_category_providedByApps" msgid="8346112074897919019">"Kuhlinzekwe ama-app"</string> + <string name="qs_edit_mode_category_display" msgid="4749511439121053942">"Bonisa"</string> + <string name="qs_edit_mode_category_unknown" msgid="509314252124053550">"Akwaziwa"</string> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index f9c2aef5f070..ba3822bd3c23 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -3114,6 +3114,10 @@ <string name="media_output_group_title_speakers_and_displays">Speakers & Displays</string> <!-- Title for Suggested Devices group. [CHAR LIMIT=NONE] --> <string name="media_output_group_title_suggested_device">Suggested Devices</string> + <!-- Title for input device group. [CHAR LIMIT=NONE] --> + <string name="media_input_group_title">Input</string> + <!-- Title for output device group. [CHAR LIMIT=NONE] --> + <string name="media_output_group_title">Output</string> <!-- Summary for end session dialog. [CHAR LIMIT=NONE] --> <string name="media_output_end_session_dialog_summary">Stop your shared session to move media to another device</string> <!-- Button text for stopping session [CHAR LIMIT=60] --> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 7efe2dde1320..ffbc85ca530f 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -968,6 +968,15 @@ public class KeyguardSecurityContainer extends ConstraintLayout { constraintSet.constrainWidth(mViewFlipper.getId(), MATCH_CONSTRAINT); constraintSet.applyTo(mView); } + + @Override + public void onDestroy() { + if (mView == null) return; + ConstraintSet constraintSet = new ConstraintSet(); + constraintSet.clone(mView); + constraintSet.clear(mViewFlipper.getId()); + constraintSet.applyTo(mView); + } } /** @@ -1043,12 +1052,20 @@ public class KeyguardSecurityContainer extends ConstraintLayout { @Override public void onDensityOrFontScaleChanged() { mView.removeView(mUserSwitcherViewGroup); + mView.removeView(mUserSwitcher); inflateUserSwitcher(); } @Override public void onDestroy() { - mUserSwitcherController.removeUserSwitchCallback(mUserSwitchCallback); + ConstraintSet constraintSet = new ConstraintSet(); + constraintSet.clone(mView); + constraintSet.clear(mUserSwitcherViewGroup.getId()); + constraintSet.clear(mViewFlipper.getId()); + constraintSet.applyTo(mView); + + mView.removeView(mUserSwitcherViewGroup); + mView.removeView(mUserSwitcher); } private Drawable findLargeUserIcon(int userId) { @@ -1344,5 +1361,13 @@ public class KeyguardSecurityContainer extends ConstraintLayout { constraintSet.constrainPercentWidth(mViewFlipper.getId(), 0.5f); constraintSet.applyTo(mView); } + + @Override + public void onDestroy() { + ConstraintSet constraintSet = new ConstraintSet(); + constraintSet.clone(mView); + constraintSet.clear(mViewFlipper.getId()); + constraintSet.applyTo(mView); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticPlayer.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticPlayer.kt index 19e7537007bf..b8c30fe9d4a8 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticPlayer.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticPlayer.kt @@ -76,11 +76,7 @@ class BouncerHapticPlayer @Inject constructor(private val msdlPlayer: dagger.Laz /** Deliver MSDL feedback when the delete key of the pin bouncer is pressed */ fun playDeleteKeyPressFeedback() = msdlPlayer.get().playToken(MSDLToken.KEYPRESS_DELETE) - /** - * Deliver MSDL feedback when the delete key of the pin bouncer is long-pressed - * - * @return whether MSDL feedback is allowed to play. - */ + /** Deliver MSDL feedback when the delete key of the pin bouncer is long-pressed. */ fun playDeleteKeyLongPressedFeedback() = msdlPlayer.get().playToken(MSDLToken.LONG_PRESS) /** Deliver MSDL feedback when a numpad key is pressed on the pin bouncer */ diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt index c67b35424cc9..873d1b3cc03d 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt @@ -21,6 +21,7 @@ import com.android.app.tracing.coroutines.flow.collectLatest import com.android.systemui.authentication.domain.interactor.AuthenticationResult import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.bouncer.domain.interactor.BouncerInteractor +import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer import com.android.systemui.lifecycle.ExclusiveActivatable import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.channels.Channel @@ -42,6 +43,7 @@ sealed class AuthMethodBouncerViewModel( /** Name to use for performance tracing purposes. */ val traceName: String, + protected val bouncerHapticPlayer: BouncerHapticPlayer? = null, ) : ExclusiveActivatable() { private val _animateFailure = MutableStateFlow(false) @@ -80,6 +82,8 @@ sealed class AuthMethodBouncerViewModel( return@collectLatest } + performAuthenticationHapticFeedback(authenticationResult) + _animateFailure.value = authenticationResult != AuthenticationResult.SUCCEEDED clearInput() } @@ -112,20 +116,23 @@ sealed class AuthMethodBouncerViewModel( /** Returns the input entered so far. */ protected abstract fun getInput(): List<Any> + /** Perform authentication result haptics */ + private fun performAuthenticationHapticFeedback(result: AuthenticationResult) { + if (result == AuthenticationResult.SKIPPED) return + + bouncerHapticPlayer?.playAuthenticationFeedback( + authenticationSucceeded = result == AuthenticationResult.SUCCEEDED + ) + } + /** * Attempts to authenticate the user using the current input value. * * @see BouncerInteractor.authenticate */ - protected fun tryAuthenticate( - input: List<Any> = getInput(), - useAutoConfirm: Boolean = false, - ) { + protected fun tryAuthenticate(input: List<Any> = getInput(), useAutoConfirm: Boolean = false) { authenticationRequests.trySend(AuthenticationRequest(input, useAutoConfirm)) } - private data class AuthenticationRequest( - val input: List<Any>, - val useAutoConfirm: Boolean, - ) + private data class AuthenticationRequest(val input: List<Any>, val useAutoConfirm: Boolean) } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt index 0aada06a7eb7..0bcb58dee934 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt @@ -30,6 +30,7 @@ import com.android.systemui.authentication.shared.model.AuthenticationWipeModel import com.android.systemui.bouncer.domain.interactor.BouncerActionButtonInteractor import com.android.systemui.bouncer.domain.interactor.BouncerInteractor import com.android.systemui.bouncer.shared.model.BouncerActionButtonModel +import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer import com.android.systemui.common.shared.model.Icon import com.android.systemui.common.shared.model.Text import com.android.systemui.dagger.qualifiers.Application @@ -61,6 +62,7 @@ constructor( private val pinViewModelFactory: PinBouncerViewModel.Factory, private val patternViewModelFactory: PatternBouncerViewModel.Factory, private val passwordViewModelFactory: PasswordBouncerViewModel.Factory, + private val bouncerHapticPlayer: BouncerHapticPlayer, ) : ExclusiveActivatable() { private val _selectedUserImage = MutableStateFlow<Bitmap?>(null) val selectedUserImage: StateFlow<Bitmap?> = _selectedUserImage.asStateFlow() @@ -162,10 +164,7 @@ constructor( } launch { - combine( - userSwitcher.users, - userSwitcher.menu, - ) { users, actions -> + combine(userSwitcher.users, userSwitcher.menu) { users, actions -> users.map { user -> UserSwitcherDropdownItemViewModel( icon = Icon.Loaded(user.image, contentDescription = null), @@ -178,7 +177,7 @@ constructor( icon = Icon.Resource( action.iconResourceId, - contentDescription = null + contentDescription = null, ), text = Text.Resource(action.textResourceId), onClick = action.onClicked, @@ -226,7 +225,7 @@ constructor( } private fun getChildViewModel( - authenticationMethod: AuthenticationMethodModel, + authenticationMethod: AuthenticationMethodModel ): AuthMethodBouncerViewModel? { // If the current child view-model matches the authentication method, reuse it instead of // creating a new instance. @@ -241,12 +240,14 @@ constructor( authenticationMethod = authenticationMethod, onIntentionalUserInput = ::onIntentionalUserInput, isInputEnabled = isInputEnabled, + bouncerHapticPlayer = bouncerHapticPlayer, ) is AuthenticationMethodModel.Sim -> pinViewModelFactory.create( authenticationMethod = authenticationMethod, onIntentionalUserInput = ::onIntentionalUserInput, isInputEnabled = isInputEnabled, + bouncerHapticPlayer = bouncerHapticPlayer, ) is AuthenticationMethodModel.Password -> passwordViewModelFactory.create( @@ -257,6 +258,7 @@ constructor( patternViewModelFactory.create( onIntentionalUserInput = ::onIntentionalUserInput, isInputEnabled = isInputEnabled, + bouncerHapticPlayer = bouncerHapticPlayer, ) else -> null } @@ -317,10 +319,7 @@ constructor( return when { // The wipe dialog takes priority over the lockout dialog. wipeText != null -> - DialogViewModel( - text = wipeText, - onDismiss = { wipeDialogMessage.value = null }, - ) + DialogViewModel(text = wipeText, onDismiss = { wipeDialogMessage.value = null }) lockoutText != null -> DialogViewModel( text = lockoutText, @@ -338,7 +337,7 @@ constructor( fun onKeyEvent(keyEvent: KeyEvent): Boolean { return (authMethodViewModel.value as? PinBouncerViewModel)?.onKeyEvent( keyEvent.type, - keyEvent.nativeKeyEvent.keyCode + keyEvent.nativeKeyEvent.keyCode, ) ?: false } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt index 0a866b43429f..158f102ccdb3 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt @@ -18,9 +18,11 @@ package com.android.systemui.bouncer.ui.viewmodel import android.content.Context import android.util.TypedValue +import android.view.View import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate import com.android.systemui.bouncer.domain.interactor.BouncerInteractor +import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer import com.android.systemui.res.R import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -35,7 +37,6 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.toList import kotlinx.coroutines.launch /** Holds UI state and handles user input for the pattern bouncer UI. */ @@ -44,6 +45,7 @@ class PatternBouncerViewModel constructor( private val applicationContext: Context, interactor: BouncerInteractor, + @Assisted bouncerHapticPlayer: BouncerHapticPlayer, @Assisted isInputEnabled: StateFlow<Boolean>, @Assisted private val onIntentionalUserInput: () -> Unit, ) : @@ -51,6 +53,7 @@ constructor( interactor = interactor, isInputEnabled = isInputEnabled, traceName = "PatternBouncerViewModel", + bouncerHapticPlayer = bouncerHapticPlayer, ) { /** The number of columns in the dot grid. */ @@ -190,14 +193,7 @@ constructor( private fun defaultDots(): List<PatternDotViewModel> { return buildList { (0 until columnCount).forEach { x -> - (0 until rowCount).forEach { y -> - add( - PatternDotViewModel( - x = x, - y = y, - ) - ) - } + (0 until rowCount).forEach { y -> add(PatternDotViewModel(x = x, y = y)) } } } } @@ -207,14 +203,17 @@ constructor( applicationContext.resources.getValue( com.android.internal.R.dimen.lock_pattern_dot_hit_factor, outValue, - true + true, ) max(min(outValue.float, 1f), MIN_DOT_HIT_FACTOR) } + fun performDotFeedback(view: View?) = bouncerHapticPlayer?.playPatternDotFeedback(view) + @AssistedFactory interface Factory { fun create( + bouncerHapticPlayer: BouncerHapticPlayer, isInputEnabled: StateFlow<Boolean>, onIntentionalUserInput: () -> Unit, ): PatternBouncerViewModel @@ -231,7 +230,7 @@ constructor( */ private fun PatternDotViewModel.isOnLineSegment( first: PatternDotViewModel, - second: PatternDotViewModel + second: PatternDotViewModel, ): Boolean { val anotherPoint = this // No need to consider any points outside the bounds of two end points @@ -253,14 +252,8 @@ private fun Int.isBetween(a: Int, b: Int): Boolean { return (this in a..b) || (this in b..a) } -data class PatternDotViewModel( - val x: Int, - val y: Int, -) { +data class PatternDotViewModel(val x: Int, val y: Int) { fun toCoordinate(): AuthenticationPatternCoordinate { - return AuthenticationPatternCoordinate( - x = x, - y = y, - ) + return AuthenticationPatternCoordinate(x = x, y = y) } } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt index da29c6230cd8..0cb4260e4d7f 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt @@ -19,12 +19,14 @@ package com.android.systemui.bouncer.ui.viewmodel import android.content.Context +import android.view.HapticFeedbackConstants import android.view.KeyEvent.KEYCODE_0 import android.view.KeyEvent.KEYCODE_9 import android.view.KeyEvent.KEYCODE_DEL import android.view.KeyEvent.KEYCODE_NUMPAD_0 import android.view.KeyEvent.KEYCODE_NUMPAD_9 import android.view.KeyEvent.isConfirmKey +import android.view.View import androidx.compose.ui.input.key.KeyEvent import androidx.compose.ui.input.key.KeyEventType import com.android.keyguard.PinShapeAdapter @@ -32,6 +34,7 @@ import com.android.systemui.authentication.shared.model.AuthenticationMethodMode import com.android.systemui.bouncer.domain.interactor.BouncerInteractor import com.android.systemui.bouncer.domain.interactor.SimBouncerInteractor import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags +import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer import com.android.systemui.res.R import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -56,6 +59,7 @@ constructor( applicationContext: Context, interactor: BouncerInteractor, private val simBouncerInteractor: SimBouncerInteractor, + @Assisted bouncerHapticPlayer: BouncerHapticPlayer, @Assisted isInputEnabled: StateFlow<Boolean>, @Assisted private val onIntentionalUserInput: () -> Unit, @Assisted override val authenticationMethod: AuthenticationMethodModel, @@ -64,6 +68,7 @@ constructor( interactor = interactor, isInputEnabled = isInputEnabled, traceName = "PinBouncerViewModel", + bouncerHapticPlayer = bouncerHapticPlayer, ) { /** * Whether the sim-related UI in the pin view is showing. @@ -126,10 +131,9 @@ constructor( .collect { _hintedPinLength.value = it } } launch { - combine( - mutablePinInput, - interactor.isAutoConfirmEnabled, - ) { mutablePinEntries, isAutoConfirmEnabled -> + combine(mutablePinInput, interactor.isAutoConfirmEnabled) { + mutablePinEntries, + isAutoConfirmEnabled -> computeBackspaceButtonAppearance( pinInput = mutablePinEntries, isAutoConfirmEnabled = isAutoConfirmEnabled, @@ -183,8 +187,22 @@ constructor( mutablePinInput.value = mutablePinInput.value.deleteLast() } + fun onBackspaceButtonPressed(view: View?) { + if (bouncerHapticPlayer?.isEnabled == true) { + bouncerHapticPlayer.playDeleteKeyPressFeedback() + } else { + view?.performHapticFeedback( + HapticFeedbackConstants.VIRTUAL_KEY, + HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING, + ) + } + } + /** Notifies that the user long-pressed the backspace button. */ fun onBackspaceButtonLongPressed() { + if (bouncerHapticPlayer?.isEnabled == true) { + bouncerHapticPlayer.playDeleteKeyLongPressedFeedback() + } clearInput() } @@ -266,13 +284,24 @@ constructor( } } - /** Notifies that the user has pressed down on a digit button. */ - fun onDigitButtonDown() { + /** + * Notifies that the user has pressed down on a digit button. This function also performs haptic + * feedback on the view. + */ + fun onDigitButtonDown(view: View?) { if (ComposeBouncerFlags.isOnlyComposeBouncerEnabled()) { // Current PIN bouncer informs FalsingInteractor#avoidGesture() upon every Pin button // touch. super.onDown() } + if (bouncerHapticPlayer?.isEnabled == true) { + bouncerHapticPlayer.playNumpadKeyFeedback() + } else { + view?.performHapticFeedback( + HapticFeedbackConstants.VIRTUAL_KEY, + HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING, + ) + } } @AssistedFactory @@ -281,6 +310,7 @@ constructor( isInputEnabled: StateFlow<Boolean>, onIntentionalUserInput: () -> Unit, authenticationMethod: AuthenticationMethodModel, + bouncerHapticPlayer: BouncerHapticPlayer, ): PinBouncerViewModel } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java index 769976ef5058..ae4b679dd4b8 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java @@ -282,6 +282,8 @@ public class FalsingDataProvider { return !mRecentKeyEvents.isEmpty(); } + // Deprecated in favor of {@code isTouchScreenSource}, b/329221787 + @Deprecated public boolean isFromTrackpad() { if (Flags.nonTouchscreenDevicesBypassFalsing()) { return false; diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java index c7a47b18f467..1ada56dea45a 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java @@ -30,6 +30,7 @@ import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.os.Build; +import android.os.UserHandle; import android.provider.Settings; import android.util.Log; @@ -37,6 +38,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEventLogger; import com.android.systemui.CoreStartable; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.user.utils.UserScopedService; import javax.inject.Inject; import javax.inject.Provider; @@ -67,13 +69,13 @@ public class ClipboardListener implements public ClipboardListener(Context context, Provider<ClipboardOverlayController> clipboardOverlayControllerProvider, ClipboardToast clipboardToast, - ClipboardManager clipboardManager, + UserScopedService<ClipboardManager> clipboardManager, KeyguardManager keyguardManager, UiEventLogger uiEventLogger) { mContext = context; mOverlayProvider = clipboardOverlayControllerProvider; mClipboardToast = clipboardToast; - mClipboardManager = clipboardManager; + mClipboardManager = clipboardManager.forUser(UserHandle.CURRENT); mKeyguardManager = keyguardManager; mUiEventLogger = uiEventLogger; } diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt index 6e01393015ed..08a7c395e57f 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt @@ -19,11 +19,13 @@ package com.android.systemui.communal import android.provider.Settings import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.TransitionKey +import com.android.internal.logging.UiEventLogger import com.android.systemui.CoreStartable import com.android.systemui.Flags.communalSceneKtfRefactor import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor +import com.android.systemui.communal.shared.log.CommunalUiEvent import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.communal.shared.model.CommunalTransitionKeys import com.android.systemui.communal.shared.model.EditModeState @@ -84,6 +86,7 @@ constructor( @Application private val applicationScope: CoroutineScope, @Background private val bgScope: CoroutineScope, @Main private val mainDispatcher: CoroutineDispatcher, + private val uiEventLogger: UiEventLogger, ) : CoreStartable { private var screenTimeout: Int = DEFAULT_SCREEN_TIMEOUT @@ -146,7 +149,7 @@ constructor( screenTimeout = systemSettings.getInt( Settings.System.SCREEN_OFF_TIMEOUT, - DEFAULT_SCREEN_TIMEOUT + DEFAULT_SCREEN_TIMEOUT, ) } .launchIn(bgScope) @@ -160,7 +163,7 @@ constructor( combine( communalSceneInteractor.currentScene, // Emit a value on start so the combine starts. - communalInteractor.userActivity.emitOnStart() + communalInteractor.userActivity.emitOnStart(), ) { scene, _ -> // Only timeout if we're on the hub is open. scene == CommunalScenes.Communal @@ -184,6 +187,7 @@ constructor( CommunalScenes.Blank, "dream started after timeout", ) + uiEventLogger.log(CommunalUiEvent.COMMUNAL_HUB_TIMEOUT) } } } @@ -212,6 +216,7 @@ constructor( newScene = CommunalScenes.Blank, loggingReason = "hub timeout", ) + uiEventLogger.log(CommunalUiEvent.COMMUNAL_HUB_TIMEOUT) } timeoutJob = null } @@ -219,7 +224,7 @@ constructor( } private suspend fun determineSceneAfterTransition( - lastStartedTransition: TransitionStep, + lastStartedTransition: TransitionStep ): Pair<SceneKey, TransitionKey>? { val to = lastStartedTransition.to val from = lastStartedTransition.from @@ -251,9 +256,8 @@ constructor( Pair(CommunalScenes.Blank, CommunalTransitionKeys.SimpleFade) } from == KeyguardState.DOZING && to == KeyguardState.GLANCEABLE_HUB -> { - // Make sure the communal hub is showing (immediately, not fading in) when - // transitioning from dozing to hub. - Pair(CommunalScenes.Communal, CommunalTransitionKeys.Immediately) + // Make sure the communal hub is showing when transitioning from dozing to hub. + Pair(CommunalScenes.Communal, CommunalTransitionKeys.SimpleFade) } else -> null } diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalTransitionKeys.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalTransitionKeys.kt index 11fb2332dc5f..78156dbc8964 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalTransitionKeys.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalTransitionKeys.kt @@ -30,6 +30,4 @@ object CommunalTransitionKeys { val ToEditMode = TransitionKey("ToEditMode") /** Transition to the glanceable hub after exiting edit mode */ val FromEditMode = TransitionKey("FromEditMode") - /** Immediately transitions without any delay */ - val Immediately = TransitionKey("Immediately") } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java index 8818c3af4916..8f913ff01337 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java @@ -733,9 +733,8 @@ public class FrameworkServicesModule { } @Provides - @Singleton - static ClipboardManager provideClipboardManager(Context context) { - return context.getSystemService(ClipboardManager.class); + static UserScopedService<ClipboardManager> provideClipboardManager(Context context) { + return new UserScopedServiceImpl<>(context, ClipboardManager.class); } @Provides diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt index e17e530a03d9..5259c5dca39f 100644 --- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt @@ -26,7 +26,9 @@ import com.android.systemui.deviceentry.shared.model.DeviceEntryRestrictionReaso import com.android.systemui.deviceentry.shared.model.DeviceUnlockSource import com.android.systemui.deviceentry.shared.model.DeviceUnlockStatus import com.android.systemui.flags.SystemPropertiesHelper +import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.domain.interactor.TrustInteractor +import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated import javax.inject.Inject @@ -36,6 +38,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf @@ -57,6 +60,7 @@ constructor( private val powerInteractor: PowerInteractor, private val biometricSettingsInteractor: DeviceEntryBiometricSettingsInteractor, private val systemPropertiesHelper: SystemPropertiesHelper, + keyguardTransitionInteractor: KeyguardTransitionInteractor, ) { private val deviceUnlockSource = @@ -74,7 +78,7 @@ constructor( trustInteractor.isTrusted.filter { it }.map { DeviceUnlockSource.TrustAgent }, authenticationInteractor.onAuthenticationResult .filter { it } - .map { DeviceUnlockSource.BouncerInput } + .map { DeviceUnlockSource.BouncerInput }, ) private val faceEnrolledAndEnabled = biometricSettingsInteractor.isFaceAuthEnrolledAndEnabled @@ -170,10 +174,20 @@ constructor( combine( powerInteractor.isAsleep, isInLockdown, - ::Pair, + keyguardTransitionInteractor + .transitionValue(KeyguardState.AOD) + .map { it == 1f } + .distinctUntilChanged(), + ::Triple, ) - .flatMapLatestConflated { (isAsleep, isInLockdown) -> - if (isAsleep || isInLockdown) { + .flatMapLatestConflated { (isAsleep, isInLockdown, isAod) -> + val isForceLocked = + when { + isAsleep && !isAod -> true + isInLockdown -> true + else -> false + } + if (isForceLocked) { flowOf(DeviceUnlockStatus(false, null)) } else { deviceUnlockSource.map { DeviceUnlockStatus(true, it) } diff --git a/packages/SystemUI/src/com/android/systemui/education/data/model/GestureEduModel.kt b/packages/SystemUI/src/com/android/systemui/education/data/model/GestureEduModel.kt index 1daaa1128ba0..500c5b387ac6 100644 --- a/packages/SystemUI/src/com/android/systemui/education/data/model/GestureEduModel.kt +++ b/packages/SystemUI/src/com/android/systemui/education/data/model/GestureEduModel.kt @@ -16,6 +16,7 @@ package com.android.systemui.education.data.model +import com.android.systemui.contextualeducation.GestureType import java.time.Instant /** @@ -23,6 +24,7 @@ import java.time.Instant * gesture stores its own model separately. */ data class GestureEduModel( + val gestureType: GestureType, val signalCount: Int = 0, val educationShownCount: Int = 0, val lastShortcutTriggeredTime: Instant? = null, diff --git a/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt b/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt index 01f838ff1ea7..29785959de18 100644 --- a/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/education/data/repository/UserContextualEducationRepository.kt @@ -17,6 +17,8 @@ package com.android.systemui.education.data.repository import android.content.Context +import android.hardware.input.InputManager +import android.hardware.input.KeyGestureEvent import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.MutablePreferences import androidx.datastore.preferences.core.PreferenceDataStoreFactory @@ -25,23 +27,31 @@ import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.intPreferencesKey import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.preferencesDataStoreFile +import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.contextualeducation.GestureType +import com.android.systemui.contextualeducation.GestureType.ALL_APPS import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.education.dagger.ContextualEducationModule.EduDataStoreScope import com.android.systemui.education.data.model.EduDeviceConnectionTime import com.android.systemui.education.data.model.GestureEduModel +import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow import java.time.Instant +import java.util.concurrent.Executor import javax.inject.Inject import javax.inject.Provider import kotlin.properties.Delegates.notNull +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.cancel +import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map /** @@ -64,6 +74,8 @@ interface ContextualEducationRepository { suspend fun updateEduDeviceConnectionTime( transform: (EduDeviceConnectionTime) -> EduDeviceConnectionTime ) + + val keyboardShortcutTriggered: Flow<GestureType> } /** @@ -75,9 +87,13 @@ class UserContextualEducationRepository @Inject constructor( @Application private val applicationContext: Context, - @EduDataStoreScope private val dataStoreScopeProvider: Provider<CoroutineScope> + @EduDataStoreScope private val dataStoreScopeProvider: Provider<CoroutineScope>, + private val inputManager: InputManager, + @Background private val backgroundDispatcher: CoroutineDispatcher, ) : ContextualEducationRepository { companion object { + const val TAG = "UserContextualEducationRepository" + const val SIGNAL_COUNT_SUFFIX = "_SIGNAL_COUNT" const val NUMBER_OF_EDU_SHOWN_SUFFIX = "_NUMBER_OF_EDU_SHOWN" const val LAST_SHORTCUT_TRIGGERED_TIME_SUFFIX = "_LAST_SHORTCUT_TRIGGERED_TIME" @@ -98,6 +114,30 @@ constructor( @OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class) private val prefData: Flow<Preferences> = datastore.filterNotNull().flatMapLatest { it.data } + override val keyboardShortcutTriggered: Flow<GestureType> = + conflatedCallbackFlow { + val listener = + InputManager.KeyGestureEventListener { event -> + // Only store keyboard shortcut time for gestures providing keyboard + // education + val shortcutType = + when (event.keyGestureType) { + KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS, + KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS -> ALL_APPS + + else -> null + } + + if (shortcutType != null) { + trySendWithFailureLogging(shortcutType, TAG) + } + } + + inputManager.registerKeyGestureEventListener(Executor(Runnable::run), listener) + awaitClose { inputManager.unregisterKeyGestureEventListener(listener) } + } + .flowOn(backgroundDispatcher) + override fun setUser(userId: Int) { dataStoreScope?.cancel() val newDsScope = dataStoreScopeProvider.get() @@ -136,7 +176,8 @@ constructor( preferences[getLastEducationTimeKey(gestureType)]?.let { Instant.ofEpochSecond(it) }, - userId = userId + userId = userId, + gestureType = gestureType, ) } diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/ContextualEducationInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/ContextualEducationInteractor.kt index 10be26e1ce0f..c88b36495ac2 100644 --- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/ContextualEducationInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/ContextualEducationInteractor.kt @@ -18,7 +18,10 @@ package com.android.systemui.education.domain.interactor import com.android.systemui.CoreStartable import com.android.systemui.contextualeducation.GestureType +import com.android.systemui.contextualeducation.GestureType.ALL_APPS import com.android.systemui.contextualeducation.GestureType.BACK +import com.android.systemui.contextualeducation.GestureType.HOME +import com.android.systemui.contextualeducation.GestureType.OVERVIEW import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.education.dagger.ContextualEducationModule.EduClock @@ -53,6 +56,13 @@ constructor( ) : CoreStartable { val backGestureModelFlow = readEduModelsOnSignalCountChanged(BACK) + val homeGestureModelFlow = readEduModelsOnSignalCountChanged(HOME) + val overviewGestureModelFlow = readEduModelsOnSignalCountChanged(OVERVIEW) + val allAppsGestureModelFlow = readEduModelsOnSignalCountChanged(ALL_APPS) + val eduDeviceConnectionTimeFlow = + repository.readEduDeviceConnectionTime().distinctUntilChanged() + + val keyboardShortcutTriggered = repository.keyboardShortcutTriggered override fun start() { backgroundScope.launch { diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt index 43855d971a2a..faee32694964 100644 --- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt @@ -16,15 +16,8 @@ package com.android.systemui.education.domain.interactor -import android.hardware.input.InputManager -import android.hardware.input.InputManager.KeyGestureEventListener -import android.hardware.input.KeyGestureEvent import android.os.SystemProperties import com.android.systemui.CoreStartable -import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging -import com.android.systemui.contextualeducation.GestureType -import com.android.systemui.contextualeducation.GestureType.ALL_APPS -import com.android.systemui.contextualeducation.GestureType.BACK import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.education.dagger.ContextualEducationModule.EduClock @@ -32,19 +25,19 @@ import com.android.systemui.education.data.model.GestureEduModel import com.android.systemui.education.shared.model.EducationInfo import com.android.systemui.education.shared.model.EducationUiType import com.android.systemui.inputdevice.data.repository.UserInputDeviceRepository -import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow import java.time.Clock -import java.util.concurrent.Executor import javax.inject.Inject import kotlin.time.Duration import kotlin.time.Duration.Companion.days import kotlin.time.DurationUnit import kotlin.time.toDuration import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.merge import kotlinx.coroutines.launch /** Allow listening to new contextual education triggered */ @@ -55,7 +48,6 @@ constructor( @Background private val backgroundScope: CoroutineScope, private val contextualEducationInteractor: ContextualEducationInteractor, private val userInputDeviceRepository: UserInputDeviceRepository, - private val inputManager: InputManager, @EduClock private val clock: Clock, ) : CoreStartable { @@ -82,34 +74,32 @@ constructor( private val _educationTriggered = MutableStateFlow<EducationInfo?>(null) val educationTriggered = _educationTriggered.asStateFlow() - private val keyboardShortcutTriggered: Flow<GestureType> = conflatedCallbackFlow { - val listener = KeyGestureEventListener { event -> - // Only store keyboard shortcut time for gestures providing keyboard education - val shortcutType = - when (event.keyGestureType) { - KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS -> ALL_APPS - else -> null - } - - if (shortcutType != null) { - trySendWithFailureLogging(shortcutType, TAG) - } - } - - inputManager.registerKeyGestureEventListener(Executor(Runnable::run), listener) - awaitClose { inputManager.unregisterKeyGestureEventListener(listener) } - } - + @OptIn(ExperimentalCoroutinesApi::class) override fun start() { backgroundScope.launch { - contextualEducationInteractor.backGestureModelFlow.collect { - if (isUsageSessionExpired(it)) { - contextualEducationInteractor.startNewUsageSession(BACK) - } else if (isEducationNeeded(it)) { - _educationTriggered.value = EducationInfo(BACK, getEduType(it), it.userId) - contextualEducationInteractor.updateOnEduTriggered(BACK) + contextualEducationInteractor.eduDeviceConnectionTimeFlow + .flatMapLatest { + val gestureFlows = mutableListOf<Flow<GestureEduModel>>() + if (it.touchpadFirstConnectionTime != null) { + gestureFlows.add(contextualEducationInteractor.backGestureModelFlow) + gestureFlows.add(contextualEducationInteractor.homeGestureModelFlow) + gestureFlows.add(contextualEducationInteractor.overviewGestureModelFlow) + } + + if (it.keyboardFirstConnectionTime != null) { + gestureFlows.add(contextualEducationInteractor.allAppsGestureModelFlow) + } + gestureFlows.merge() + } + .collect { + if (isUsageSessionExpired(it)) { + contextualEducationInteractor.startNewUsageSession(it.gestureType) + } else if (isEducationNeeded(it)) { + _educationTriggered.value = + EducationInfo(it.gestureType, getEduType(it), it.userId) + contextualEducationInteractor.updateOnEduTriggered(it.gestureType) + } } - } } backgroundScope.launch { @@ -139,7 +129,7 @@ constructor( } backgroundScope.launch { - keyboardShortcutTriggered.collect { + contextualEducationInteractor.keyboardShortcutTriggered.collect { contextualEducationInteractor.updateShortcutTriggerTime(it) } } diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt index 6318dc000c21..0b775ab486bd 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt @@ -31,9 +31,7 @@ import com.android.systemui.Flags.statusBarCallChipNotificationIcon import com.android.systemui.Flags.statusBarScreenSharingChips import com.android.systemui.Flags.statusBarUseReposForCallChip import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.keyguard.KeyguardBottomAreaRefactor import com.android.systemui.keyguard.MigrateClocksToBlueprint -import com.android.systemui.keyguard.shared.ComposeLockscreen import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.shared.flag.DualShade import com.android.systemui.statusbar.notification.collection.SortBySectionTimeFlag @@ -62,10 +60,6 @@ class FlagDependencies @Inject constructor(featureFlags: FeatureFlagsClassic, ha // SceneContainer dependencies SceneContainerFlag.getFlagDependencies().forEach { (alpha, beta) -> alpha dependsOn beta } - // ComposeLockscreen dependencies - ComposeLockscreen.token dependsOn KeyguardBottomAreaRefactor.token - ComposeLockscreen.token dependsOn MigrateClocksToBlueprint.token - // CommunalHub dependencies communalHub dependsOn MigrateClocksToBlueprint.token @@ -99,7 +93,7 @@ class FlagDependencies @Inject constructor(featureFlags: FeatureFlagsClassic, ha get() = FlagToken( FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON, - statusBarCallChipNotificationIcon() + statusBarCallChipNotificationIcon(), ) private inline val statusBarScreenSharingChipsToken diff --git a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt index e50c05c7f6ed..e09e1987698d 100644 --- a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt +++ b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt @@ -29,6 +29,7 @@ import com.android.systemui.animation.Expandable import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel import com.android.systemui.log.dagger.QSLog +import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.qs.QSTile import com.android.systemui.statusbar.VibratorHelper import com.android.systemui.statusbar.policy.KeyguardStateController @@ -44,12 +45,12 @@ import javax.inject.Inject * @property[vibratorHelper] The [VibratorHelper] to deliver haptic effects. * @property[effectDuration] The duration of the effect in ms. */ -// TODO(b/332902869): In addition from being injectable, we can consider making it a singleton class QSLongPressEffect @Inject constructor( private val vibratorHelper: VibratorHelper?, private val keyguardStateController: KeyguardStateController, + private val falsingManager: FalsingManager, @QSLog private val logBuffer: LogBuffer, ) { @@ -72,7 +73,7 @@ constructor( private val durations = vibratorHelper?.getPrimitiveDurations( VibrationEffect.Composition.PRIMITIVE_LOW_TICK, - VibrationEffect.Composition.PRIMITIVE_SPIN + VibrationEffect.Composition.PRIMITIVE_SPIN, ) private var longPressHint: VibrationEffect? = null @@ -152,15 +153,27 @@ constructor( logEvent(qsTile?.tileSpec, state, "animation completed") when (state) { State.RUNNING_FORWARD -> { - vibrate(snapEffect) - if (keyguardStateController.isUnlocked) { + val wasFalseLongTap = falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY) + if (wasFalseLongTap) { + callback?.onResetProperties() + setState(State.IDLE) + logEvent(qsTile?.tileSpec, state, "false long click. No action triggered") + } else if (keyguardStateController.isUnlocked) { + vibrate(snapEffect) setState(State.LONG_CLICKED) + qsTile?.longClick(expandable) + logEvent(qsTile?.tileSpec, state, "long click action triggered") } else { + vibrate(snapEffect) callback?.onResetProperties() setState(State.IDLE) + qsTile?.longClick(expandable) + logEvent( + qsTile?.tileSpec, + state, + "properties reset and long click action triggered", + ) } - logEvent(qsTile?.tileSpec, state, "long click action triggered") - qsTile?.longClick(expandable) } State.RUNNING_BACKWARDS_FROM_UP -> { callback?.onEffectFinishedReversing() @@ -236,7 +249,7 @@ constructor( LongPressHapticBuilder.createLongPressHint( durations?.get(0) ?: LongPressHapticBuilder.INVALID_DURATION, durations?.get(1) ?: LongPressHapticBuilder.INVALID_DURATION, - effectDuration + effectDuration, ) setState(State.IDLE) return true @@ -265,7 +278,7 @@ constructor( } override fun dialogTransitionController( - cuj: DialogCuj?, + cuj: DialogCuj? ): DialogTransitionAnimator.Controller? = DialogTransitionAnimator.Controller.fromView(view, cuj) } @@ -298,7 +311,7 @@ constructor( str2 = event str3 = state.name }, - { "[long-press effect on $str1 tile] $str2 on state: $str3" } + { "[long-press effect on $str1 tile] $str2 on state: $str3" }, ) } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/InputDeviceTutorialLogger.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/InputDeviceTutorialLogger.kt index 95251749132d..48f5cb6dc219 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/InputDeviceTutorialLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/InputDeviceTutorialLogger.kt @@ -16,27 +16,27 @@ package com.android.systemui.inputdevice.tutorial +import com.android.systemui.inputdevice.tutorial.domain.interactor.ConnectionState +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen as KeyboardTouchpadTutorialScreen +import com.android.systemui.log.ConstantStringsLogger +import com.android.systemui.log.ConstantStringsLoggerImpl import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel +import com.android.systemui.log.core.MessageInitializer +import com.android.systemui.log.core.MessagePrinter import com.android.systemui.log.dagger.InputDeviceTutorialLog -import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen -import com.google.errorprone.annotations.CompileTimeConstant +import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen as TouchpadTutorialScreen import javax.inject.Inject private const val TAG = "InputDeviceTutorial" class InputDeviceTutorialLogger @Inject -constructor(@InputDeviceTutorialLog private val buffer: LogBuffer) { +constructor(@InputDeviceTutorialLog private val buffer: LogBuffer) : + ConstantStringsLogger by ConstantStringsLoggerImpl(buffer, TAG) { - fun log(@CompileTimeConstant s: String) { - buffer.log(TAG, LogLevel.INFO, message = s) - } - - fun logGoingToScreen(screen: Screen, context: TutorialContext) { - buffer.log( - TAG, - LogLevel.INFO, + fun logGoingToScreen(screen: TouchpadTutorialScreen, context: TutorialContext) { + logInfo( { str1 = screen.toString() str2 = context.string @@ -46,7 +46,58 @@ constructor(@InputDeviceTutorialLog private val buffer: LogBuffer) { } fun logCloseTutorial(context: TutorialContext) { - buffer.log(TAG, LogLevel.INFO, { str1 = context.string }, { "Closing $str1" }) + logInfo({ str1 = context.string }, { "Closing $str1" }) + } + + fun logOpenTutorial(context: TutorialContext) { + logInfo({ str1 = context.string }, { "Opening $str1" }) + } + + fun logNextScreenMissingHardware(nextScreen: KeyboardTouchpadTutorialScreen) { + buffer.log( + TAG, + LogLevel.WARNING, + { str1 = nextScreen.toString() }, + { "next screen should be $str1 but required hardware is missing" } + ) + } + + fun logNextScreen(nextScreen: KeyboardTouchpadTutorialScreen) { + logInfo({ str1 = nextScreen.toString() }, { "going to $str1 screen" }) + } + + fun logNewConnectionState(connectionState: ConnectionState) { + logInfo( + { + bool1 = connectionState.touchpadConnected + bool2 = connectionState.keyboardConnected + }, + { "Received connection state: touchpad connected: $bool1 keyboard connected: $bool2" } + ) + } + + fun logMovingBetweenScreens( + previousScreen: KeyboardTouchpadTutorialScreen?, + currentScreen: KeyboardTouchpadTutorialScreen + ) { + logInfo( + { + str1 = previousScreen?.toString() ?: "NO_SCREEN" + str2 = currentScreen.toString() + }, + { "Moving from $str1 screen to $str2 screen" } + ) + } + + fun logGoingBack(previousScreen: KeyboardTouchpadTutorialScreen) { + logInfo({ str1 = previousScreen.toString() }, { "Going back to $str1 screen" }) + } + + private inline fun logInfo( + messageInitializer: MessageInitializer, + noinline messagePrinter: MessagePrinter + ) { + buffer.log(TAG, LogLevel.INFO, messageInitializer, messagePrinter) } enum class TutorialContext(val string: String) { diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt index 1adc285e6bb5..c130c6c7fe12 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt @@ -28,6 +28,8 @@ import androidx.lifecycle.Lifecycle.State.STARTED import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.lifecycleScope import com.android.compose.theme.PlatformTheme +import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger +import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger.TutorialContext import com.android.systemui.inputdevice.tutorial.TouchpadTutorialScreensProvider import com.android.systemui.inputdevice.tutorial.ui.composable.ActionKeyTutorialScreen import com.android.systemui.inputdevice.tutorial.ui.viewmodel.KeyboardTouchpadTutorialViewModel @@ -48,6 +50,7 @@ class KeyboardTouchpadTutorialActivity constructor( private val viewModelFactoryAssistedProvider: ViewModelFactoryAssistedProvider, private val touchpadTutorialScreensProvider: Optional<TouchpadTutorialScreensProvider>, + private val logger: InputDeviceTutorialLogger, ) : ComponentActivity() { companion object { @@ -74,6 +77,7 @@ constructor( lifecycleScope.launch { vm.closeActivity.collect { finish -> if (finish) { + logger.logCloseTutorial(TutorialContext.KEYBOARD_TOUCHPAD_TUTORIAL) finish() } } @@ -81,6 +85,9 @@ constructor( setContent { PlatformTheme { KeyboardTouchpadTutorialContainer(vm, touchpadTutorialScreensProvider) } } + if (savedInstanceState == null) { + logger.logOpenTutorial(TutorialContext.KEYBOARD_TOUCHPAD_TUTORIAL) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt index 315c102e94d0..5cf19677a98e 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt @@ -22,6 +22,7 @@ import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger import com.android.systemui.inputdevice.tutorial.domain.interactor.ConnectionState import com.android.systemui.inputdevice.tutorial.domain.interactor.KeyboardTouchpadConnectionInteractor import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY @@ -47,6 +48,7 @@ class KeyboardTouchpadTutorialViewModel( private val gesturesInteractor: Optional<TouchpadGesturesInteractor>, private val keyboardTouchpadConnectionInteractor: KeyboardTouchpadConnectionInteractor, private val hasTouchpadTutorialScreens: Boolean, + private val logger: InputDeviceTutorialLogger, handle: SavedStateHandle ) : ViewModel(), DefaultLifecycleObserver { @@ -68,7 +70,10 @@ class KeyboardTouchpadTutorialViewModel( init { viewModelScope.launch { - keyboardTouchpadConnectionInteractor.connectionState.collect { connectionState = it } + keyboardTouchpadConnectionInteractor.connectionState.collect { + logger.logNewConnectionState(connectionState) + connectionState = it + } } viewModelScope.launch { @@ -89,7 +94,14 @@ class KeyboardTouchpadTutorialViewModel( viewModelScope.launch { // close activity if screen requires touchpad but we don't have it. This can only happen // when current sysui build doesn't contain touchpad module dependency - _screen.filterNot { it.canBeShown() }.collect { _closeActivity.value = true } + _screen + .filterNot { it.canBeShown() } + .collect { + logger.e( + "Touchpad is connected but touchpad module is missing, something went wrong" + ) + _closeActivity.value = true + } } } @@ -114,11 +126,14 @@ class KeyboardTouchpadTutorialViewModel( if (requiredHardwarePresent(nextScreen)) { break } + logger.logNextScreenMissingHardware(nextScreen) nextScreen = nextScreen.next() } if (nextScreen == null) { + logger.d("Final screen reached, closing tutorial") _closeActivity.value = true } else { + logger.logNextScreen(nextScreen) _screen.value = nextScreen screensBackStack.add(nextScreen) } @@ -127,6 +142,7 @@ class KeyboardTouchpadTutorialViewModel( private fun Screen.canBeShown() = requiredHardware != TOUCHPAD || hasTouchpadTutorialScreens private fun setupDeviceState(previousScreen: Screen?, currentScreen: Screen) { + logger.logMovingBetweenScreens(previousScreen, currentScreen) if (previousScreen?.requiredHardware == currentScreen.requiredHardware) return previousScreen?.let { clearDeviceStateForScreen(it) } when (currentScreen.requiredHardware) { @@ -153,6 +169,7 @@ class KeyboardTouchpadTutorialViewModel( _closeActivity.value = true } else { screensBackStack.removeLast() + logger.logGoingBack(screensBackStack.last()) _screen.value = screensBackStack.last() } } @@ -162,6 +179,7 @@ class KeyboardTouchpadTutorialViewModel( constructor( private val gesturesInteractor: Optional<TouchpadGesturesInteractor>, private val keyboardTouchpadConnected: KeyboardTouchpadConnectionInteractor, + private val logger: InputDeviceTutorialLogger, @Assisted private val hasTouchpadTutorialScreens: Boolean, ) : AbstractSavedStateViewModelFactory() { @@ -180,6 +198,7 @@ class KeyboardTouchpadTutorialViewModel( gesturesInteractor, keyboardTouchpadConnected, hasTouchpadTutorialScreens, + logger, handle ) as T diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt index df0f10acac1f..416eabae78eb 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt @@ -24,12 +24,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView -import androidx.constraintlayout.widget.ConstraintSet -import androidx.constraintlayout.widget.ConstraintSet.BOTTOM -import androidx.constraintlayout.widget.ConstraintSet.END -import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID -import androidx.constraintlayout.widget.ConstraintSet.START -import androidx.constraintlayout.widget.ConstraintSet.TOP import com.android.compose.animation.scene.MutableSceneTransitionLayoutState import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.SceneTransitionLayout @@ -47,7 +41,6 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor -import com.android.systemui.keyguard.shared.ComposeLockscreen import com.android.systemui.keyguard.shared.model.LockscreenSceneBlueprint import com.android.systemui.keyguard.ui.binder.KeyguardBlueprintViewBinder import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder @@ -128,7 +121,7 @@ constructor( keyguardStatusViewComponentFactory.build( LayoutInflater.from(context).inflate(R.layout.keyguard_status_view, null) as KeyguardStatusView, - context.display + context.display, ) val controller = statusViewComponent.keyguardStatusViewController controller.init() @@ -143,29 +136,12 @@ constructor( initializeViews() if (!SceneContainerFlag.isEnabled) { - if (ComposeLockscreen.isEnabled) { - val composeView = - createLockscreen( - context = context, - viewModelFactory = lockscreenContentViewModelFactory, - blueprints = lockscreenSceneBlueprintsLazy.get(), - ) - composeView.id = View.generateViewId() - val cs = ConstraintSet() - cs.clone(keyguardRootView) - cs.connect(composeView.id, START, PARENT_ID, START) - cs.connect(composeView.id, END, PARENT_ID, END) - cs.connect(composeView.id, TOP, PARENT_ID, TOP) - cs.connect(composeView.id, BOTTOM, PARENT_ID, BOTTOM) - keyguardRootView.addView(composeView) - } else { - KeyguardBlueprintViewBinder.bind( - keyguardRootView, - keyguardBlueprintViewModel, - keyguardClockViewModel, - smartspaceViewModel, - ) - } + KeyguardBlueprintViewBinder.bind( + keyguardRootView, + keyguardBlueprintViewModel, + keyguardClockViewModel, + smartspaceViewModel, + ) } if (deviceEntryUnlockTrackerViewBinder.isPresent) { deviceEntryUnlockTrackerViewBinder.get().bind(keyguardRootView) @@ -247,7 +223,7 @@ constructor( LockscreenContent( viewModelFactory = viewModelFactory, blueprints = sceneBlueprints, - clockInteractor = clockInteractor + clockInteractor = clockInteractor, ) ) { Content(modifier = Modifier.fillMaxSize()) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt index 406b9f6e6a0d..be873344b719 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt @@ -25,7 +25,9 @@ import android.provider.Settings.Global.ZEN_MODE_OFF import android.provider.Settings.Secure.ZEN_DURATION_FOREVER import android.provider.Settings.Secure.ZEN_DURATION_PROMPT import android.service.notification.ZenModeConfig +import android.util.Log import com.android.settingslib.notification.modes.EnableZenModeDialog +import com.android.settingslib.notification.modes.ZenMode import com.android.settingslib.notification.modes.ZenModeDialogMetricsLogger import com.android.systemui.animation.Expandable import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging @@ -35,30 +37,38 @@ import com.android.systemui.common.shared.model.Icon import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.keyguard.shared.quickaffordance.ActivationState +import com.android.systemui.modes.shared.ModesUi import com.android.systemui.res.R import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.policy.ZenModeController +import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.settings.SettingsProxyExt.observerFlow import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.flow.stateIn @SysUISingleton class DoNotDisturbQuickAffordanceConfig constructor( private val context: Context, private val controller: ZenModeController, + private val interactor: ZenModeInteractor, private val secureSettings: SecureSettings, private val userTracker: UserTracker, @Background private val backgroundDispatcher: CoroutineDispatcher, + @Background private val backgroundScope: CoroutineScope, private val testConditionId: Uri?, testDialog: EnableZenModeDialog?, ) : KeyguardQuickAffordanceConfig { @@ -67,15 +77,45 @@ constructor( constructor( context: Context, controller: ZenModeController, + interactor: ZenModeInteractor, secureSettings: SecureSettings, userTracker: UserTracker, @Background backgroundDispatcher: CoroutineDispatcher, - ) : this(context, controller, secureSettings, userTracker, backgroundDispatcher, null, null) + @Background backgroundScope: CoroutineScope, + ) : this( + context, + controller, + interactor, + secureSettings, + userTracker, + backgroundDispatcher, + backgroundScope, + null, + null, + ) - private var dndMode: Int = 0 - private var isAvailable = false + private var zenMode: Int = 0 + private var oldIsAvailable = false private var settingsValue: Int = 0 + private val dndMode: StateFlow<ZenMode?> by lazy { + ModesUi.assertInNewMode() + interactor.dndMode.stateIn( + scope = backgroundScope, + started = SharingStarted.Eagerly, + initialValue = null, + ) + } + + private val isAvailable: StateFlow<Boolean> by lazy { + ModesUi.assertInNewMode() + interactor.isZenAvailable.stateIn( + scope = backgroundScope, + started = SharingStarted.Eagerly, + initialValue = false, + ) + } + private val conditionUri: Uri get() = testConditionId @@ -104,42 +144,68 @@ constructor( override val pickerIconResourceId: Int = R.drawable.ic_do_not_disturb override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = - combine( - conflatedCallbackFlow { - val callback = - object : ZenModeController.Callback { - override fun onZenChanged(zen: Int) { - dndMode = zen - trySendWithFailureLogging(updateState(), TAG) - } + if (ModesUi.isEnabled) { + combine(isAvailable, dndMode) { isAvailable, dndMode -> + if (!isAvailable) { + KeyguardQuickAffordanceConfig.LockScreenState.Hidden + } else if (dndMode?.isActive == true) { + KeyguardQuickAffordanceConfig.LockScreenState.Visible( + Icon.Resource( + R.drawable.qs_dnd_icon_on, + ContentDescription.Resource(R.string.dnd_is_on), + ), + ActivationState.Active, + ) + } else { + KeyguardQuickAffordanceConfig.LockScreenState.Visible( + Icon.Resource( + R.drawable.qs_dnd_icon_off, + ContentDescription.Resource(R.string.dnd_is_off), + ), + ActivationState.Inactive, + ) + } + } + } else { + combine( + conflatedCallbackFlow { + val callback = + object : ZenModeController.Callback { + override fun onZenChanged(zen: Int) { + zenMode = zen + trySendWithFailureLogging(updateState(), TAG) + } - override fun onZenAvailableChanged(available: Boolean) { - isAvailable = available - trySendWithFailureLogging(updateState(), TAG) + override fun onZenAvailableChanged(available: Boolean) { + oldIsAvailable = available + trySendWithFailureLogging(updateState(), TAG) + } } - } - dndMode = controller.zen - isAvailable = controller.isZenAvailable - trySendWithFailureLogging(updateState(), TAG) - - controller.addCallback(callback) - - awaitClose { controller.removeCallback(callback) } - }, - secureSettings - .observerFlow(userTracker.userId, Settings.Secure.ZEN_DURATION) - .onStart { emit(Unit) } - .map { secureSettings.getInt(Settings.Secure.ZEN_DURATION, ZEN_MODE_OFF) } - .flowOn(backgroundDispatcher) - .distinctUntilChanged() - .onEach { settingsValue = it } - ) { callbackFlowValue, _ -> - callbackFlowValue + zenMode = controller.zen + oldIsAvailable = controller.isZenAvailable + trySendWithFailureLogging(updateState(), TAG) + + controller.addCallback(callback) + + awaitClose { controller.removeCallback(callback) } + }, + secureSettings + .observerFlow(userTracker.userId, Settings.Secure.ZEN_DURATION) + .onStart { emit(Unit) } + .map { secureSettings.getInt(Settings.Secure.ZEN_DURATION, ZEN_MODE_OFF) } + .flowOn(backgroundDispatcher) + .distinctUntilChanged() + .onEach { settingsValue = it }, + ) { callbackFlowValue, _ -> + callbackFlowValue + } } override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState { - return if (controller.isZenAvailable) { + val isZenAvailable = if (ModesUi.isEnabled) isAvailable.value else controller.isZenAvailable + + return if (isZenAvailable) { KeyguardQuickAffordanceConfig.PickerScreenState.Default( configureIntent = Intent(Settings.ACTION_ZEN_MODE_SETTINGS) ) @@ -151,32 +217,63 @@ constructor( override fun onTriggered( expandable: Expandable? ): KeyguardQuickAffordanceConfig.OnTriggeredResult { - return when { - !isAvailable -> KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled - dndMode != ZEN_MODE_OFF -> { - controller.setZen(ZEN_MODE_OFF, null, TAG) - KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled - } - settingsValue == ZEN_DURATION_PROMPT -> - KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog( - dialog.createDialog(), - expandable - ) - settingsValue == ZEN_DURATION_FOREVER -> { - controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG) + return if (ModesUi.isEnabled) { + if (!isAvailable.value) { KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled + } else { + val dnd = dndMode.value + if (dnd == null) { + Log.wtf(TAG, "Triggered DND but it's null!?") + return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled + } + if (dnd.isActive) { + interactor.deactivateMode(dnd) + return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled + } else { + if (interactor.shouldAskForZenDuration(dnd)) { + // NOTE: The dialog handles turning on the mode itself. + return KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog( + dialog.createDialog(), + expandable, + ) + } else { + interactor.activateMode(dnd) + return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled + } + } } - else -> { - controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, conditionUri, TAG) - KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled + } else { + when { + !oldIsAvailable -> KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled + zenMode != ZEN_MODE_OFF -> { + controller.setZen(ZEN_MODE_OFF, null, TAG) + KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled + } + + settingsValue == ZEN_DURATION_PROMPT -> + KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog( + dialog.createDialog(), + expandable, + ) + + settingsValue == ZEN_DURATION_FOREVER -> { + controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG) + KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled + } + + else -> { + controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, conditionUri, TAG) + KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled + } } } } private fun updateState(): KeyguardQuickAffordanceConfig.LockScreenState { - return if (!isAvailable) { + ModesUi.assertInLegacyMode() + return if (!oldIsAvailable) { KeyguardQuickAffordanceConfig.LockScreenState.Hidden - } else if (dndMode == ZEN_MODE_OFF) { + } else if (zenMode == ZEN_MODE_OFF) { KeyguardQuickAffordanceConfig.LockScreenState.Visible( Icon.Resource( R.drawable.qs_dnd_icon_off, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt index 80a0cee4f319..b0820a747e17 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt @@ -24,7 +24,6 @@ import com.android.systemui.Flags.communalSceneKtfRefactor import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.shared.model.CommunalScenes -import com.android.systemui.communal.shared.model.CommunalTransitionKeys import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main @@ -95,10 +94,7 @@ constructor( scope.launch { powerInteractor.isAwake .filterRelevantKeyguardStateAnd { isAwake -> isAwake } - .sample( - keyguardInteractor.biometricUnlockState, - ::Pair, - ) + .sample(keyguardInteractor.biometricUnlockState, ::Pair) .collect { ( _, @@ -203,21 +199,21 @@ constructor( if (!SceneContainerFlag.isEnabled) { startTransitionTo( KeyguardState.GONE, - ownerReason = "waking from dozing" + ownerReason = "waking from dozing", ) } } else if (primaryBouncerShowing) { if (!SceneContainerFlag.isEnabled) { startTransitionTo( KeyguardState.PRIMARY_BOUNCER, - ownerReason = "waking from dozing" + ownerReason = "waking from dozing", ) } } else if (isIdleOnCommunal && !communalSceneKtfRefactor()) { if (!SceneContainerFlag.isEnabled) { startTransitionTo( KeyguardState.GLANCEABLE_HUB, - ownerReason = "waking from dozing" + ownerReason = "waking from dozing", ) } } else if (isCommunalAvailable && dreamManager.canStartDreaming(true)) { @@ -227,7 +223,7 @@ constructor( } else { startTransitionTo( KeyguardState.LOCKSCREEN, - ownerReason = "waking from dozing" + ownerReason = "waking from dozing", ) } } @@ -237,11 +233,9 @@ constructor( private suspend fun transitionToGlanceableHub() { if (communalSceneKtfRefactor()) { - communalSceneInteractor.changeScene( + communalSceneInteractor.snapToScene( newScene = CommunalScenes.Communal, loggingReason = "from dozing to hub", - // Immediately show the hub when transitioning from dozing to hub. - transitionKey = CommunalTransitionKeys.Immediately, ) } else { startTransitionTo(KeyguardState.GLANCEABLE_HUB) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt index 199caa168e31..7759298cb32a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt @@ -162,10 +162,9 @@ constructor( .filterRelevantKeyguardStateAnd { isAsleep -> isAsleep } .collect { if (communalSceneKtfRefactor()) { - communalSceneInteractor.changeScene( + communalSceneInteractor.snapToScene( newScene = CommunalScenes.Blank, loggingReason = "hub to dozing", - transitionKey = CommunalTransitionKeys.Immediately, keyguardState = KeyguardState.DOZING, ) } else { @@ -210,12 +209,12 @@ constructor( // ends, to avoid transitioning to OCCLUDED erroneously when exiting // the dream. .debounce(100.milliseconds), - ::Pair + ::Pair, ) .sampleFilter( // When launching activities from widgets on the hub, we have a // custom occlusion animation. - communalSceneInteractor.isLaunchingWidget, + communalSceneInteractor.isLaunchingWidget ) { launchingWidget -> !launchingWidget } @@ -253,7 +252,7 @@ constructor( noneOf( // When launching activities from widgets on the hub, we wait to change // scenes until the activity launch is complete. - communalSceneInteractor.isLaunchingWidget, + communalSceneInteractor.isLaunchingWidget ), ) .filterRelevantKeyguardStateAnd { isKeyguardGoingAway -> isKeyguardGoingAway } @@ -270,7 +269,7 @@ constructor( newScene = CommunalScenes.Blank, loggingReason = "hub to gone", transitionKey = CommunalTransitionKeys.SimpleFade, - keyguardState = KeyguardState.GONE + keyguardState = KeyguardState.GONE, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt index 7afc7596a994..6932eb51e141 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt @@ -25,13 +25,13 @@ import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository -import com.android.systemui.keyguard.shared.ComposeLockscreen import com.android.systemui.keyguard.shared.model.KeyguardBlueprint import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Type import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.domain.interactor.ShadeInteractor import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -64,7 +64,7 @@ constructor( /** Current BlueprintId */ val blueprintId = shadeInteractor.isShadeLayoutWide.map { isShadeLayoutWide -> - val useSplitShade = isShadeLayoutWide && !ComposeLockscreen.isEnabled + val useSplitShade = isShadeLayoutWide && !SceneContainerFlag.isEnabled when { useSplitShade -> SplitShadeKeyguardBlueprint.ID else -> DefaultKeyguardBlueprint.DEFAULT diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt index ed82159e6160..deb0b2d8f848 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt @@ -59,7 +59,6 @@ import com.android.systemui.keyguard.KeyguardBottomAreaRefactor import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.MigrateClocksToBlueprint import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor -import com.android.systemui.keyguard.shared.ComposeLockscreen import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters @@ -72,6 +71,7 @@ import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.FalsingManager import com.android.systemui.res.R +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.CrossFadeHelper import com.android.systemui.statusbar.VibratorHelper @@ -241,7 +241,7 @@ object KeyguardRootViewBinder { disposables += view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { - if (ComposeLockscreen.isEnabled) { + if (SceneContainerFlag.isEnabled) { view.setViewTreeOnBackPressedDispatcherOwner( object : OnBackPressedDispatcherOwner { override val onBackPressedDispatcher = @@ -261,10 +261,7 @@ object KeyguardRootViewBinder { -> if (biometricMessage?.message != null) { chipbarCoordinator!!.displayView( - createChipbarInfo( - biometricMessage.message, - R.drawable.ic_lock, - ) + createChipbarInfo(biometricMessage.message, R.drawable.ic_lock) ) } else { chipbarCoordinator!!.removeView(ID, "occludingAppMsgNull") @@ -327,12 +324,16 @@ object KeyguardRootViewBinder { .getDimensionPixelSize(R.dimen.shelf_appear_translation) .stateIn(this) viewModel.isNotifIconContainerVisible.collect { isVisible -> - childViews[aodNotificationIconContainerId] - ?.setAodNotifIconContainerIsVisible( - isVisible, - iconsAppearTranslationPx.value, - screenOffAnimationController, - ) + if (isVisible.value) { + blueprintViewModel.refreshBlueprint() + } else { + childViews[aodNotificationIconContainerId] + ?.setAodNotifIconContainerIsVisible( + isVisible, + iconsAppearTranslationPx.value, + screenOffAnimationController, + ) + } } } @@ -382,7 +383,7 @@ object KeyguardRootViewBinder { if (msdlFeedback()) { msdlPlayer?.playToken( MSDLToken.UNLOCK, - authInteractionProperties + authInteractionProperties, ) } else { vibratorHelper.performHapticFeedback( @@ -398,7 +399,7 @@ object KeyguardRootViewBinder { if (msdlFeedback()) { msdlPlayer?.playToken( MSDLToken.FAILURE, - authInteractionProperties + authInteractionProperties, ) } else { vibratorHelper.performHapticFeedback( @@ -425,7 +426,7 @@ object KeyguardRootViewBinder { blueprintViewModel, clockViewModel, childViews, - burnInParams + burnInParams, ) ) @@ -464,11 +465,7 @@ object KeyguardRootViewBinder { */ private fun createChipbarInfo(message: String, @DrawableRes icon: Int): ChipbarInfo { return ChipbarInfo( - startIcon = - TintedIcon( - Icon.Resource(icon, null), - ChipbarInfo.DEFAULT_ICON_TINT, - ), + startIcon = TintedIcon(Icon.Resource(icon, null), ChipbarInfo.DEFAULT_ICON_TINT), text = Text.Loaded(message), endItem = null, vibrationEffect = null, @@ -499,7 +496,7 @@ object KeyguardRootViewBinder { oldLeft: Int, oldTop: Int, oldRight: Int, - oldBottom: Int + oldBottom: Int, ) { // After layout, ensure the notifications are positioned correctly childViews[nsslPlaceholderId]?.let { notificationListPlaceholder -> @@ -515,7 +512,7 @@ object KeyguardRootViewBinder { viewModel.onNotificationContainerBoundsChanged( notificationListPlaceholder.top.toFloat(), notificationListPlaceholder.bottom.toFloat(), - animate = shouldAnimate + animate = shouldAnimate, ) } @@ -531,7 +528,7 @@ object KeyguardRootViewBinder { Int.MAX_VALUE } else { view.getTop() - } + }, ) } } else { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt index c6efcfad8da7..4cf3c4e7f6d0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBlueprintViewModel.kt @@ -25,20 +25,18 @@ import androidx.constraintlayout.widget.ConstraintLayout import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config +import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Type import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow -data class TransitionData( - val config: Config, - val start: Long = System.currentTimeMillis(), -) +data class TransitionData(val config: Config, val start: Long = System.currentTimeMillis()) class KeyguardBlueprintViewModel @Inject constructor( @Main private val handler: Handler, - keyguardBlueprintInteractor: KeyguardBlueprintInteractor, + private val keyguardBlueprintInteractor: KeyguardBlueprintInteractor, ) { val blueprint = keyguardBlueprintInteractor.blueprint val blueprintId = keyguardBlueprintInteractor.blueprintId @@ -76,6 +74,9 @@ constructor( } } + fun refreshBlueprint(type: Type = Type.NoTransition) = + keyguardBlueprintInteractor.refreshBlueprint(type) + fun updateTransitions(data: TransitionData?, mutate: MutableSet<Transition>.() -> Unit) { runningTransitions.mutate() @@ -95,7 +96,7 @@ constructor( Log.w( TAG, "runTransition: skipping ${transition::class.simpleName}: " + - "currentPriority=$currentPriority; config=$config" + "currentPriority=$currentPriority; config=$config", ) } apply() @@ -106,7 +107,7 @@ constructor( Log.i( TAG, "runTransition: running ${transition::class.simpleName}: " + - "currentPriority=$currentPriority; config=$config" + "currentPriority=$currentPriority; config=$config", ) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt index 73028c5cf496..36f684ee4759 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt @@ -25,10 +25,10 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor -import com.android.systemui.keyguard.shared.ComposeLockscreen import com.android.systemui.keyguard.shared.model.ClockSize import com.android.systemui.keyguard.shared.model.ClockSizeSetting import com.android.systemui.res.R +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerAlwaysOnDisplayViewModel import com.android.systemui.statusbar.ui.SystemBarUtilsProxy @@ -56,10 +56,9 @@ constructor( var burnInLayer: Layer? = null val clockSize: StateFlow<ClockSize> = - combine( - keyguardClockInteractor.selectedClockSize, - keyguardClockInteractor.clockSize, - ) { selectedSize, clockSize -> + combine(keyguardClockInteractor.selectedClockSize, keyguardClockInteractor.clockSize) { + selectedSize, + clockSize -> if (selectedSize == ClockSizeSetting.SMALL) ClockSize.SMALL else clockSize } .stateIn( @@ -80,10 +79,7 @@ constructor( val currentClock = keyguardClockInteractor.currentClock val hasCustomWeatherDataDisplay = - combine( - isLargeClockVisible, - currentClock, - ) { isLargeClock, currentClock -> + combine(isLargeClockVisible, currentClock) { isLargeClock, currentClock -> currentClock?.let { clock -> val face = if (isLargeClock) clock.largeClock else clock.smallClock face.config.hasCustomWeatherDataDisplay @@ -93,14 +89,14 @@ constructor( scope = applicationScope, started = SharingStarted.WhileSubscribed(), initialValue = - currentClock.value?.largeClock?.config?.hasCustomWeatherDataDisplay ?: false + currentClock.value?.largeClock?.config?.hasCustomWeatherDataDisplay ?: false, ) val clockShouldBeCentered: StateFlow<Boolean> = keyguardClockInteractor.clockShouldBeCentered.stateIn( scope = applicationScope, started = SharingStarted.WhileSubscribed(), - initialValue = false + initialValue = false, ) // To translate elements below smartspace in weather clock to avoid overlapping between date @@ -111,7 +107,7 @@ constructor( .stateIn( scope = applicationScope, started = SharingStarted.WhileSubscribed(), - initialValue = false + initialValue = false, ) val currentClockLayout: StateFlow<ClockLayout> = @@ -145,7 +141,7 @@ constructor( .stateIn( scope = applicationScope, started = SharingStarted.WhileSubscribed(), - initialValue = ClockLayout.SMALL_CLOCK + initialValue = ClockLayout.SMALL_CLOCK, ) val hasCustomPositionUpdatedAnimation: StateFlow<Boolean> = @@ -156,7 +152,7 @@ constructor( .stateIn( scope = applicationScope, started = SharingStarted.WhileSubscribed(), - initialValue = false + initialValue = false, ) /** Calculates the top margin for the small clock. */ @@ -164,10 +160,10 @@ constructor( val statusBarHeight = systemBarUtils.getStatusBarHeaderHeightKeyguard() return if (shadeInteractor.isShadeLayoutWide.value) { resources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin) - - if (ComposeLockscreen.isEnabled) statusBarHeight else 0 + if (SceneContainerFlag.isEnabled) statusBarHeight else 0 } else { resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) + - if (!ComposeLockscreen.isEnabled) statusBarHeight else 0 + if (!SceneContainerFlag.isEnabled) statusBarHeight else 0 } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt index 53cc15b8c588..7b55dac8eee1 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt @@ -42,7 +42,6 @@ import android.service.notification.StatusBarNotification import android.support.v4.media.MediaMetadataCompat import android.text.TextUtils import android.util.Log -import android.util.Pair import androidx.media.utils.MediaConstants import com.android.app.tracing.coroutines.traceCoroutine import com.android.systemui.dagger.SysUISingleton @@ -70,6 +69,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.async import kotlinx.coroutines.cancel +import kotlinx.coroutines.delay import kotlinx.coroutines.ensureActive /** Loads media information from media style [StatusBarNotification] classes. */ @@ -85,7 +85,7 @@ constructor( private val imageLoader: ImageLoader, private val statusBarManager: StatusBarManager, ) { - private val mediaProcessingJobs = ConcurrentHashMap<JobKey, Job>() + private val mediaProcessingJobs = ConcurrentHashMap<String, Job>() private val artworkWidth: Int = context.resources.getDimensionPixelSize( @@ -97,7 +97,7 @@ constructor( private val themeText = com.android.settingslib.Utils.getColorAttr( context, - com.android.internal.R.attr.textColorPrimary + com.android.internal.R.attr.textColorPrimary, ) .defaultColor @@ -112,11 +112,14 @@ constructor( * load will be cancelled. */ suspend fun loadMediaData(key: String, sbn: StatusBarNotification): MediaDataLoaderResult? { - logD(TAG) { "Loading media data for $key..." } - val jobKey = JobKey(key, sbn) val loadMediaJob = backgroundScope.async { loadMediaDataInBackground(key, sbn) } - loadMediaJob.invokeOnCompletion { mediaProcessingJobs.remove(jobKey) } - val existingJob = mediaProcessingJobs.put(jobKey, loadMediaJob) + loadMediaJob.invokeOnCompletion { + // We need to make sure we're removing THIS job after cancellation, not + // a job that we created later. + mediaProcessingJobs.remove(key, loadMediaJob) + } + val existingJob = mediaProcessingJobs.put(key, loadMediaJob) + logD(TAG) { "Loading media data for $key... / existing job: $existingJob" } existingJob?.cancel("New processing job incoming.") return loadMediaJob.await() } @@ -128,10 +131,15 @@ constructor( sbn: StatusBarNotification, ): MediaDataLoaderResult? = traceCoroutine("MediaDataLoader#loadMediaData") { + // We have apps spamming us with quick notification updates which can cause + // us to spend significant CPU time loading duplicate data. This debounces + // those requests at the cost of a bit of latency. + delay(DEBOUNCE_DELAY_MS) + val token = sbn.notification.extras.getParcelable( Notification.EXTRA_MEDIA_SESSION, - MediaSession.Token::class.java + MediaSession.Token::class.java, ) if (token == null) { Log.i(TAG, "Token was null, not loading media info") @@ -144,7 +152,7 @@ constructor( val appInfo = notification.extras.getParcelable( Notification.EXTRA_BUILDER_APPLICATION_INFO, - ApplicationInfo::class.java + ApplicationInfo::class.java, ) ?: getAppInfoFromPackage(sbn.packageName) // App name @@ -240,7 +248,7 @@ constructor( playbackLocation = playbackLocation, isPlaying = isPlaying, appUid = appUid, - isExplicit = isExplicit + isExplicit = isExplicit, ) } @@ -258,7 +266,7 @@ constructor( token: MediaSession.Token, appName: String, appIntent: PendingIntent, - packageName: String + packageName: String, ): MediaDataLoaderResult? { val mediaData = backgroundScope.async { @@ -270,7 +278,7 @@ constructor( token, appName, appIntent, - packageName + packageName, ) } return mediaData.await() @@ -286,7 +294,7 @@ constructor( token: MediaSession.Token, appName: String, appIntent: PendingIntent, - packageName: String + packageName: String, ): MediaDataLoaderResult? = traceCoroutine("MediaDataLoader#loadMediaDataForResumption") { if (desc.title.isNullOrBlank()) { @@ -338,14 +346,14 @@ constructor( appUid = appUid, isExplicit = isExplicit, resumeAction = resumeAction, - resumeProgress = progress + resumeProgress = progress, ) } private fun createActionsFromState( packageName: String, controller: MediaController, - user: UserHandle + user: UserHandle, ): MediaButton? { if (!mediaFlags.areMediaSessionActionsEnabled(packageName, user)) { return null @@ -368,7 +376,7 @@ constructor( */ private fun getDeviceInfoForRemoteCast( key: String, - sbn: StatusBarNotification + sbn: StatusBarNotification, ): MediaDeviceData? { val extras = sbn.notification.extras val deviceName = extras.getCharSequence(Notification.EXTRA_MEDIA_REMOTE_DEVICE, null) @@ -388,7 +396,7 @@ constructor( deviceDrawable, deviceName, deviceIntent, - showBroadcastButton = false + showBroadcastButton = false, ) } return null @@ -439,7 +447,7 @@ constructor( listOf( ContentResolver.SCHEME_CONTENT, ContentResolver.SCHEME_ANDROID_RESOURCE, - ContentResolver.SCHEME_FILE + ContentResolver.SCHEME_FILE, ) ) { Log.w(TAG, "Invalid album art uri $uri") @@ -451,7 +459,7 @@ constructor( source, artworkWidth, artworkHeight, - allocator = ImageDecoder.ALLOCATOR_SOFTWARE + allocator = ImageDecoder.ALLOCATOR_SOFTWARE, ) } @@ -459,7 +467,7 @@ constructor( uri: Uri, userId: Int, appUid: Int, - packageName: String + packageName: String, ): Bitmap? { try { val ugm = UriGrantsManager.getService() @@ -468,7 +476,7 @@ constructor( packageName, ContentProvider.getUriWithoutUserId(uri), Intent.FLAG_GRANT_READ_URI_PERMISSION, - ContentProvider.getUserIdFromUri(uri, userId) + ContentProvider.getUserIdFromUri(uri, userId), ) return loadBitmapFromUri(uri) } catch (e: SecurityException) { @@ -488,21 +496,20 @@ constructor( .loadDrawable(context), action, context.getString(R.string.controls_media_resume), - context.getDrawable(R.drawable.ic_media_play_container) + context.getDrawable(R.drawable.ic_media_play_container), ) } - private data class JobKey(val key: String, val sbn: StatusBarNotification) : - Pair<String, StatusBarNotification>(key, sbn) - companion object { private const val TAG = "MediaDataLoader" private val ART_URIS = arrayOf( MediaMetadata.METADATA_KEY_ALBUM_ART_URI, MediaMetadata.METADATA_KEY_ART_URI, - MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI + MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI, ) + + private const val DEBOUNCE_DELAY_MS = 200L } /** Returned data from loader. */ @@ -523,6 +530,6 @@ constructor( val appUid: Int, val isExplicit: Boolean, val resumeAction: Runnable? = null, - val resumeProgress: Double? = null + val resumeProgress: Double? = null, ) } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt index 8505a784d302..49a8758ed51e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt @@ -123,7 +123,7 @@ private val DEBUG = Log.isLoggable(TAG, Log.DEBUG) * Class that is responsible for keeping the view carousel up to date. This also handles changes in * state and applies them to the media carousel like the expansion. */ -@ExperimentalCoroutinesApi +@OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class MediaCarouselController @Inject @@ -252,13 +252,13 @@ constructor( fun calculateAlpha( squishinessFraction: Float, startPosition: Float, - endPosition: Float + endPosition: Float, ): Float { val transformFraction = MathUtils.constrain( (squishinessFraction - startPosition) / (endPosition - startPosition), 0F, - 1F + 1F, ) return TRANSFORM_BEZIER.getInterpolation(transformFraction) } @@ -354,7 +354,7 @@ constructor( this::closeGuts, falsingManager, this::logSmartspaceImpression, - logger + logger, ) carouselLocale = context.resources.configuration.locales.get(0) isRtl = context.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL @@ -387,7 +387,7 @@ constructor( object : MediaHostStatesManager.Callback { override fun onHostStateChanged( @MediaLocation location: Int, - mediaHostState: MediaHostState + mediaHostState: MediaHostState, ) { updateUserVisibility() if (location == desiredLocation) { @@ -412,7 +412,7 @@ constructor( bgExecutor.execute { globalSettings.registerContentObserverSync( Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE), - animationScaleObserver + animationScaleObserver, ) } } @@ -452,7 +452,7 @@ constructor( data: MediaData, immediately: Boolean, receivedSmartspaceCardLatency: Int, - isSsReactivated: Boolean + isSsReactivated: Boolean, ) { debugLogger.logMediaLoaded(key, data.active) if (addOrUpdatePlayer(key, oldKey, data, isSsReactivated)) { @@ -468,7 +468,7 @@ constructor( SSPACE_CARD_REPORTED__LOCKSCREEN, SSPACE_CARD_REPORTED__DREAM_OVERLAY, ), - rank = MediaPlayerData.getMediaPlayerIndex(key) + rank = MediaPlayerData.getMediaPlayerIndex(key), ) } if ( @@ -500,7 +500,7 @@ constructor( SSPACE_CARD_REPORTED__DREAM_OVERLAY, ), rank = index, - receivedLatencyMillis = receivedSmartspaceCardLatency + receivedLatencyMillis = receivedSmartspaceCardLatency, ) } } @@ -533,7 +533,7 @@ constructor( override fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean + shouldPrioritize: Boolean, ) { debugLogger.logRecommendationLoaded(key, data.isActive) // Log the case where the hidden media carousel with the existed inactive resume @@ -568,7 +568,7 @@ constructor( receivedLatencyMillis = (systemClock.currentTimeMillis() - data.headphoneConnectionTimeMillis) - .toInt() + .toInt(), ) } } @@ -589,7 +589,7 @@ constructor( receivedLatencyMillis = (systemClock.currentTimeMillis() - data.headphoneConnectionTimeMillis) - .toInt() + .toInt(), ) } if ( @@ -644,10 +644,7 @@ constructor( mediaCarouselScrollHandler.onSettingsButtonUpdated(settings) settingsButton.setOnClickListener { logger.logCarouselSettings() - activityStarter.startActivity( - settingsIntent, - /* dismissShade= */ true, - ) + activityStarter.startActivity(settingsIntent, /* dismissShade= */ true) } } @@ -739,7 +736,7 @@ constructor( val lp = LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT + ViewGroup.LayoutParams.WRAP_CONTENT, ) when (commonViewModel) { is MediaCommonViewModel.MediaControl -> { @@ -785,7 +782,7 @@ constructor( ) { mediaCarouselScrollHandler.scrollToPlayer( mediaCarouselScrollHandler.visibleMediaIndex, - destIndex = 0 + destIndex = 0, ) } mediaCarouselScrollHandler.onPlayersChanged() @@ -799,7 +796,7 @@ constructor( mediaCarouselScrollHandler.onPlayersChanged() onAddOrUpdateVisibleToUserCard( position, - commonViewModel is MediaCommonViewModel.MediaControl + commonViewModel is MediaCommonViewModel.MediaControl, ) } @@ -856,7 +853,7 @@ constructor( mediaCarouselScrollHandler.qsExpanded, mediaCarouselScrollHandler.visibleMediaIndex, currentEndLocation, - isMediaCardUpdate + isMediaCardUpdate, ) } } @@ -893,7 +890,7 @@ constructor( secureSettings.getBoolForUser( Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, true, - UserHandle.USER_CURRENT + UserHandle.USER_CURRENT, ) } } @@ -926,7 +923,7 @@ constructor( private fun reorderAllPlayers( previousVisiblePlayerKey: MediaPlayerData.MediaSortKey?, - key: String? = null + key: String? = null, ) { mediaContent.removeAllViews() for (mediaPlayer in MediaPlayerData.players()) { @@ -960,7 +957,7 @@ constructor( TAG, "Size of players list and number of views in carousel are out of sync. " + "Players size is ${MediaPlayerData.players().size}. " + - "View count is ${mediaContent.childCount}." + "View count is ${mediaContent.childCount}.", ) } } @@ -970,7 +967,7 @@ constructor( key: String, oldKey: String?, data: MediaData, - isSsReactivated: Boolean + isSsReactivated: Boolean, ): Boolean = traceSection("MediaCarouselController#addOrUpdatePlayer") { MediaPlayerData.moveIfExists(oldKey, key) @@ -992,7 +989,7 @@ constructor( val lp = LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT + ViewGroup.LayoutParams.WRAP_CONTENT, ) newPlayer.mediaViewHolder?.player?.setLayoutParams(lp) newPlayer.bindPlayer(data, key) @@ -1005,7 +1002,7 @@ constructor( newPlayer, systemClock, isSsReactivated, - debugLogger + debugLogger, ) updateViewControllerToState(newPlayer.mediaViewController, noAnimation = true) // Media data added from a recommendation card should starts playing. @@ -1025,7 +1022,7 @@ constructor( existingPlayer, systemClock, isSsReactivated, - debugLogger + debugLogger, ) val packageName = MediaPlayerData.smartspaceMediaData?.packageName ?: String() // In case of recommendations hits. @@ -1051,7 +1048,7 @@ constructor( private fun addSmartspaceMediaRecommendations( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean + shouldPrioritize: Boolean, ) = traceSection("MediaCarouselController#addSmartspaceMediaRecommendations") { if (DEBUG) Log.d(TAG, "Updating smartspace target in carousel") @@ -1090,7 +1087,7 @@ constructor( val lp = LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT + ViewGroup.LayoutParams.WRAP_CONTENT, ) newRecs.recommendationViewHolder?.recommendations?.setLayoutParams(lp) newRecs.bindRecommendation(data) @@ -1117,7 +1114,7 @@ constructor( TAG, "Size of players list and number of views in carousel are out of sync. " + "Players size is ${MediaPlayerData.players().size}. " + - "View count is ${mediaContent.childCount}." + "View count is ${mediaContent.childCount}.", ) } } @@ -1173,7 +1170,7 @@ constructor( addSmartspaceMediaRecommendations( it.targetId, it, - MediaPlayerData.shouldPrioritizeSs + MediaPlayerData.shouldPrioritizeSs, ) } } else { @@ -1185,7 +1182,7 @@ constructor( key = key, oldKey = null, data = data, - isSsReactivated = isSsReactivated + isSsReactivated = isSsReactivated, ) } if (recreateMedia) { @@ -1248,7 +1245,7 @@ constructor( @MediaLocation startLocation: Int, @MediaLocation endLocation: Int, progress: Float, - immediately: Boolean + immediately: Boolean, ) { if ( startLocation != currentStartLocation || @@ -1286,7 +1283,7 @@ constructor( squishFraction, (pageIndicator.translationY + pageIndicator.height) / mediaCarousel.measuredHeight, - 1F + 1F, ) var alpha = 1.0f if (!endIsVisible || !startIsVisible) { @@ -1354,7 +1351,7 @@ constructor( currentCarouselHeight = height mediaCarouselScrollHandler.setCarouselBounds( currentCarouselWidth, - currentCarouselHeight + currentCarouselHeight, ) updatePageIndicatorLocation() updatePageIndicatorAlpha() @@ -1386,13 +1383,13 @@ constructor( private fun updateViewControllerToState( viewController: MediaViewController, - noAnimation: Boolean + noAnimation: Boolean, ) { viewController.setCurrentState( startLocation = currentStartLocation, endLocation = currentEndLocation, transitionProgress = currentTransitionProgress, - applyImmediately = noAnimation + applyImmediately = noAnimation, ) } @@ -1411,7 +1408,7 @@ constructor( desiredHostState: MediaHostState?, animate: Boolean, duration: Long = 200, - startDelay: Long = 0 + startDelay: Long = 0, ) = traceSection("MediaCarouselController#onDesiredLocationChanged") { desiredHostState?.let { @@ -1435,7 +1432,7 @@ constructor( if (animate) { mediaPlayer.mediaViewController.animatePendingStateChange( duration = duration, - delay = startDelay + delay = startDelay, ) } if (shouldCloseGuts && mediaPlayer.mediaViewController.isGutsVisible) { @@ -1506,7 +1503,7 @@ constructor( mediaCarouselViewModel.onCardVisibleToUser( qsExpanded, mediaCarouselScrollHandler.visibleMediaIndex, - currentEndLocation + currentEndLocation, ) return } @@ -1524,7 +1521,7 @@ constructor( 800, // SMARTSPACE_CARD_SEEN it.mSmartspaceId, it.mUid, - intArrayOf(it.surfaceForSmartspaceLogging) + intArrayOf(it.surfaceForSmartspaceLogging), ) it.mIsImpressed = true } @@ -1559,7 +1556,7 @@ constructor( interactedSubcardCardinality: Int = 0, rank: Int = mediaCarouselScrollHandler.visibleMediaIndex, receivedLatencyMillis: Int = 0, - isSwipeToDismiss: Boolean = false + isSwipeToDismiss: Boolean = false, ) { if (MediaPlayerData.players().size <= rank) { return @@ -1600,7 +1597,7 @@ constructor( interactedSubcardCardinality, receivedLatencyMillis, null, // Media cards cannot have subcards. - null // Media cards don't have dimensions today. + null, // Media cards don't have dimensions today. ) if (DEBUG) { @@ -1613,7 +1610,7 @@ constructor( "uid: $uid " + "interactedSubcardRank: $interactedSubcardRank " + "interactedSubcardCardinality: $interactedSubcardCardinality " + - "received_latency_millis: $receivedLatencyMillis" + "received_latency_millis: $receivedLatencyMillis", ) } } @@ -1633,7 +1630,7 @@ constructor( it.mUid, intArrayOf(it.surfaceForSmartspaceLogging), rank = index, - isSwipeToDismiss = true + isSwipeToDismiss = true, ) // Reset card impressed state when swipe to dismissed it.mIsImpressed = false @@ -1692,7 +1689,7 @@ internal object MediaPlayerData { active = true, resumeAction = null, instanceId = InstanceId.fakeInstanceId(-1), - appUid = -1 + appUid = -1, ) // Whether should prioritize Smartspace card. @@ -1741,7 +1738,7 @@ internal object MediaPlayerData { player: MediaControlPanel, clock: SystemClock, isSsReactivated: Boolean, - debugLogger: MediaCarouselControllerLogger? = null + debugLogger: MediaCarouselControllerLogger? = null, ) { val removedPlayer = removeMediaPlayer(key) if (removedPlayer != null && removedPlayer != player) { @@ -1754,7 +1751,7 @@ internal object MediaPlayerData { data, key, clock.currentTimeMillis(), - isSsReactivated = isSsReactivated + isSsReactivated = isSsReactivated, ) mediaData.put(key, sortKey) mediaPlayers.put(sortKey, player) @@ -1768,7 +1765,7 @@ internal object MediaPlayerData { shouldPrioritize: Boolean, clock: SystemClock, debugLogger: MediaCarouselControllerLogger? = null, - update: Boolean = false + update: Boolean = false, ) { shouldPrioritizeSs = shouldPrioritize val removedPlayer = removeMediaPlayer(key) @@ -1782,7 +1779,7 @@ internal object MediaPlayerData { EMPTY.copy(active = data.isActive, isPlaying = false), key, clock.currentTimeMillis(), - isSsReactivated = true + isSsReactivated = true, ) mediaData.put(key, sortKey) mediaPlayers.put(sortKey, player) @@ -1793,7 +1790,7 @@ internal object MediaPlayerData { fun moveIfExists( oldKey: String?, newKey: String, - debugLogger: MediaCarouselControllerLogger? = null + debugLogger: MediaCarouselControllerLogger? = null, ) { if (oldKey == null || oldKey == newKey) { return diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt index a9d2a541a241..38cea5b23f78 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt @@ -64,6 +64,7 @@ import com.android.systemui.util.settings.SecureSettings import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged @@ -431,6 +432,12 @@ constructor( /** Is the communal UI showing */ private var isCommunalShowing: Boolean = false + /** Is the primary bouncer showing */ + private var isPrimaryBouncerShowing: Boolean = false + + /** Is either shade or QS fully expanded */ + private var isAnyShadeFullyExpanded: Boolean = false + /** Is the communal UI showing and not dreaming */ private var onCommunalNotDreaming: Boolean = false @@ -587,6 +594,20 @@ constructor( } } + coroutineScope.launch { + shadeInteractor.isAnyFullyExpanded.collect { + isAnyShadeFullyExpanded = it + updateUserVisibility() + } + } + + coroutineScope.launch { + keyguardInteractor.primaryBouncerShowing.collect { + isPrimaryBouncerShowing = it + updateUserVisibility() + } + } + if (mediaControlsLockscreenShadeBugFix()) { coroutineScope.launch { shadeInteractor.shadeExpansion.collect { expansion -> @@ -638,6 +659,7 @@ constructor( communalShowing && isDreaming && isShadeExpanding onCommunalNotDreaming = communalShowing && !isDreaming updateDesiredLocation(forceNoAnimation = true) + updateUserVisibility() } } } @@ -1290,7 +1312,8 @@ constructor( val shadeVisible = isLockScreenVisibleToUser() || isLockScreenShadeVisibleToUser() || - isHomeScreenShadeVisibleToUser() + isHomeScreenShadeVisibleToUser() || + isGlanceableHubVisibleToUser() val mediaVisible = qsExpanded || hasActiveMediaOrRecommendation mediaCarouselController.mediaCarouselScrollHandler.visibleToUser = shadeVisible && mediaVisible @@ -1318,6 +1341,10 @@ constructor( statusBarStateController.isExpanded } + private fun isGlanceableHubVisibleToUser(): Boolean { + return isCommunalShowing && !isPrimaryBouncerShowing && !isAnyShadeFullyExpanded + } + companion object { /** Attached in expanded quick settings */ const val LOCATION_QS = 0 diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java index ff9495daaa22..2961d05b2e51 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java @@ -57,7 +57,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { private static final float DEVICE_CONNECTED_ALPHA = 1f; protected List<MediaItem> mMediaItemList = new CopyOnWriteArrayList<>(); - public MediaOutputAdapter(MediaOutputController controller) { + public MediaOutputAdapter(MediaSwitchingController controller) { super(controller); setHasStableIds(true); } @@ -531,8 +531,10 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { @RequiresApi(34) private static class Api34Impl { @DoNotInline - static View.OnClickListener getClickListenerBasedOnSelectionBehavior(MediaDevice device, - MediaOutputController controller, View.OnClickListener defaultTransferListener) { + static View.OnClickListener getClickListenerBasedOnSelectionBehavior( + MediaDevice device, + MediaSwitchingController controller, + View.OnClickListener defaultTransferListener) { switch (device.getSelectionBehavior()) { case SELECTION_BEHAVIOR_NONE: return null; diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java index 5958b0a24a5e..63a7e013022a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java @@ -63,7 +63,7 @@ public abstract class MediaOutputBaseAdapter extends static final int CUSTOMIZED_ITEM_GROUP = 2; static final int CUSTOMIZED_ITEM_DYNAMIC_GROUP = 3; - protected final MediaOutputController mController; + protected final MediaSwitchingController mController; private static final int UNMUTE_DEFAULT_VOLUME = 2; @@ -73,7 +73,7 @@ public abstract class MediaOutputBaseAdapter extends int mCurrentActivePosition; private boolean mIsInitVolumeFirstTime; - public MediaOutputBaseAdapter(MediaOutputController controller) { + public MediaOutputBaseAdapter(MediaSwitchingController controller) { mController = controller; mIsDragging = false; mCurrentActivePosition = -1; @@ -127,7 +127,7 @@ public abstract class MediaOutputBaseAdapter extends return mCurrentActivePosition; } - public MediaOutputController getController() { + public MediaSwitchingController getController() { return mController; } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java index 6cc4dcbaa1ea..6bc995f3437c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java @@ -65,11 +65,9 @@ import com.android.systemui.statusbar.phone.SystemUIDialog; import java.util.concurrent.Executor; import java.util.concurrent.Executors; -/** - * Base dialog for media output UI - */ -public abstract class MediaOutputBaseDialog extends SystemUIDialog implements - MediaOutputController.Callback, Window.Callback { +/** Base dialog for media output UI */ +public abstract class MediaOutputBaseDialog extends SystemUIDialog + implements MediaSwitchingController.Callback, Window.Callback { private static final String TAG = "MediaOutputDialog"; private static final String EMPTY_TITLE = " "; @@ -82,7 +80,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements private final RecyclerView.LayoutManager mLayoutManager; final Context mContext; - final MediaOutputController mMediaOutputController; + final MediaSwitchingController mMediaSwitchingController; final BroadcastSender mBroadcastSender; /** @@ -212,22 +210,22 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements @Override public void onLayoutCompleted(RecyclerView.State state) { super.onLayoutCompleted(state); - mMediaOutputController.setRefreshing(false); - mMediaOutputController.refreshDataSetIfNeeded(); + mMediaSwitchingController.setRefreshing(false); + mMediaSwitchingController.refreshDataSetIfNeeded(); } } public MediaOutputBaseDialog( Context context, BroadcastSender broadcastSender, - MediaOutputController mediaOutputController, + MediaSwitchingController mediaSwitchingController, boolean includePlaybackAndAppMetadata) { super(context, R.style.Theme_SystemUI_Dialog_Media); // Save the context that is wrapped with our theme. mContext = getContext(); mBroadcastSender = broadcastSender; - mMediaOutputController = mediaOutputController; + mMediaSwitchingController = mediaSwitchingController; mLayoutManager = new LayoutManagerWrapper(mContext); mListMaxHeight = context.getResources().getDimensionPixelSize( R.dimen.media_output_dialog_list_max_height); @@ -279,9 +277,9 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements // Init bottom buttons mDoneButton.setOnClickListener(v -> dismiss()); mStopButton.setOnClickListener(v -> onStopButtonClick()); - mAppButton.setOnClickListener(mMediaOutputController::tryToLaunchMediaApplication); + mAppButton.setOnClickListener(mMediaSwitchingController::tryToLaunchMediaApplication); mMediaMetadataSectionLayout.setOnClickListener( - mMediaOutputController::tryToLaunchMediaApplication); + mMediaSwitchingController::tryToLaunchMediaApplication); mDismissing = false; } @@ -298,10 +296,10 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements @Override public void start() { - mMediaOutputController.start(this); + mMediaSwitchingController.start(this); if (isBroadcastSupported() && !mIsLeBroadcastCallbackRegistered) { - mMediaOutputController.registerLeBroadcastServiceCallback(mExecutor, - mBroadcastCallback); + mMediaSwitchingController.registerLeBroadcastServiceCallback( + mExecutor, mBroadcastCallback); mIsLeBroadcastCallbackRegistered = true; } } @@ -311,11 +309,11 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements // unregister broadcast callback should only depend on profile and registered flag // rather than remote device or broadcast state // otherwise it might have risks of leaking registered callback handle - if (mMediaOutputController.isBroadcastSupported() && mIsLeBroadcastCallbackRegistered) { - mMediaOutputController.unregisterLeBroadcastServiceCallback(mBroadcastCallback); + if (mMediaSwitchingController.isBroadcastSupported() && mIsLeBroadcastCallbackRegistered) { + mMediaSwitchingController.unregisterLeBroadcastServiceCallback(mBroadcastCallback); mIsLeBroadcastCallbackRegistered = false; } - mMediaOutputController.stop(); + mMediaSwitchingController.stop(); } @VisibleForTesting @@ -326,18 +324,17 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements void refresh(boolean deviceSetChanged) { // TODO(287191450): remove binder calls in this method from the UI thread. // If the dialog is going away or is already refreshing, do nothing. - if (mDismissing || mMediaOutputController.isRefreshing()) { + if (mDismissing || mMediaSwitchingController.isRefreshing()) { return; } - mMediaOutputController.setRefreshing(true); + mMediaSwitchingController.setRefreshing(true); // Update header icon final int iconRes = getHeaderIconRes(); final IconCompat headerIcon = getHeaderIcon(); final IconCompat appSourceIcon = getAppSourceIcon(); boolean colorSetUpdated = false; mCastAppLayout.setVisibility( - mMediaOutputController.shouldShowLaunchSection() - ? View.VISIBLE : View.GONE); + mMediaSwitchingController.shouldShowLaunchSection() ? View.VISIBLE : View.GONE); if (iconRes != 0) { mHeaderIcon.setVisibility(View.VISIBLE); mHeaderIcon.setImageResource(iconRes); @@ -371,10 +368,10 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements mAppResourceIcon.setVisibility(View.GONE); } else if (appSourceIcon != null) { Icon appIcon = appSourceIcon.toIcon(mContext); - mAppResourceIcon.setColorFilter(mMediaOutputController.getColorItemContent()); + mAppResourceIcon.setColorFilter(mMediaSwitchingController.getColorItemContent()); mAppResourceIcon.setImageIcon(appIcon); } else { - Drawable appIconDrawable = mMediaOutputController.getAppSourceIconFromPackage(); + Drawable appIconDrawable = mMediaSwitchingController.getAppSourceIconFromPackage(); if (appIconDrawable != null) { mAppResourceIcon.setImageDrawable(appIconDrawable); } else { @@ -387,7 +384,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements R.dimen.media_output_dialog_header_icon_padding); mHeaderIcon.setLayoutParams(new LinearLayout.LayoutParams(size + padding, size)); } - mAppButton.setText(mMediaOutputController.getAppSourceName()); + mAppButton.setText(mMediaSwitchingController.getAppSourceName()); if (!mIncludePlaybackAndAppMetadata) { mHeaderTitle.setVisibility(View.GONE); @@ -424,23 +421,26 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements mAdapter.updateItems(); } } else { - mMediaOutputController.setRefreshing(false); - mMediaOutputController.refreshDataSetIfNeeded(); + mMediaSwitchingController.setRefreshing(false); + mMediaSwitchingController.refreshDataSetIfNeeded(); } } private void updateButtonBackgroundColorFilter() { - ColorFilter buttonColorFilter = new PorterDuffColorFilter( - mMediaOutputController.getColorButtonBackground(), - PorterDuff.Mode.SRC_IN); + ColorFilter buttonColorFilter = + new PorterDuffColorFilter( + mMediaSwitchingController.getColorButtonBackground(), + PorterDuff.Mode.SRC_IN); mDoneButton.getBackground().setColorFilter(buttonColorFilter); mStopButton.getBackground().setColorFilter(buttonColorFilter); - mDoneButton.setTextColor(mMediaOutputController.getColorPositiveButtonText()); + mDoneButton.setTextColor(mMediaSwitchingController.getColorPositiveButtonText()); } private void updateDialogBackgroundColor() { - getDialogView().getBackground().setTint(mMediaOutputController.getColorDialogBackground()); - mDeviceListLayout.setBackgroundColor(mMediaOutputController.getColorDialogBackground()); + getDialogView() + .getBackground() + .setTint(mMediaSwitchingController.getColorDialogBackground()); + mDeviceListLayout.setBackgroundColor(mMediaSwitchingController.getColorDialogBackground()); } private Drawable resizeDrawable(Drawable drawable, int size) { @@ -499,7 +499,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements protected void startLeBroadcast() { mStopButton.setText(R.string.media_output_broadcast_starting); mStopButton.setEnabled(false); - if (!mMediaOutputController.startBluetoothLeBroadcast()) { + if (!mMediaSwitchingController.startBluetoothLeBroadcast()) { // If the system can't execute "broadcast start", then UI shows the error. handleLeBroadcastStartFailed(); } @@ -512,9 +512,10 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements && sharedPref.getBoolean(PREF_IS_LE_BROADCAST_FIRST_LAUNCH, true)) { Log.d(TAG, "PREF_IS_LE_BROADCAST_FIRST_LAUNCH: true"); - mMediaOutputController.launchLeBroadcastNotifyDialog(mDialogView, + mMediaSwitchingController.launchLeBroadcastNotifyDialog( + mDialogView, mBroadcastSender, - MediaOutputController.BroadcastNotifyDialog.ACTION_FIRST_LAUNCH, + MediaSwitchingController.BroadcastNotifyDialog.ACTION_FIRST_LAUNCH, (d, w) -> { startLeBroadcast(); }); @@ -527,14 +528,13 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements } protected void startLeBroadcastDialog() { - mMediaOutputController.launchMediaOutputBroadcastDialog(mDialogView, - mBroadcastSender); + mMediaSwitchingController.launchMediaOutputBroadcastDialog(mDialogView, mBroadcastSender); refresh(); } protected void stopLeBroadcast() { mStopButton.setEnabled(false); - if (!mMediaOutputController.stopBluetoothLeBroadcast()) { + if (!mMediaSwitchingController.stopBluetoothLeBroadcast()) { // If the system can't execute "broadcast stop", then UI does refresh. mMainThreadHandler.post(() -> refresh()); } @@ -559,7 +559,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements } public void onStopButtonClick() { - mMediaOutputController.releaseSession(); + mMediaSwitchingController.releaseSession(); dismiss(); } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java index 1e317554859c..9b5b872a00db 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java @@ -235,14 +235,17 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { } }; - MediaOutputBroadcastDialog(Context context, boolean aboveStatusbar, - BroadcastSender broadcastSender, MediaOutputController mediaOutputController) { + MediaOutputBroadcastDialog( + Context context, + boolean aboveStatusbar, + BroadcastSender broadcastSender, + MediaSwitchingController mediaSwitchingController) { super( context, broadcastSender, - mediaOutputController, /* includePlaybackAndAppMetadata */ + mediaSwitchingController, /* includePlaybackAndAppMetadata */ true); - mAdapter = new MediaOutputAdapter(mMediaOutputController); + mAdapter = new MediaOutputAdapter(mMediaSwitchingController); // TODO(b/226710953): Move the part to MediaOutputBaseDialog for every class // that extends MediaOutputBaseDialog if (!aboveStatusbar) { @@ -262,8 +265,8 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { super.start(); if (!mIsLeBroadcastAssistantCallbackRegistered) { mIsLeBroadcastAssistantCallbackRegistered = true; - mMediaOutputController.registerLeBroadcastAssistantServiceCallback(mExecutor, - mBroadcastAssistantCallback); + mMediaSwitchingController.registerLeBroadcastAssistantServiceCallback( + mExecutor, mBroadcastAssistantCallback); } /* Add local source broadcast to connected capable devices that may be possible receivers * of stream. @@ -276,7 +279,7 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { super.stop(); if (mIsLeBroadcastAssistantCallbackRegistered) { mIsLeBroadcastAssistantCallbackRegistered = false; - mMediaOutputController.unregisterLeBroadcastAssistantServiceCallback( + mMediaSwitchingController.unregisterLeBroadcastAssistantServiceCallback( mBroadcastAssistantCallback); } } @@ -288,7 +291,7 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { @Override IconCompat getHeaderIcon() { - return mMediaOutputController.getHeaderIcon(); + return mMediaSwitchingController.getHeaderIcon(); } @Override @@ -299,17 +302,17 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { @Override CharSequence getHeaderText() { - return mMediaOutputController.getHeaderTitle(); + return mMediaSwitchingController.getHeaderTitle(); } @Override CharSequence getHeaderSubtitle() { - return mMediaOutputController.getHeaderSubTitle(); + return mMediaSwitchingController.getHeaderSubTitle(); } @Override IconCompat getAppSourceIcon() { - return mMediaOutputController.getNotificationSmallIcon(); + return mMediaSwitchingController.getNotificationSmallIcon(); } @Override @@ -319,16 +322,16 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { @Override public void onStopButtonClick() { - mMediaOutputController.stopBluetoothLeBroadcast(); + mMediaSwitchingController.stopBluetoothLeBroadcast(); dismiss(); } private String getBroadcastMetadataInfo(int metadata) { switch (metadata) { case METADATA_BROADCAST_NAME: - return mMediaOutputController.getBroadcastName(); + return mMediaSwitchingController.getBroadcastName(); case METADATA_BROADCAST_CODE: - return mMediaOutputController.getBroadcastCode(); + return mMediaSwitchingController.getBroadcastCode(); default: return ""; } @@ -342,13 +345,15 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { mBroadcastQrCodeView = getDialogView().requireViewById(R.id.qrcode_view); mBroadcastNotify = getDialogView().requireViewById(R.id.broadcast_info); - mBroadcastNotify.setOnClickListener(v -> { - mMediaOutputController.launchLeBroadcastNotifyDialog( - /* view= */ null, - /* broadcastSender= */ null, - MediaOutputController.BroadcastNotifyDialog.ACTION_BROADCAST_INFO_ICON, - /* onClickListener= */ null); - }); + mBroadcastNotify.setOnClickListener( + v -> { + mMediaSwitchingController.launchLeBroadcastNotifyDialog( + /* mediaOutputDialog= */ null, + /* broadcastSender= */ null, + MediaSwitchingController.BroadcastNotifyDialog + .ACTION_BROADCAST_INFO_ICON, + /* listener= */ null); + }); mBroadcastName = getDialogView().requireViewById(R.id.broadcast_name_summary); mBroadcastNameEdit = getDialogView().requireViewById(R.id.broadcast_name_edit); mBroadcastNameEdit.setOnClickListener(v -> { @@ -409,16 +414,16 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { return; } - for (BluetoothDevice sink : mMediaOutputController.getConnectedBroadcastSinkDevices()) { + for (BluetoothDevice sink : mMediaSwitchingController.getConnectedBroadcastSinkDevices()) { Log.d(TAG, "The broadcastMetadata broadcastId: " + broadcastMetadata.getBroadcastId() + ", the device: " + sink.getAnonymizedAddress()); - if (mMediaOutputController.isThereAnyBroadcastSourceIntoSinkDevice(sink)) { + if (mMediaSwitchingController.isThereAnyBroadcastSourceIntoSinkDevice(sink)) { Log.d(TAG, "The sink device has the broadcast source now."); return; } - if (!mMediaOutputController.addSourceIntoSinkDeviceWithBluetoothLeAssistant(sink, - broadcastMetadata, /*isGroupOp=*/ false)) { + if (!mMediaSwitchingController.addSourceIntoSinkDeviceWithBluetoothLeAssistant( + sink, broadcastMetadata, /* isGroupOp= */ false)) { Log.e(TAG, "Error: Source add failed"); } } @@ -457,11 +462,11 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { } private String getLocalBroadcastMetadataQrCodeString() { - return mMediaOutputController.getLocalBroadcastMetadataQrCodeString(); + return mMediaSwitchingController.getLocalBroadcastMetadataQrCodeString(); } private BluetoothLeBroadcastMetadata getBroadcastMetadata() { - return mMediaOutputController.getBroadcastMetadata(); + return mMediaSwitchingController.getBroadcastMetadata(); } @VisibleForTesting @@ -476,8 +481,8 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { * stopped then used the new Broadcast code to start the Broadcast. */ mIsStopbyUpdateBroadcastCode = true; - mMediaOutputController.setBroadcastCode(updatedString); - if (!mMediaOutputController.stopBluetoothLeBroadcast()) { + mMediaSwitchingController.setBroadcastCode(updatedString); + if (!mMediaSwitchingController.stopBluetoothLeBroadcast()) { handleLeBroadcastStopFailed(); return; } @@ -485,8 +490,8 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { /* If the user wants to update the Broadcast Name, we don't need to stop the Broadcast * session. Only use the new Broadcast name to update the broadcast session. */ - mMediaOutputController.setBroadcastName(updatedString); - if (!mMediaOutputController.updateBluetoothLeBroadcast()) { + mMediaSwitchingController.setBroadcastName(updatedString); + if (!mMediaSwitchingController.updateBluetoothLeBroadcast()) { handleLeBroadcastUpdateFailed(); } } @@ -496,12 +501,13 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { public boolean isBroadcastSupported() { if (!legacyLeAudioSharing()) return false; boolean isBluetoothLeDevice = false; - if (mMediaOutputController.getCurrentConnectedMediaDevice() != null) { - isBluetoothLeDevice = mMediaOutputController.isBluetoothLeDevice( - mMediaOutputController.getCurrentConnectedMediaDevice()); + if (mMediaSwitchingController.getCurrentConnectedMediaDevice() != null) { + isBluetoothLeDevice = + mMediaSwitchingController.isBluetoothLeDevice( + mMediaSwitchingController.getCurrentConnectedMediaDevice()); } - return mMediaOutputController.isBroadcastSupported() && isBluetoothLeDevice; + return mMediaSwitchingController.isBroadcastSupported() && isBluetoothLeDevice; } @Override @@ -515,7 +521,7 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { @Override public void handleLeBroadcastStartFailed() { - mMediaOutputController.setBroadcastCode(mCurrentBroadcastCode); + mMediaSwitchingController.setBroadcastCode(mCurrentBroadcastCode); mRetryCount++; handleUpdateFailedUi(); @@ -538,8 +544,8 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { @Override public void handleLeBroadcastUpdateFailed() { - //Change the value in shared preferences back to it original value - mMediaOutputController.setBroadcastName(mCurrentBroadcastName); + // Change the value in shared preferences back to it original value + mMediaSwitchingController.setBroadcastName(mCurrentBroadcastName); mRetryCount++; handleUpdateFailedUi(); @@ -550,7 +556,7 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { if (mIsStopbyUpdateBroadcastCode) { mIsStopbyUpdateBroadcastCode = false; mRetryCount = 0; - if (!mMediaOutputController.startBluetoothLeBroadcast()) { + if (!mMediaSwitchingController.startBluetoothLeBroadcast()) { handleLeBroadcastStartFailed(); return; } @@ -561,8 +567,8 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog { @Override public void handleLeBroadcastStopFailed() { - //Change the value in shared preferences back to it original value - mMediaOutputController.setBroadcastCode(mCurrentBroadcastCode); + // Change the value in shared preferences back to it original value + mMediaSwitchingController.setBroadcastCode(mCurrentBroadcastCode); mRetryCount++; handleUpdateFailedUi(); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogManager.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogManager.kt index 6ef9ea36882b..2e7e66f5b384 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogManager.kt @@ -29,7 +29,7 @@ constructor( private val context: Context, private val broadcastSender: BroadcastSender, private val dialogTransitionAnimator: DialogTransitionAnimator, - private val mediaOutputControllerFactory: MediaOutputController.Factory + private val mediaSwitchingControllerFactory: MediaSwitchingController.Factory ) { var mediaOutputBroadcastDialog: MediaOutputBroadcastDialog? = null @@ -41,7 +41,7 @@ constructor( // TODO: b/321969740 - Populate the userHandle parameter. The user handle is necessary to // disambiguate the same package running on different users. val controller = - mediaOutputControllerFactory.create( + mediaSwitchingControllerFactory.create( packageName, /* userHandle= */ null, /* token */ null, diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java index eb6a32023eb7..c9af7b322811 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java @@ -46,14 +46,14 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { Context context, boolean aboveStatusbar, BroadcastSender broadcastSender, - MediaOutputController mediaOutputController, + MediaSwitchingController mediaSwitchingController, DialogTransitionAnimator dialogTransitionAnimator, UiEventLogger uiEventLogger, boolean includePlaybackAndAppMetadata) { - super(context, broadcastSender, mediaOutputController, includePlaybackAndAppMetadata); + super(context, broadcastSender, mediaSwitchingController, includePlaybackAndAppMetadata); mDialogTransitionAnimator = dialogTransitionAnimator; mUiEventLogger = uiEventLogger; - mAdapter = new MediaOutputAdapter(mMediaOutputController); + mAdapter = new MediaOutputAdapter(mMediaSwitchingController); if (!aboveStatusbar) { getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); } @@ -72,7 +72,7 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { @Override IconCompat getHeaderIcon() { - return mMediaOutputController.getHeaderIcon(); + return mMediaSwitchingController.getHeaderIcon(); } @Override @@ -83,27 +83,29 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { @Override CharSequence getHeaderText() { - return mMediaOutputController.getHeaderTitle(); + return mMediaSwitchingController.getHeaderTitle(); } @Override CharSequence getHeaderSubtitle() { - return mMediaOutputController.getHeaderSubTitle(); + return mMediaSwitchingController.getHeaderSubTitle(); } @Override IconCompat getAppSourceIcon() { - return mMediaOutputController.getNotificationSmallIcon(); + return mMediaSwitchingController.getNotificationSmallIcon(); } @Override int getStopButtonVisibility() { boolean isActiveRemoteDevice = false; - if (mMediaOutputController.getCurrentConnectedMediaDevice() != null) { - isActiveRemoteDevice = mMediaOutputController.isActiveRemoteDevice( - mMediaOutputController.getCurrentConnectedMediaDevice()); + if (mMediaSwitchingController.getCurrentConnectedMediaDevice() != null) { + isActiveRemoteDevice = + mMediaSwitchingController.isActiveRemoteDevice( + mMediaSwitchingController.getCurrentConnectedMediaDevice()); } - boolean showBroadcastButton = isBroadcastSupported() && mMediaOutputController.isPlaying(); + boolean showBroadcastButton = + isBroadcastSupported() && mMediaSwitchingController.isPlaying(); return (isActiveRemoteDevice || showBroadcastButton) ? View.VISIBLE : View.GONE; } @@ -115,13 +117,14 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { boolean isBroadcastEnabled = false; if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST)) { - if (mMediaOutputController.getCurrentConnectedMediaDevice() != null) { - isBluetoothLeDevice = mMediaOutputController.isBluetoothLeDevice( - mMediaOutputController.getCurrentConnectedMediaDevice()); + if (mMediaSwitchingController.getCurrentConnectedMediaDevice() != null) { + isBluetoothLeDevice = + mMediaSwitchingController.isBluetoothLeDevice( + mMediaSwitchingController.getCurrentConnectedMediaDevice()); // if broadcast is active, broadcast should be considered as supported // there could be a valid case that broadcast is ongoing // without active LEA device connected - isBroadcastEnabled = mMediaOutputController.isBluetoothLeBroadcastEnabled(); + isBroadcastEnabled = mMediaSwitchingController.isBluetoothLeBroadcastEnabled(); } } else { // To decouple LE Audio Broadcast and Unicast, it always displays the button when there @@ -129,15 +132,16 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { isBluetoothLeDevice = true; } - return mMediaOutputController.isBroadcastSupported() + return mMediaSwitchingController.isBroadcastSupported() && (isBluetoothLeDevice || isBroadcastEnabled); } @Override public CharSequence getStopButtonText() { int resId = R.string.media_output_dialog_button_stop_casting; - if (isBroadcastSupported() && mMediaOutputController.isPlaying() - && !mMediaOutputController.isBluetoothLeBroadcastEnabled()) { + if (isBroadcastSupported() + && mMediaSwitchingController.isPlaying() + && !mMediaSwitchingController.isBluetoothLeBroadcastEnabled()) { resId = R.string.media_output_broadcast; } return mContext.getText(resId); @@ -145,8 +149,8 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { @Override public void onStopButtonClick() { - if (isBroadcastSupported() && mMediaOutputController.isPlaying()) { - if (!mMediaOutputController.isBluetoothLeBroadcastEnabled()) { + if (isBroadcastSupported() && mMediaSwitchingController.isPlaying()) { + if (!mMediaSwitchingController.isBluetoothLeBroadcastEnabled()) { if (startLeBroadcastDialogForFirstTime()) { return; } @@ -155,7 +159,7 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { stopLeBroadcast(); } } else { - mMediaOutputController.releaseSession(); + mMediaSwitchingController.releaseSession(); mDialogTransitionAnimator.disableAllCurrentDialogsExitAnimations(); dismiss(); } @@ -163,8 +167,9 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { @Override public int getBroadcastIconVisibility() { - return (isBroadcastSupported() && mMediaOutputController.isBluetoothLeBroadcastEnabled()) - ? View.VISIBLE : View.GONE; + return (isBroadcastSupported() && mMediaSwitchingController.isBluetoothLeBroadcastEnabled()) + ? View.VISIBLE + : View.GONE; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt index 47e069102035..4e9451a838ad 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt @@ -35,7 +35,7 @@ constructor( private val broadcastSender: BroadcastSender, private val uiEventLogger: UiEventLogger, private val dialogTransitionAnimator: DialogTransitionAnimator, - private val mediaOutputControllerFactory: MediaOutputController.Factory, + private val mediaSwitchingControllerFactory: MediaSwitchingController.Factory, ) { companion object { const val INTERACTION_JANK_TAG = "media_output" @@ -118,7 +118,7 @@ constructor( // Dismiss the previous dialog, if any. mediaOutputDialog?.dismiss() - val controller = mediaOutputControllerFactory.create(packageName, userHandle, token) + val controller = mediaSwitchingControllerFactory.create(packageName, userHandle, token) val mediaOutputDialog = MediaOutputDialog( diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSwitchingController.java index 875e505db1c6..2cbc75755cfd 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSwitchingController.java @@ -77,6 +77,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastMetadata; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.InfoMediaManager; +import com.android.settingslib.media.InputRouteManager; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; import com.android.settingslib.media.flags.Flags; @@ -116,12 +117,13 @@ import java.util.function.Function; import java.util.stream.Collectors; /** - * Controller for media output dialog + * Controller for a dialog that allows users to switch media output and input devices, control + * volume, connect to new devices, etc. */ -public class MediaOutputController implements LocalMediaManager.DeviceCallback, - INearbyMediaDevicesUpdateCallback { +public class MediaSwitchingController + implements LocalMediaManager.DeviceCallback, INearbyMediaDevicesUpdateCallback { - private static final String TAG = "MediaOutputController"; + private static final String TAG = "MediaSwitchingController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final String PAGE_CONNECTED_DEVICES_KEY = "top_level_connected_devices"; @@ -137,10 +139,12 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, private final DialogTransitionAnimator mDialogTransitionAnimator; private final CommonNotifCollection mNotifCollection; protected final Object mMediaDevicesLock = new Object(); + protected final Object mInputMediaDevicesLock = new Object(); @VisibleForTesting final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>(); final List<MediaDevice> mCachedMediaDevices = new CopyOnWriteArrayList<>(); - private final List<MediaItem> mMediaItemList = new CopyOnWriteArrayList<>(); + private final List<MediaItem> mOutputMediaItemList = new CopyOnWriteArrayList<>(); + private final List<MediaItem> mInputMediaItemList = new CopyOnWriteArrayList<>(); private final AudioManager mAudioManager; private final PowerExemptionManager mPowerExemptionManager; private final KeyguardManager mKeyGuardManager; @@ -153,6 +157,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, @VisibleForTesting boolean mNeedRefresh = false; private MediaController mMediaController; + private InputRouteManager mInputRouteManager; @VisibleForTesting Callback mCallback; @VisibleForTesting @@ -181,8 +186,20 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, ACTION_BROADCAST_INFO_ICON } + @VisibleForTesting + final InputRouteManager.InputDeviceCallback mInputDeviceCallback = + new InputRouteManager.InputDeviceCallback() { + @Override + public void onInputDeviceListUpdated(@NonNull List<MediaDevice> devices) { + synchronized (mInputMediaDevicesLock) { + buildInputMediaItems(devices); + mCallback.onDeviceListChanged(); + } + } + }; + @AssistedInject - public MediaOutputController( + public MediaSwitchingController( Context context, @Assisted String packageName, @Assisted @Nullable UserHandle userHandle, @@ -241,19 +258,23 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, R.dimen.media_output_dialog_default_margin_end); mItemMarginEndSelectable = (int) mContext.getResources().getDimension( R.dimen.media_output_dialog_selectable_margin_end); + + if (enableInputRouting()) { + mInputRouteManager = new InputRouteManager(mContext, audioManager); + } } @AssistedFactory public interface Factory { - /** Construct a MediaOutputController */ - MediaOutputController create( + /** Construct a MediaSwitchingController */ + MediaSwitchingController create( String packageName, UserHandle userHandle, MediaSession.Token token); } protected void start(@NonNull Callback cb) { synchronized (mMediaDevicesLock) { mCachedMediaDevices.clear(); - mMediaItemList.clear(); + mOutputMediaItemList.clear(); } mNearbyDeviceInfoMap.clear(); if (mNearbyMediaDevicesManager != null) { @@ -277,6 +298,10 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mCallback = cb; mLocalMediaManager.registerCallback(this); mLocalMediaManager.startScan(); + + if (enableInputRouting()) { + mInputRouteManager.registerCallback(mInputDeviceCallback); + } } boolean shouldShowLaunchSection() { @@ -300,12 +325,19 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mLocalMediaManager.stopScan(); synchronized (mMediaDevicesLock) { mCachedMediaDevices.clear(); - mMediaItemList.clear(); + mOutputMediaItemList.clear(); } if (mNearbyMediaDevicesManager != null) { mNearbyMediaDevicesManager.unregisterNearbyDevicesCallback(this); } mNearbyDeviceInfoMap.clear(); + + if (enableInputRouting()) { + mInputRouteManager.unregisterCallback(mInputDeviceCallback); + synchronized (mInputMediaDevicesLock) { + mInputMediaItemList.clear(); + } + } } private MediaController getMediaController() { @@ -335,7 +367,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, @Override public void onDeviceListUpdate(List<MediaDevice> devices) { - boolean isListEmpty = mMediaItemList.isEmpty(); + boolean isListEmpty = mOutputMediaItemList.isEmpty(); if (isListEmpty || !mIsRefreshing) { buildMediaItems(devices); mCallback.onDeviceListChanged(); @@ -352,7 +384,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, public void onSelectedDeviceStateChanged(MediaDevice device, @LocalMediaManager.MediaDeviceState int state) { mCallback.onRouteChanged(); - mMetricLogger.logOutputItemSuccess(device.toString(), new ArrayList<>(mMediaItemList)); + mMetricLogger.logOutputItemSuccess( + device.toString(), new ArrayList<>(mOutputMediaItemList)); } @Override @@ -363,7 +396,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, @Override public void onRequestFailed(int reason) { mCallback.onRouteChanged(); - mMetricLogger.logOutputItemFailure(new ArrayList<>(mMediaItemList), reason); + mMetricLogger.logOutputItemFailure(new ArrayList<>(mOutputMediaItemList), reason); } /** @@ -382,7 +415,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, } try { synchronized (mMediaDevicesLock) { - mMediaItemList.removeIf((MediaItem::isMutingExpectedDevice)); + mOutputMediaItemList.removeIf((MediaItem::isMutingExpectedDevice)); } mAudioManager.cancelMuteAwaitConnection(mAudioManager.getMutingExpectedDevice()); } catch (Exception e) { @@ -638,9 +671,9 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, private void buildMediaItems(List<MediaDevice> devices) { synchronized (mMediaDevicesLock) { - List<MediaItem> updatedMediaItems = buildMediaItems(mMediaItemList, devices); - mMediaItemList.clear(); - mMediaItemList.addAll(updatedMediaItems); + List<MediaItem> updatedMediaItems = buildMediaItems(mOutputMediaItemList, devices); + mOutputMediaItemList.clear(); + mOutputMediaItemList.addAll(updatedMediaItems); } } @@ -714,6 +747,19 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, } } + private boolean enableInputRouting() { + return com.android.media.flags.Flags.enableAudioInputDeviceRoutingAndVolumeControl(); + } + + private void buildInputMediaItems(List<MediaDevice> devices) { + synchronized (mInputMediaDevicesLock) { + List<MediaItem> updatedInputMediaItems = + devices.stream().map(MediaItem::createDeviceMediaItem).toList(); + mInputMediaItemList.clear(); + mInputMediaItemList.addAll(updatedInputMediaItems); + } + } + /** * Initial categorization of current devices, will not be called for updates to the devices * list. @@ -778,7 +824,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mediaDevice.setRangeZone(mNearbyDeviceInfoMap.get(mediaDevice.getId())); } } - } boolean isCurrentConnectedDeviceRemote() { @@ -837,8 +882,31 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, }); } + private void addInputDevices(List<MediaItem> mediaItems) { + mediaItems.add( + MediaItem.createGroupDividerMediaItem( + mContext.getString(R.string.media_input_group_title))); + mediaItems.addAll(mInputMediaItemList); + } + + private void addOutputDevices(List<MediaItem> mediaItems) { + mediaItems.add( + MediaItem.createGroupDividerMediaItem( + mContext.getString(R.string.media_output_group_title))); + mediaItems.addAll(mOutputMediaItemList); + } + public List<MediaItem> getMediaItemList() { - return mMediaItemList; + // If input routing is not enabled, only return output media items. + if (!enableInputRouting()) { + return mOutputMediaItemList; + } + + // If input routing is enabled, return both output and input media items. + List<MediaItem> mediaItems = new ArrayList<>(); + addOutputDevices(mediaItems); + addInputDevices(mediaItems); + return mediaItems; } public MediaDevice getCurrentConnectedMediaDevice() { @@ -921,7 +989,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, public boolean isAnyDeviceTransferring() { synchronized (mMediaDevicesLock) { - for (MediaItem mediaItem : mMediaItemList) { + for (MediaItem mediaItem : mOutputMediaItemList) { if (mediaItem.getMediaDevice().isPresent() && mediaItem.getMediaDevice().get().getState() == LocalMediaManager.MediaDeviceState.STATE_CONNECTING) { @@ -986,8 +1054,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, } void launchMediaOutputBroadcastDialog(View mediaOutputDialog, BroadcastSender broadcastSender) { - MediaOutputController controller = - new MediaOutputController( + MediaSwitchingController controller = + new MediaSwitchingController( mContext, mPackageName, mUserHandle, diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java index d59658947771..4251b81226b3 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java @@ -53,7 +53,6 @@ import android.text.TextPaint; import android.text.TextUtils; import android.util.Log; import android.view.Window; -import android.view.WindowManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; @@ -309,9 +308,6 @@ public class MediaProjectionPermissionActivity extends Activity { private void setUpDialog(AlertDialog dialog) { SystemUIDialog.registerDismissListener(dialog); SystemUIDialog.applyFlags(dialog, /* showWhenLocked= */ false); - - final Window w = dialog.getWindow(); - w.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); SystemUIDialog.setDialogSize(dialog); dialog.setOnCancelListener(this::onDialogDismissedOrCancelled); @@ -319,6 +315,7 @@ public class MediaProjectionPermissionActivity extends Activity { dialog.create(); dialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true); + final Window w = dialog.getWindow(); w.addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); } diff --git a/packages/SystemUI/src/com/android/systemui/modes/shared/ModesUi.kt b/packages/SystemUI/src/com/android/systemui/modes/shared/ModesUi.kt new file mode 100644 index 000000000000..a0663d72a076 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/modes/shared/ModesUi.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.modes.shared + +import android.app.Flags +import com.android.systemui.flags.RefactorFlagUtils + +/** Helper for reading or using the modes ui flag state. */ +@Suppress("NOTHING_TO_INLINE") +object ModesUi { + /** Is the refactor enabled */ + @JvmStatic + inline val isEnabled + get() = Flags.modesApi() && Flags.modesUi() + + /** + * 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, Flags.FLAG_MODES_UI) + + /** + * Called to ensure code is only run when the flag is disabled. This will throw an exception if + * the flag is not enabled to ensure that the refactor author catches issues in testing. + * Caution!! Using this check incorrectly will cause crashes in nextfood builds! + */ + @JvmStatic + inline fun assertInNewMode() = RefactorFlagUtils.assertInNewMode(isEnabled, Flags.FLAG_MODES_UI) + + /** + * 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, Flags.FLAG_MODES_UI) +} diff --git a/packages/SystemUI/src/com/android/systemui/modes/shared/ModesUiIcons.kt b/packages/SystemUI/src/com/android/systemui/modes/shared/ModesUiIcons.kt new file mode 100644 index 000000000000..032b0aca1770 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/modes/shared/ModesUiIcons.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.systemui.modes.shared + +import android.app.Flags +import com.android.systemui.flags.RefactorFlagUtils + +/** Helper for reading or using the modes ui icons flag state. */ +@Suppress("NOTHING_TO_INLINE") +object ModesUiIcons { + /** Is the refactor enabled */ + @JvmStatic + inline val isEnabled + get() = ModesUi.isEnabled && Flags.modesUiIcons() + + /** + * 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, Flags.FLAG_MODES_UI_ICONS) + + /** + * Called to ensure code is only run when the flag is disabled. This will throw an exception if + * the flag is not enabled to ensure that the refactor author catches issues in testing. + * Caution!! Using this check incorrectly will cause crashes in nextfood builds! + */ + @JvmStatic + inline fun assertInNewMode() = + RefactorFlagUtils.assertInNewMode(isEnabled, Flags.FLAG_MODES_UI_ICONS) + + /** + * 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, Flags.FLAG_MODES_UI_ICONS) +} diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt index 54a59f30c8fd..44460ed0716d 100644 --- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt +++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt @@ -19,11 +19,15 @@ import android.app.role.OnRoleHoldersChangedListener import android.app.role.RoleManager import android.content.Context import android.content.pm.UserInfo +import android.hardware.input.InputManager +import android.hardware.input.KeyGestureEvent +import android.os.IBinder import android.os.UserHandle import android.view.KeyEvent import android.view.KeyEvent.KEYCODE_N import android.view.KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL import android.view.ViewConfiguration +import com.android.hardware.input.Flags.useKeyGestureEventHandler import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.dagger.qualifiers.Background @@ -47,6 +51,7 @@ constructor( private val optionalBubbles: Optional<Bubbles>, private val userTracker: UserTracker, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, + private val inputManager: InputManager, @Background private val backgroundExecutor: Executor, @NoteTaskEnabledKey private val isEnabled: Boolean, ) { @@ -59,6 +64,7 @@ constructor( if (!isEnabled || optionalBubbles.isEmpty) return initializeHandleSystemKey() + initializeKeyGestureEventHandler() initializeOnRoleHoldersChanged() initializeOnUserUnlocked() initializeUserTracker() @@ -73,6 +79,16 @@ constructor( } /** + * Initializes a [InputManager.KeyGestureEventHandler] which will handle shortcuts for opening + * the notes role via [NoteTaskController]. + */ + private fun initializeKeyGestureEventHandler() { + if (useKeyGestureEventHandler()) { + inputManager.registerKeyGestureEventHandler(callbacks) + } + } + + /** * Initializes the [RoleManager] role holder changed listener to ensure [NoteTaskController] * will always update whenever the role holder app changes. Keep in mind that a role may change * by direct user interaction (i.e., user goes to settings and change it) or by indirect @@ -110,7 +126,8 @@ constructor( KeyguardUpdateMonitorCallback(), CommandQueue.Callbacks, UserTracker.Callback, - OnRoleHoldersChangedListener { + OnRoleHoldersChangedListener, + InputManager.KeyGestureEventHandler { override fun handleSystemKey(key: KeyEvent) { key.toNoteTaskEntryPointOrNull()?.let(controller::showNoteTask) @@ -131,6 +148,17 @@ constructor( override fun onProfilesChanged(profiles: List<UserInfo>) { controller.updateNoteTaskForCurrentUserAndManagedProfiles() } + + override fun handleKeyGestureEvent( + event: KeyGestureEvent, + focusedToken: IBinder? + ): Boolean { + return this@NoteTaskInitializer.handleKeyGestureEvent(event) + } + + override fun isKeyGestureSupported(gestureType: Int): Boolean { + return this@NoteTaskInitializer.isKeyGestureSupported(gestureType); + } } /** @@ -171,6 +199,24 @@ constructor( return !isMultiPress && !isLongPress } + private fun handleKeyGestureEvent(event: KeyGestureEvent): Boolean { + // This method is on input hot path and should be kept lightweight. Shift all complex + // processing onto background executor wherever possible. + if (event.keyGestureType != KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES) { + return false + } + debugLog { + "handleKeyGestureEvent: Received OPEN_NOTES gesture event from keycodes: " + + event.keycodes.contentToString() + } + backgroundExecutor.execute { controller.showNoteTask(KEYBOARD_SHORTCUT) } + return true + } + + private fun isKeyGestureSupported(gestureType: Int): Boolean { + return gestureType == KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES + } + companion object { val MULTI_PRESS_TIMEOUT = ViewConfiguration.getMultiPressTimeout().toLong() val LONG_PRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout().toLong() diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt index 072d322d69a6..1fe54e46fee1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt @@ -23,17 +23,14 @@ import com.android.systemui.qs.panels.data.repository.DefaultLargeTilesRepositor import com.android.systemui.qs.panels.data.repository.DefaultLargeTilesRepositoryImpl import com.android.systemui.qs.panels.data.repository.GridLayoutTypeRepository import com.android.systemui.qs.panels.data.repository.GridLayoutTypeRepositoryImpl -import com.android.systemui.qs.panels.domain.interactor.GridTypeConsistencyInteractor -import com.android.systemui.qs.panels.domain.interactor.InfiniteGridConsistencyInteractor -import com.android.systemui.qs.panels.domain.interactor.NoopGridConsistencyInteractor import com.android.systemui.qs.panels.shared.model.GridLayoutType import com.android.systemui.qs.panels.shared.model.InfiniteGridLayoutType import com.android.systemui.qs.panels.shared.model.PaginatedGridLayoutType import com.android.systemui.qs.panels.shared.model.PanelsLog import com.android.systemui.qs.panels.ui.compose.GridLayout -import com.android.systemui.qs.panels.ui.compose.InfiniteGridLayout import com.android.systemui.qs.panels.ui.compose.PaginatableGridLayout import com.android.systemui.qs.panels.ui.compose.PaginatedGridLayout +import com.android.systemui.qs.panels.ui.compose.infinitegrid.InfiniteGridLayout import com.android.systemui.qs.panels.ui.viewmodel.FixedColumnsSizeViewModel import com.android.systemui.qs.panels.ui.viewmodel.FixedColumnsSizeViewModelImpl import com.android.systemui.qs.panels.ui.viewmodel.IconLabelVisibilityViewModel @@ -56,11 +53,6 @@ interface PanelsModule { @Binds fun bindGridLayoutTypeRepository(impl: GridLayoutTypeRepositoryImpl): GridLayoutTypeRepository - @Binds - fun bindDefaultGridConsistencyInteractor( - impl: NoopGridConsistencyInteractor - ): GridTypeConsistencyInteractor - @Binds fun bindIconTilesViewModel(impl: IconTilesViewModelImpl): IconTilesViewModel @Binds fun bindGridSizeViewModel(impl: FixedColumnsSizeViewModelImpl): FixedColumnsSizeViewModel @@ -74,12 +66,6 @@ interface PanelsModule { @PaginatedBaseLayoutType fun bindPaginatedBaseGridLayout(impl: InfiniteGridLayout): PaginatableGridLayout - @Binds - @PaginatedBaseLayoutType - fun bindPaginatedBaseConsistencyInteractor( - impl: NoopGridConsistencyInteractor - ): GridTypeConsistencyInteractor - @Binds @Named("Default") fun bindDefaultGridLayout(impl: PaginatedGridLayout): GridLayout companion object { @@ -117,28 +103,5 @@ interface PanelsModule { ): Set<GridLayoutType> { return entries.map { it.first }.toSet() } - - @Provides - @IntoSet - fun provideGridConsistencyInteractor( - consistencyInteractor: InfiniteGridConsistencyInteractor - ): Pair<GridLayoutType, GridTypeConsistencyInteractor> { - return Pair(InfiniteGridLayoutType, consistencyInteractor) - } - - @Provides - @IntoSet - fun providePaginatedGridConsistencyInteractor( - @PaginatedBaseLayoutType consistencyInteractor: GridTypeConsistencyInteractor, - ): Pair<GridLayoutType, GridTypeConsistencyInteractor> { - return Pair(PaginatedGridLayoutType, consistencyInteractor) - } - - @Provides - fun provideGridConsistencyInteractorMap( - entries: Set<@JvmSuppressWildcards Pair<GridLayoutType, GridTypeConsistencyInteractor>> - ): Map<GridLayoutType, GridTypeConsistencyInteractor> { - return entries.toMap() - } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridConsistencyInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridConsistencyInteractor.kt deleted file mode 100644 index a2e7ea6fe797..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridConsistencyInteractor.kt +++ /dev/null @@ -1,75 +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.qs.panels.domain.interactor - -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.log.LogBuffer -import com.android.systemui.log.core.LogLevel -import com.android.systemui.qs.panels.shared.model.GridLayoutType -import com.android.systemui.qs.panels.shared.model.PanelsLog -import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor -import com.android.systemui.qs.pipeline.shared.TileSpec -import javax.inject.Inject -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.launch - -@SysUISingleton -class GridConsistencyInteractor -@Inject -constructor( - private val gridLayoutTypeInteractor: GridLayoutTypeInteractor, - private val currentTilesInteractor: CurrentTilesInteractor, - private val consistencyInteractors: - Map<GridLayoutType, @JvmSuppressWildcards GridTypeConsistencyInteractor>, - private val defaultConsistencyInteractor: GridTypeConsistencyInteractor, - @PanelsLog private val logBuffer: LogBuffer, - @Application private val applicationScope: CoroutineScope, -) { - fun start() { - applicationScope.launch { - gridLayoutTypeInteractor.layout.collectLatest { type -> - val consistencyInteractor = - consistencyInteractors[type] ?: defaultConsistencyInteractor - currentTilesInteractor.currentTiles - .map { tiles -> tiles.map { it.spec } } - .collectLatest { tiles -> - val newTiles = consistencyInteractor.reconcileTiles(tiles) - if (newTiles != tiles) { - currentTilesInteractor.setTiles(newTiles) - logChange(newTiles) - } - } - } - } - } - - private fun logChange(tiles: List<TileSpec>) { - logBuffer.log( - LOG_BUFFER_CURRENT_TILES_CHANGE_TAG, - LogLevel.DEBUG, - { str1 = tiles.toString() }, - { "Tiles reordered: $str1" } - ) - } - - private companion object { - const val LOG_BUFFER_CURRENT_TILES_CHANGE_TAG = "GridConsistencyTilesChange" - } -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridConsistencyInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridConsistencyInteractor.kt deleted file mode 100644 index 874b3b0a4636..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridConsistencyInteractor.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.qs.panels.domain.interactor - -import android.util.Log -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.qs.panels.shared.model.SizedTile -import com.android.systemui.qs.panels.shared.model.SizedTileImpl -import com.android.systemui.qs.panels.shared.model.TileRow -import com.android.systemui.qs.pipeline.shared.TileSpec -import javax.inject.Inject - -@SysUISingleton -class InfiniteGridConsistencyInteractor -@Inject -constructor( - private val iconTilesInteractor: IconTilesInteractor, - private val gridSizeInteractor: FixedColumnsSizeInteractor -) : GridTypeConsistencyInteractor { - - /** - * Tries to fill in every columns of all rows (except the last row), potentially reordering - * tiles. - */ - override fun reconcileTiles(tiles: List<TileSpec>): List<TileSpec> { - val newTiles: MutableList<TileSpec> = mutableListOf() - val row = TileRow<TileSpec>(columns = gridSizeInteractor.columns.value) - val tilesQueue: ArrayDeque<SizedTile<TileSpec>> = - ArrayDeque( - tiles.map { - SizedTileImpl( - it, - if (iconTilesInteractor.isIconTile(it)) 1 else 2, - ) - } - ) - - while (tilesQueue.isNotEmpty()) { - if (row.isFull()) { - newTiles.addAll(row.tiles.map { it.tile }) - row.clear() - } - - val tile = tilesQueue.removeFirst() - - // If the tile fits in the row, add it. - if (!row.maybeAddTile(tile)) { - // If the tile does not fit the row, find an icon tile to move. - // We'll try to either add an icon tile from the queue to complete the row, or - // remove an icon tile from the current row to free up space. - - val iconTile: SizedTile<TileSpec>? = tilesQueue.firstOrNull { it.width == 1 } - if (iconTile != null) { - tilesQueue.remove(iconTile) - tilesQueue.addFirst(tile) - row.maybeAddTile(iconTile) - } else { - val tileToRemove: SizedTile<TileSpec>? = row.findLastIconTile() - if (tileToRemove != null) { - row.removeTile(tileToRemove) - row.maybeAddTile(tile) - - // Moving the icon tile to the end because there's no other - // icon tiles in the queue. - tilesQueue.addLast(tileToRemove) - } else { - // If the row does not have an icon tile, add the incomplete row. - // Note: this shouldn't happen because an icon tile is guaranteed to be in a - // row that doesn't have enough space for a large tile. - val tileSpecs = row.tiles.map { it.tile } - Log.wtf(TAG, "Uneven row does not have an icon tile to remove: $tileSpecs") - newTiles.addAll(tileSpecs) - row.clear() - tilesQueue.addFirst(tile) - } - } - } - } - - // Add last row that might be incomplete - newTiles.addAll(row.tiles.map { it.tile }) - - return newTiles.toList() - } - - private companion object { - const val TAG = "InfiniteGridConsistencyInteractor" - } -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/NoopGridConsistencyInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/NoopGridConsistencyInteractor.kt deleted file mode 100644 index 0386a6ab20d6..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/NoopGridConsistencyInteractor.kt +++ /dev/null @@ -1,27 +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.qs.panels.domain.interactor - -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.qs.pipeline.shared.TileSpec -import javax.inject.Inject - -/** [GridTypeConsistencyInteractor] implementation that doesn't do any changes to tiles. */ -@SysUISingleton -class NoopGridConsistencyInteractor @Inject constructor() : GridTypeConsistencyInteractor { - override fun reconcileTiles(tiles: List<TileSpec>): List<TileSpec> = tiles -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/DragAndDropState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/DragAndDropState.kt index 9a2315be29a2..1f8a24a1da67 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/DragAndDropState.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/DragAndDropState.kt @@ -161,9 +161,9 @@ private fun insertAfter(item: LazyGridItemInfo, offset: Offset): Boolean { @Composable fun Modifier.dragAndDropTileSource( sizedTile: SizedTile<EditTileViewModel>, + dragAndDropState: DragAndDropState, onTap: (TileSpec) -> Unit, - onDoubleTap: (TileSpec) -> Unit, - dragAndDropState: DragAndDropState + onDoubleTap: (TileSpec) -> Unit = {}, ): Modifier { val state by rememberUpdatedState(dragAndDropState) return dragAndDropSource { @@ -181,11 +181,11 @@ fun Modifier.dragAndDropTileSource( ClipData( QsDragAndDrop.CLIPDATA_LABEL, arrayOf(QsDragAndDrop.TILESPEC_MIME_TYPE), - ClipData.Item(sizedTile.tile.tileSpec.spec) + ClipData.Item(sizedTile.tile.tileSpec.spec), ) ) ) - } + }, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt index fde40da2e5bc..f4acbec1063c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt @@ -25,6 +25,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.util.fastMap import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.systemui.compose.modifiers.sysuiResTag +import com.android.systemui.qs.panels.ui.compose.infinitegrid.Tile +import com.android.systemui.qs.panels.ui.compose.infinitegrid.TileLazyGrid import com.android.systemui.qs.panels.ui.viewmodel.QuickQuickSettingsViewModel @Composable diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt deleted file mode 100644 index afd47a7f7758..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/Tile.kt +++ /dev/null @@ -1,926 +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(ExperimentalFoundationApi::class) - -package com.android.systemui.qs.panels.ui.compose - -import android.content.res.Resources -import android.graphics.drawable.Animatable -import android.service.quicksettings.Tile.STATE_ACTIVE -import android.service.quicksettings.Tile.STATE_INACTIVE -import android.text.TextUtils -import androidx.compose.animation.AnimatedContent -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.core.animateDpAsState -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi -import androidx.compose.animation.graphics.res.animatedVectorResource -import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter -import androidx.compose.animation.graphics.vector.AnimatedImageVector -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.Image -import androidx.compose.foundation.LocalOverscrollConfiguration -import androidx.compose.foundation.background -import androidx.compose.foundation.basicMarquee -import androidx.compose.foundation.border -import androidx.compose.foundation.combinedClickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Arrangement.spacedBy -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxScope -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyGridItemScope -import androidx.compose.foundation.lazy.grid.LazyGridScope -import androidx.compose.foundation.lazy.grid.LazyGridState -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.rememberLazyGridState -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Clear -import androidx.compose.material3.Icon -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.ReadOnlyComposable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberUpdatedState -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.layout.positionInRoot -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.testTag -import androidx.compose.ui.res.dimensionResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.Role -import androidx.compose.ui.semantics.clearAndSetSemantics -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.onClick -import androidx.compose.ui.semantics.role -import androidx.compose.ui.semantics.semantics -import androidx.compose.ui.semantics.stateDescription -import androidx.compose.ui.semantics.toggleableState -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.util.fastMap -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.android.compose.animation.Expandable -import com.android.compose.modifiers.background -import com.android.compose.modifiers.thenIf -import com.android.systemui.animation.Expandable -import com.android.systemui.common.shared.model.Icon -import com.android.systemui.common.ui.compose.Icon -import com.android.systemui.common.ui.compose.load -import com.android.systemui.compose.modifiers.sysuiResTag -import com.android.systemui.plugins.qs.QSTile -import com.android.systemui.qs.panels.shared.model.SizedTile -import com.android.systemui.qs.panels.shared.model.SizedTileImpl -import com.android.systemui.qs.panels.ui.compose.TileDefaults.longPressLabel -import com.android.systemui.qs.panels.ui.model.GridCell -import com.android.systemui.qs.panels.ui.model.SpacerGridCell -import com.android.systemui.qs.panels.ui.model.TileGridCell -import com.android.systemui.qs.panels.ui.viewmodel.AccessibilityUiState -import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel -import com.android.systemui.qs.panels.ui.viewmodel.TileUiState -import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel -import com.android.systemui.qs.panels.ui.viewmodel.toUiState -import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor -import com.android.systemui.qs.pipeline.shared.TileSpec -import com.android.systemui.qs.shared.model.groupAndSort -import com.android.systemui.qs.tileimpl.QSTileImpl -import com.android.systemui.res.R -import java.util.function.Supplier -import kotlinx.coroutines.delay - -object TileType - -private const val TEST_TAG_SMALL = "qs_tile_small" -private const val TEST_TAG_LARGE = "qs_tile_large" -private const val TEST_TAG_TOGGLE = "qs_tile_toggle_target" - -@Composable -fun Tile(tile: TileViewModel, iconOnly: Boolean, showLabels: Boolean = false, modifier: Modifier) { - val state by tile.state.collectAsStateWithLifecycle(tile.currentState) - val resources = resources() - val uiState = remember(state, resources) { state.toUiState(resources) } - val colors = TileDefaults.getColorForState(uiState) - - // TODO(b/361789146): Draw the shapes instead of clipping - val tileShape = TileDefaults.animateTileShape(uiState.state) - - TileContainer( - colors = colors, - showLabels = showLabels, - label = uiState.label, - iconOnly = iconOnly, - shape = tileShape, - clickEnabled = true, - onClick = tile::onClick, - onLongClick = tile::onLongClick, - modifier = modifier.height(tileHeight()), - uiState = uiState, - ) { - val icon = getTileIcon(icon = uiState.icon) - if (iconOnly) { - TileIcon(icon = icon, color = colors.icon, modifier = Modifier.align(Alignment.Center)) - } else { - val iconShape = TileDefaults.animateIconShape(uiState.state) - LargeTileContent( - label = uiState.label, - secondaryLabel = uiState.secondaryLabel, - icon = icon, - colors = colors, - iconShape = iconShape, - toggleClickSupported = state.handlesSecondaryClick, - onClick = { - if (state.handlesSecondaryClick) { - tile.onSecondaryClick() - } - }, - onLongClick = { tile.onLongClick(it) }, - accessibilityUiState = uiState.accessibilityUiState, - ) - } - } -} - -@Composable -private fun TileContainer( - colors: TileColors, - showLabels: Boolean, - label: String, - iconOnly: Boolean, - shape: Shape, - clickEnabled: Boolean = false, - onClick: (Expandable) -> Unit = {}, - onLongClick: (Expandable) -> Unit = {}, - modifier: Modifier = Modifier, - uiState: TileUiState? = null, - content: @Composable BoxScope.(Expandable) -> Unit, -) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = - spacedBy(dimensionResource(id = R.dimen.qs_label_container_margin), Alignment.Top), - modifier = modifier, - ) { - val backgroundColor = - if (iconOnly || uiState?.handlesSecondaryClick != true) { - colors.iconBackground - } else { - colors.background - } - Expandable( - color = backgroundColor, - shape = shape, - modifier = Modifier.height(tileHeight()).clip(shape), - ) { - val longPressLabel = longPressLabel() - Box( - modifier = - Modifier.fillMaxSize() - .thenIf(clickEnabled) { - Modifier.combinedClickable( - onClick = { onClick(it) }, - onLongClick = { onLongClick(it) }, - onClickLabel = uiState?.accessibilityUiState?.clickLabel, - onLongClickLabel = longPressLabel, - ) - } - .thenIf(uiState != null) { - uiState as TileUiState - Modifier.semantics { - role = uiState.accessibilityUiState.accessibilityRole - if ( - uiState.accessibilityUiState.accessibilityRole == - Role.Switch - ) { - uiState.accessibilityUiState.toggleableState?.let { - toggleableState = it - } - } - stateDescription = uiState.accessibilityUiState.stateDescription - } - .sysuiResTag(if (iconOnly) TEST_TAG_SMALL else TEST_TAG_LARGE) - .thenIf(iconOnly) { - Modifier.semantics { - contentDescription = - uiState.accessibilityUiState.contentDescription - } - } - } - .tilePadding() - ) { - content(it) - } - } - - if (showLabels && iconOnly) { - Text( - label, - maxLines = 2, - color = colors.label, - overflow = TextOverflow.Ellipsis, - textAlign = TextAlign.Center, - ) - } - } -} - -@Composable -private fun LargeTileContent( - label: String, - secondaryLabel: String?, - icon: Icon, - colors: TileColors, - iconShape: Shape, - accessibilityUiState: AccessibilityUiState? = null, - toggleClickSupported: Boolean = false, - onClick: () -> Unit = {}, - onLongClick: () -> Unit = {}, -) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = tileHorizontalArrangement(), - ) { - // Icon - val longPressLabel = longPressLabel() - Box( - modifier = - Modifier.size(TileDefaults.ToggleTargetSize).thenIf(toggleClickSupported) { - Modifier.clip(iconShape) - .background(colors.iconBackground, { 1f }) - .combinedClickable( - onClick = onClick, - onLongClick = onLongClick, - onLongClickLabel = longPressLabel, - ) - .thenIf(accessibilityUiState != null) { - accessibilityUiState as AccessibilityUiState - Modifier.semantics { - contentDescription = accessibilityUiState.contentDescription - stateDescription = accessibilityUiState.stateDescription - accessibilityUiState.toggleableState?.let { - toggleableState = it - } - role = Role.Switch - } - .sysuiResTag(TEST_TAG_TOGGLE) - } - } - ) { - TileIcon(icon = icon, color = colors.icon, modifier = Modifier.align(Alignment.Center)) - } - - // Labels - Column(verticalArrangement = Arrangement.Center, modifier = Modifier.fillMaxHeight()) { - Text(label, color = colors.label, modifier = Modifier.tileMarquee()) - if (!TextUtils.isEmpty(secondaryLabel)) { - Text( - secondaryLabel ?: "", - color = colors.secondaryLabel, - modifier = - Modifier.tileMarquee().thenIf( - accessibilityUiState - ?.stateDescription - ?.contains(secondaryLabel ?: "") == true - ) { - Modifier.clearAndSetSemantics {} - }, - ) - } - } - } -} - -private fun Modifier.tileMarquee(): Modifier { - return basicMarquee(iterations = 1, initialDelayMillis = 200) -} - -@Composable -fun TileLazyGrid( - modifier: Modifier = Modifier, - state: LazyGridState = rememberLazyGridState(), - columns: GridCells, - content: LazyGridScope.() -> Unit, -) { - LazyVerticalGrid( - state = state, - columns = columns, - verticalArrangement = spacedBy(dimensionResource(R.dimen.qs_tile_margin_vertical)), - horizontalArrangement = spacedBy(dimensionResource(R.dimen.qs_tile_margin_horizontal)), - modifier = modifier, - content = content, - ) -} - -@Composable -fun DefaultEditTileGrid( - currentListState: EditTileListState, - otherTiles: List<SizedTile<EditTileViewModel>>, - columns: Int, - modifier: Modifier, - onAddTile: (TileSpec, Int) -> Unit, - onRemoveTile: (TileSpec) -> Unit, - onSetTiles: (List<TileSpec>) -> Unit, - onResize: (TileSpec) -> Unit, -) { - val addTileToEnd: (TileSpec) -> Unit by rememberUpdatedState { - onAddTile(it, CurrentTilesInteractor.POSITION_AT_END) - } - val tilePadding = dimensionResource(R.dimen.qs_tile_margin_vertical) - - CompositionLocalProvider(LocalOverscrollConfiguration provides null) { - Column( - verticalArrangement = - spacedBy(dimensionResource(id = R.dimen.qs_label_container_margin)), - modifier = modifier.fillMaxSize().verticalScroll(rememberScrollState()), - ) { - AnimatedContent( - targetState = currentListState.dragInProgress, - modifier = Modifier.wrapContentSize(), - ) { dragIsInProgress -> - EditGridHeader(Modifier.dragAndDropRemoveZone(currentListState, onRemoveTile)) { - if (dragIsInProgress) { - RemoveTileTarget() - } else { - Text(text = "Hold and drag to rearrange tiles.") - } - } - } - - CurrentTilesGrid( - currentListState, - columns, - tilePadding, - onRemoveTile, - onResize, - onSetTiles, - ) - - // Hide available tiles when dragging - AnimatedVisibility( - visible = !currentListState.dragInProgress, - enter = fadeIn(), - exit = fadeOut(), - ) { - Column( - verticalArrangement = - spacedBy(dimensionResource(id = R.dimen.qs_label_container_margin)), - modifier = modifier.fillMaxSize(), - ) { - EditGridHeader { Text(text = "Hold and drag to add tiles.") } - - AvailableTileGrid( - otherTiles, - columns, - tilePadding, - addTileToEnd, - currentListState, - ) - } - } - - // Drop zone to remove tiles dragged out of the tile grid - Spacer( - modifier = - Modifier.fillMaxWidth() - .weight(1f) - .dragAndDropRemoveZone(currentListState, onRemoveTile) - ) - } - } -} - -@Composable -private fun EditGridHeader( - modifier: Modifier = Modifier, - content: @Composable BoxScope.() -> Unit, -) { - CompositionLocalProvider( - LocalContentColor provides MaterialTheme.colorScheme.onBackground.copy(alpha = .5f) - ) { - Box( - contentAlignment = Alignment.Center, - modifier = modifier.fillMaxWidth().height(EditModeTileDefaults.EditGridHeaderHeight), - ) { - content() - } - } -} - -@Composable -private fun RemoveTileTarget() { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = tileHorizontalArrangement(), - modifier = - Modifier.fillMaxHeight() - .border(1.dp, LocalContentColor.current, shape = CircleShape) - .padding(10.dp), - ) { - Icon(imageVector = Icons.Default.Clear, contentDescription = null) - Text(text = "Remove") - } -} - -@Composable -private fun CurrentTilesContainer(content: @Composable () -> Unit) { - Box( - Modifier.fillMaxWidth() - .border( - width = 1.dp, - color = MaterialTheme.colorScheme.onBackground.copy(alpha = .5f), - shape = RoundedCornerShape(48.dp), - ) - .padding(dimensionResource(R.dimen.qs_tile_margin_vertical)) - ) { - content() - } -} - -@Composable -private fun CurrentTilesGrid( - listState: EditTileListState, - columns: Int, - tilePadding: Dp, - onClick: (TileSpec) -> Unit, - onResize: (TileSpec) -> Unit, - onSetTiles: (List<TileSpec>) -> Unit, -) { - val currentListState by rememberUpdatedState(listState) - - CurrentTilesContainer { - val tileHeight = tileHeight() - val totalRows = listState.tiles.lastOrNull()?.row ?: 0 - val totalHeight = gridHeight(totalRows + 1, tileHeight, tilePadding) - val gridState = rememberLazyGridState() - var gridContentOffset by remember { mutableStateOf(Offset(0f, 0f)) } - - TileLazyGrid( - state = gridState, - modifier = - Modifier.height(totalHeight) - .dragAndDropTileList(gridState, gridContentOffset, listState) { - onSetTiles(currentListState.tileSpecs()) - } - .onGloballyPositioned { coordinates -> - gridContentOffset = coordinates.positionInRoot() - } - .testTag(CURRENT_TILES_GRID_TEST_TAG), - columns = GridCells.Fixed(columns), - ) { - editTiles( - listState.tiles, - ClickAction.REMOVE, - onClick, - listState, - onResize = onResize, - indicatePosition = true, - ) - } - } -} - -@Composable -private fun AvailableTileGrid( - tiles: List<SizedTile<EditTileViewModel>>, - columns: Int, - tilePadding: Dp, - onClick: (TileSpec) -> Unit, - dragAndDropState: DragAndDropState, -) { - val availableTileHeight = tileHeight(true) - val availableGridHeight = gridHeight(tiles.size, availableTileHeight, columns, tilePadding) - - // Available tiles aren't visible during drag and drop, so the row isn't needed - val groupedTiles = - remember(tiles.fastMap { it.tile.category }, tiles.fastMap { it.tile.label }) { - groupAndSort(tiles.fastMap { TileGridCell(it, 0) }) - } - val labelColors = TileDefaults.inactiveTileColors() - // Available tiles - TileLazyGrid( - modifier = Modifier.height(availableGridHeight).testTag(AVAILABLE_TILES_GRID_TEST_TAG), - columns = GridCells.Fixed(columns), - ) { - groupedTiles.forEach { category, tiles -> - stickyHeader { - Text( - text = category.label.load() ?: "", - fontSize = 20.sp, - color = labelColors.label, - modifier = - Modifier.background(Color.Black) - .padding(start = 16.dp, bottom = 8.dp, top = 8.dp), - ) - } - editTiles( - tiles, - ClickAction.ADD, - onClick, - dragAndDropState = dragAndDropState, - showLabels = true, - ) - } - } -} - -fun gridHeight(nTiles: Int, tileHeight: Dp, columns: Int, padding: Dp): Dp { - val rows = (nTiles + columns - 1) / columns - return gridHeight(rows, tileHeight, padding) -} - -fun gridHeight(rows: Int, tileHeight: Dp, padding: Dp): Dp { - return ((tileHeight + padding) * rows) - padding -} - -private fun GridCell.key(index: Int, dragAndDropState: DragAndDropState): Any { - return if (this is TileGridCell && !dragAndDropState.isMoving(tile.tileSpec)) { - key - } else { - index - } -} - -fun LazyGridScope.editTiles( - cells: List<GridCell>, - clickAction: ClickAction, - onClick: (TileSpec) -> Unit, - dragAndDropState: DragAndDropState, - onResize: (TileSpec) -> Unit = {}, - showLabels: Boolean = false, - indicatePosition: Boolean = false, -) { - items( - count = cells.size, - key = { cells[it].key(it, dragAndDropState) }, - span = { cells[it].span }, - contentType = { TileType }, - ) { index -> - when (val cell = cells[index]) { - is TileGridCell -> - if (dragAndDropState.isMoving(cell.tile.tileSpec)) { - // If the tile is being moved, replace it with a visible spacer - SpacerGridCell( - Modifier.background( - color = MaterialTheme.colorScheme.secondary, - alpha = { EditModeTileDefaults.PLACEHOLDER_ALPHA }, - shape = RoundedCornerShape(TileDefaults.InactiveCornerRadius), - ) - .animateItem() - ) - } else { - TileGridCell( - cell = cell, - index = index, - dragAndDropState = dragAndDropState, - clickAction = clickAction, - onClick = onClick, - onResize = onResize, - showLabels = showLabels, - indicatePosition = indicatePosition, - ) - } - is SpacerGridCell -> SpacerGridCell() - } - } -} - -@Composable -private fun LazyGridItemScope.TileGridCell( - cell: TileGridCell, - index: Int, - dragAndDropState: DragAndDropState, - clickAction: ClickAction, - onClick: (TileSpec) -> Unit, - onResize: (TileSpec) -> Unit = {}, - showLabels: Boolean = false, - indicatePosition: Boolean = false, -) { - val tileHeight = tileHeight(cell.isIcon && showLabels) - val onClickActionName = - when (clickAction) { - ClickAction.ADD -> stringResource(id = R.string.accessibility_qs_edit_tile_add_action) - ClickAction.REMOVE -> - stringResource(id = R.string.accessibility_qs_edit_remove_tile_action) - } - val stateDescription = - if (indicatePosition) { - stringResource(id = R.string.accessibility_qs_edit_position, index + 1) - } else { - "" - } - EditTile( - tileViewModel = cell.tile, - iconOnly = cell.isIcon, - showLabels = showLabels, - modifier = - Modifier.height(tileHeight) - .animateItem() - .semantics(mergeDescendants = true) { - onClick(onClickActionName) { false } - this.stateDescription = stateDescription - } - .dragAndDropTileSource( - SizedTileImpl(cell.tile, cell.width), - onClick, - onResize, - dragAndDropState, - ), - ) -} - -@Composable -private fun SpacerGridCell(modifier: Modifier = Modifier) { - // By default, spacers are invisible and exist purely to catch drag movements - Box(modifier.height(tileHeight()).fillMaxWidth().tilePadding()) -} - -@Composable -fun EditTile( - tileViewModel: EditTileViewModel, - iconOnly: Boolean, - showLabels: Boolean, - modifier: Modifier = Modifier, -) { - val label = tileViewModel.label.text - val colors = TileDefaults.inactiveTileColors() - - TileContainer( - colors = colors, - showLabels = showLabels, - label = label, - iconOnly = iconOnly, - shape = RoundedCornerShape(TileDefaults.InactiveCornerRadius), - modifier = modifier, - ) { - if (iconOnly) { - TileIcon( - icon = tileViewModel.icon, - color = colors.icon, - modifier = Modifier.align(Alignment.Center), - ) - } else { - LargeTileContent( - label = label, - secondaryLabel = tileViewModel.appName?.text, - icon = tileViewModel.icon, - colors = colors, - iconShape = RoundedCornerShape(TileDefaults.InactiveCornerRadius), - ) - } - } -} - -enum class ClickAction { - ADD, - REMOVE, -} - -@Composable -private fun getTileIcon(icon: Supplier<QSTile.Icon?>): Icon { - val context = LocalContext.current - return icon.get()?.let { - if (it is QSTileImpl.ResourceIcon) { - Icon.Resource(it.resId, null) - } else { - Icon.Loaded(it.getDrawable(context), null) - } - } ?: Icon.Resource(R.drawable.ic_error_outline, null) -} - -@OptIn(ExperimentalAnimationGraphicsApi::class) -@Composable -private fun TileIcon( - icon: Icon, - color: Color, - animateToEnd: Boolean = false, - modifier: Modifier = Modifier, -) { - val iconModifier = modifier.size(TileDefaults.IconSize) - val context = LocalContext.current - val loadedDrawable = - remember(icon, context) { - when (icon) { - is Icon.Loaded -> icon.drawable - is Icon.Resource -> context.getDrawable(icon.res) - } - } - if (loadedDrawable !is Animatable) { - Icon(icon = icon, tint = color, modifier = iconModifier) - } else if (icon is Icon.Resource) { - val image = AnimatedImageVector.animatedVectorResource(id = icon.res) - val painter = - if (animateToEnd) { - rememberAnimatedVectorPainter(animatedImageVector = image, atEnd = true) - } else { - var atEnd by remember(icon.res) { mutableStateOf(false) } - LaunchedEffect(key1 = icon.res) { - delay(350) - atEnd = true - } - rememberAnimatedVectorPainter(animatedImageVector = image, atEnd = atEnd) - } - Image( - painter = painter, - contentDescription = icon.contentDescription?.load(), - colorFilter = ColorFilter.tint(color = color), - modifier = iconModifier, - ) - } -} - -private fun Modifier.tilePadding(): Modifier { - return padding(TileDefaults.TilePadding) -} - -private fun tileHorizontalArrangement(): Arrangement.Horizontal { - return spacedBy(space = TileDefaults.TileArrangementPadding, alignment = Alignment.Start) -} - -@Composable -fun tileHeight(iconWithLabel: Boolean = false): Dp { - return if (iconWithLabel) { - TileDefaults.IconTileWithLabelHeight - } else { - TileDefaults.TileHeight - } -} - -private data class TileColors( - val background: Color, - val iconBackground: Color, - val label: Color, - val secondaryLabel: Color, - val icon: Color, -) - -private object EditModeTileDefaults { - const val PLACEHOLDER_ALPHA = .3f - val EditGridHeaderHeight = 60.dp -} - -private object TileDefaults { - val InactiveCornerRadius = 50.dp - val ActiveIconCornerRadius = 16.dp - val ActiveTileCornerRadius = 24.dp - - val ToggleTargetSize = 56.dp - val IconSize = 24.dp - - val TilePadding = 8.dp - val TileArrangementPadding = 6.dp - - val TileHeight = 72.dp - val IconTileWithLabelHeight = 140.dp - - @Composable fun longPressLabel() = stringResource(id = R.string.accessibility_long_click_tile) - - /** An active tile without dual target uses the active color as background */ - @Composable - fun activeTileColors(): TileColors = - TileColors( - background = MaterialTheme.colorScheme.primary, - iconBackground = MaterialTheme.colorScheme.primary, - label = MaterialTheme.colorScheme.onPrimary, - secondaryLabel = MaterialTheme.colorScheme.onPrimary, - icon = MaterialTheme.colorScheme.onPrimary, - ) - - /** An active tile with dual target only show the active color on the icon */ - @Composable - fun activeDualTargetTileColors(): TileColors = - TileColors( - background = MaterialTheme.colorScheme.surfaceVariant, - iconBackground = MaterialTheme.colorScheme.primary, - label = MaterialTheme.colorScheme.onSurfaceVariant, - secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, - icon = MaterialTheme.colorScheme.onPrimary, - ) - - @Composable - fun inactiveTileColors(): TileColors = - TileColors( - background = MaterialTheme.colorScheme.surfaceVariant, - iconBackground = MaterialTheme.colorScheme.surfaceVariant, - label = MaterialTheme.colorScheme.onSurfaceVariant, - secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, - icon = MaterialTheme.colorScheme.onSurfaceVariant, - ) - - @Composable - fun unavailableTileColors(): TileColors = - TileColors( - background = MaterialTheme.colorScheme.surface, - iconBackground = MaterialTheme.colorScheme.surface, - label = MaterialTheme.colorScheme.onSurface, - secondaryLabel = MaterialTheme.colorScheme.onSurface, - icon = MaterialTheme.colorScheme.onSurface, - ) - - @Composable - fun getColorForState(uiState: TileUiState): TileColors { - return when (uiState.state) { - STATE_ACTIVE -> { - if (uiState.handlesSecondaryClick) { - activeDualTargetTileColors() - } else { - activeTileColors() - } - } - STATE_INACTIVE -> inactiveTileColors() - else -> unavailableTileColors() - } - } - - @Composable - fun animateIconShape(state: Int): Shape { - return animateShape( - state = state, - activeCornerRadius = ActiveIconCornerRadius, - label = "QSTileCornerRadius", - ) - } - - @Composable - fun animateTileShape(state: Int): Shape { - return animateShape( - state = state, - activeCornerRadius = ActiveTileCornerRadius, - label = "QSTileIconCornerRadius", - ) - } - - @Composable - fun animateShape(state: Int, activeCornerRadius: Dp, label: String): Shape { - val animatedCornerRadius by - animateDpAsState( - targetValue = - if (state == STATE_ACTIVE) { - activeCornerRadius - } else { - InactiveCornerRadius - }, - label = label, - ) - return RoundedCornerShape(animatedCornerRadius) - } -} - -private const val CURRENT_TILES_GRID_TEST_TAG = "CurrentTilesGrid" -private const val AVAILABLE_TILES_GRID_TEST_TAG = "AvailableTilesGrid" - -/** - * A composable function that returns the [Resources]. It will be recomposed when [Configuration] - * gets updated. - */ -@Composable -@ReadOnlyComposable -private fun resources(): Resources { - LocalConfiguration.current - return LocalContext.current.resources -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt new file mode 100644 index 000000000000..aeb6031d7b72 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt @@ -0,0 +1,204 @@ +/* + * 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.qs.panels.ui.compose.infinitegrid + +import android.graphics.drawable.Animatable +import android.text.TextUtils +import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi +import androidx.compose.animation.graphics.res.animatedVectorResource +import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter +import androidx.compose.animation.graphics.vector.AnimatedImageVector +import androidx.compose.foundation.Image +import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.layout.Arrangement +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.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.stateDescription +import androidx.compose.ui.semantics.toggleableState +import androidx.compose.ui.unit.dp +import com.android.compose.modifiers.background +import com.android.compose.modifiers.thenIf +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.common.ui.compose.Icon +import com.android.systemui.common.ui.compose.load +import com.android.systemui.compose.modifiers.sysuiResTag +import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.longPressLabel +import com.android.systemui.qs.panels.ui.viewmodel.AccessibilityUiState +import com.android.systemui.res.R +import kotlinx.coroutines.delay + +private const val TEST_TAG_TOGGLE = "qs_tile_toggle_target" + +@Composable +fun LargeTileContent( + label: String, + secondaryLabel: String?, + icon: Icon, + colors: TileColors, + accessibilityUiState: AccessibilityUiState? = null, + toggleClickSupported: Boolean = false, + iconShape: Shape = RoundedCornerShape(CommonTileDefaults.InactiveCornerRadius), + onClick: () -> Unit = {}, + onLongClick: () -> Unit = {}, +) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = tileHorizontalArrangement(), + ) { + // Icon + val longPressLabel = longPressLabel() + Box( + modifier = + Modifier.size(CommonTileDefaults.ToggleTargetSize).thenIf(toggleClickSupported) { + Modifier.clip(iconShape) + .background(colors.iconBackground, { 1f }) + .combinedClickable( + onClick = onClick, + onLongClick = onLongClick, + onLongClickLabel = longPressLabel, + ) + .thenIf(accessibilityUiState != null) { + Modifier.semantics { + accessibilityUiState as AccessibilityUiState + contentDescription = accessibilityUiState.contentDescription + stateDescription = accessibilityUiState.stateDescription + accessibilityUiState.toggleableState?.let { + toggleableState = it + } + role = Role.Switch + } + .sysuiResTag(TEST_TAG_TOGGLE) + } + } + ) { + SmallTileContent( + icon = icon, + color = colors.icon, + modifier = Modifier.align(Alignment.Center), + ) + } + + // Labels + LargeTileLabels( + label = label, + secondaryLabel = secondaryLabel, + colors = colors, + accessibilityUiState = accessibilityUiState, + ) + } +} + +@Composable +private fun LargeTileLabels( + label: String, + secondaryLabel: String?, + colors: TileColors, + accessibilityUiState: AccessibilityUiState? = null, +) { + Column(verticalArrangement = Arrangement.Center, modifier = Modifier.fillMaxHeight()) { + Text(label, color = colors.label, modifier = Modifier.tileMarquee()) + if (!TextUtils.isEmpty(secondaryLabel)) { + Text( + secondaryLabel ?: "", + color = colors.secondaryLabel, + modifier = + Modifier.tileMarquee().thenIf( + accessibilityUiState?.stateDescription?.contains(secondaryLabel ?: "") == + true + ) { + Modifier.clearAndSetSemantics {} + }, + ) + } + } +} + +@OptIn(ExperimentalAnimationGraphicsApi::class) +@Composable +fun SmallTileContent( + modifier: Modifier = Modifier, + icon: Icon, + color: Color, + animateToEnd: Boolean = false, +) { + val iconModifier = modifier.size(CommonTileDefaults.IconSize) + val context = LocalContext.current + val loadedDrawable = + remember(icon, context) { + when (icon) { + is Icon.Loaded -> icon.drawable + is Icon.Resource -> context.getDrawable(icon.res) + } + } + if (loadedDrawable !is Animatable) { + Icon(icon = icon, tint = color, modifier = iconModifier) + } else if (icon is Icon.Resource) { + val image = AnimatedImageVector.animatedVectorResource(id = icon.res) + val painter = + if (animateToEnd) { + rememberAnimatedVectorPainter(animatedImageVector = image, atEnd = true) + } else { + var atEnd by remember(icon.res) { mutableStateOf(false) } + LaunchedEffect(key1 = icon.res) { + delay(350) + atEnd = true + } + rememberAnimatedVectorPainter(animatedImageVector = image, atEnd = atEnd) + } + Image( + painter = painter, + contentDescription = icon.contentDescription?.load(), + colorFilter = ColorFilter.tint(color = color), + modifier = iconModifier, + ) + } +} + +object CommonTileDefaults { + val IconSize = 24.dp + val ToggleTargetSize = 56.dp + val TileHeight = 72.dp + val TilePadding = 8.dp + val TileArrangementPadding = 6.dp + val InactiveCornerRadius = 50.dp + + @Composable fun longPressLabel() = stringResource(id = R.string.accessibility_long_click_tile) +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt new file mode 100644 index 000000000000..a43b8807b211 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt @@ -0,0 +1,503 @@ +/* + * 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(ExperimentalFoundationApi::class) + +package com.android.systemui.qs.panels.ui.compose.infinitegrid + +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.LocalOverscrollConfiguration +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement.spacedBy +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyGridItemScope +import androidx.compose.foundation.lazy.grid.LazyGridScope +import androidx.compose.foundation.lazy.grid.rememberLazyGridState +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Clear +import androidx.compose.material3.Icon +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.geometry.CornerRadius +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.layout.positionInRoot +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.onClick +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.stateDescription +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.util.fastMap +import com.android.compose.modifiers.background +import com.android.systemui.common.ui.compose.load +import com.android.systemui.qs.panels.shared.model.SizedTile +import com.android.systemui.qs.panels.shared.model.SizedTileImpl +import com.android.systemui.qs.panels.ui.compose.DragAndDropState +import com.android.systemui.qs.panels.ui.compose.EditTileListState +import com.android.systemui.qs.panels.ui.compose.dragAndDropRemoveZone +import com.android.systemui.qs.panels.ui.compose.dragAndDropTileList +import com.android.systemui.qs.panels.ui.compose.dragAndDropTileSource +import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.InactiveCornerRadius +import com.android.systemui.qs.panels.ui.model.GridCell +import com.android.systemui.qs.panels.ui.model.SpacerGridCell +import com.android.systemui.qs.panels.ui.model.TileGridCell +import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel +import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor +import com.android.systemui.qs.pipeline.shared.TileSpec +import com.android.systemui.qs.shared.model.groupAndSort +import com.android.systemui.res.R + +object TileType + +@Composable +fun DefaultEditTileGrid( + currentListState: EditTileListState, + otherTiles: List<SizedTile<EditTileViewModel>>, + columns: Int, + modifier: Modifier, + onAddTile: (TileSpec, Int) -> Unit, + onRemoveTile: (TileSpec) -> Unit, + onSetTiles: (List<TileSpec>) -> Unit, + onResize: (TileSpec) -> Unit, +) { + val addTileToEnd: (TileSpec) -> Unit by rememberUpdatedState { + onAddTile(it, CurrentTilesInteractor.POSITION_AT_END) + } + + CompositionLocalProvider(LocalOverscrollConfiguration provides null) { + Column( + verticalArrangement = + spacedBy(dimensionResource(id = R.dimen.qs_label_container_margin)), + modifier = modifier.fillMaxSize().verticalScroll(rememberScrollState()), + ) { + AnimatedContent( + targetState = currentListState.dragInProgress, + modifier = Modifier.wrapContentSize(), + label = "", + ) { dragIsInProgress -> + EditGridHeader(Modifier.dragAndDropRemoveZone(currentListState, onRemoveTile)) { + if (dragIsInProgress) { + RemoveTileTarget() + } else { + Text(text = "Hold and drag to rearrange tiles.") + } + } + } + + CurrentTilesGrid(currentListState, columns, onRemoveTile, onResize, onSetTiles) + + // Hide available tiles when dragging + AnimatedVisibility( + visible = !currentListState.dragInProgress, + enter = fadeIn(), + exit = fadeOut(), + ) { + Column( + verticalArrangement = + spacedBy(dimensionResource(id = R.dimen.qs_label_container_margin)), + modifier = modifier.fillMaxSize(), + ) { + EditGridHeader { Text(text = "Hold and drag to add tiles.") } + + AvailableTileGrid(otherTiles, columns, addTileToEnd, currentListState) + } + } + + // Drop zone to remove tiles dragged out of the tile grid + Spacer( + modifier = + Modifier.fillMaxWidth() + .weight(1f) + .dragAndDropRemoveZone(currentListState, onRemoveTile) + ) + } + } +} + +@Composable +private fun EditGridHeader( + modifier: Modifier = Modifier, + content: @Composable BoxScope.() -> Unit, +) { + CompositionLocalProvider( + LocalContentColor provides MaterialTheme.colorScheme.onBackground.copy(alpha = .5f) + ) { + Box( + contentAlignment = Alignment.Center, + modifier = modifier.fillMaxWidth().height(EditModeTileDefaults.EditGridHeaderHeight), + ) { + content() + } + } +} + +@Composable +private fun RemoveTileTarget() { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = tileHorizontalArrangement(), + modifier = + Modifier.fillMaxHeight() + .border(1.dp, LocalContentColor.current, shape = CircleShape) + .padding(10.dp), + ) { + Icon(imageVector = Icons.Default.Clear, contentDescription = null) + Text(text = "Remove") + } +} + +@Composable +private fun CurrentTilesContainer(content: @Composable () -> Unit) { + Box( + Modifier.fillMaxWidth() + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.onBackground.copy(alpha = .5f), + shape = RoundedCornerShape(48.dp), + ) + .padding(dimensionResource(R.dimen.qs_tile_margin_vertical)) + ) { + content() + } +} + +@Composable +private fun CurrentTilesGrid( + listState: EditTileListState, + columns: Int, + onClick: (TileSpec) -> Unit, + onResize: (TileSpec) -> Unit, + onSetTiles: (List<TileSpec>) -> Unit, +) { + val currentListState by rememberUpdatedState(listState) + val tilePadding = CommonTileDefaults.TileArrangementPadding + + CurrentTilesContainer { + val tileHeight = CommonTileDefaults.TileHeight + val totalRows = listState.tiles.lastOrNull()?.row ?: 0 + val totalHeight = gridHeight(totalRows + 1, tileHeight, tilePadding) + val gridState = rememberLazyGridState() + var gridContentOffset by remember { mutableStateOf(Offset(0f, 0f)) } + + TileLazyGrid( + state = gridState, + modifier = + Modifier.height(totalHeight) + .dragAndDropTileList(gridState, gridContentOffset, listState) { + onSetTiles(currentListState.tileSpecs()) + } + .onGloballyPositioned { coordinates -> + gridContentOffset = coordinates.positionInRoot() + } + .testTag(CURRENT_TILES_GRID_TEST_TAG), + columns = GridCells.Fixed(columns), + ) { + EditTiles(listState.tiles, onClick, listState, onResize = onResize) + } + } +} + +@Composable +private fun AvailableTileGrid( + tiles: List<SizedTile<EditTileViewModel>>, + columns: Int, + onClick: (TileSpec) -> Unit, + dragAndDropState: DragAndDropState, +) { + // Available tiles aren't visible during drag and drop, so the row isn't needed + val groupedTiles = + remember(tiles.fastMap { it.tile.category }, tiles.fastMap { it.tile.label }) { + groupAndSort(tiles.fastMap { TileGridCell(it, 0) }) + } + val labelColors = EditModeTileDefaults.editTileColors() + + // Available tiles + Column( + verticalArrangement = spacedBy(CommonTileDefaults.TileArrangementPadding), + horizontalAlignment = Alignment.Start, + modifier = + Modifier.fillMaxWidth().wrapContentHeight().testTag(AVAILABLE_TILES_GRID_TEST_TAG), + ) { + groupedTiles.forEach { (category, tiles) -> + Text( + text = category.label.load() ?: "", + fontSize = 20.sp, + color = labelColors.label, + modifier = + Modifier.fillMaxWidth() + .background(Color.Black) + .padding(start = 16.dp, bottom = 8.dp, top = 8.dp), + ) + tiles.chunked(columns).forEach { row -> + Row( + horizontalArrangement = spacedBy(CommonTileDefaults.TileArrangementPadding), + modifier = Modifier.fillMaxWidth().height(IntrinsicSize.Max), + ) { + row.forEachIndexed { index, tileGridCell -> + AvailableTileGridCell( + cell = tileGridCell, + index = index, + dragAndDropState = dragAndDropState, + onClick = onClick, + modifier = Modifier.weight(1f).fillMaxHeight(), + ) + } + + // Spacers for incomplete rows + repeat(columns - row.size) { Spacer(modifier = Modifier.weight(1f)) } + } + } + } + } +} + +fun gridHeight(rows: Int, tileHeight: Dp, padding: Dp): Dp { + return ((tileHeight + padding) * rows) - padding +} + +private fun GridCell.key(index: Int, dragAndDropState: DragAndDropState): Any { + return when (this) { + is TileGridCell -> { + if (dragAndDropState.isMoving(tile.tileSpec)) index else key + } + is SpacerGridCell -> index + } +} + +fun LazyGridScope.EditTiles( + cells: List<GridCell>, + onClick: (TileSpec) -> Unit, + dragAndDropState: DragAndDropState, + onResize: (TileSpec) -> Unit = {}, +) { + items( + count = cells.size, + key = { cells[it].key(it, dragAndDropState) }, + span = { cells[it].span }, + contentType = { TileType }, + ) { index -> + when (val cell = cells[index]) { + is TileGridCell -> + if (dragAndDropState.isMoving(cell.tile.tileSpec)) { + // If the tile is being moved, replace it with a visible spacer + SpacerGridCell( + Modifier.background( + color = MaterialTheme.colorScheme.secondary, + alpha = { EditModeTileDefaults.PLACEHOLDER_ALPHA }, + shape = RoundedCornerShape(InactiveCornerRadius), + ) + .animateItem() + ) + } else { + TileGridCell( + cell = cell, + index = index, + dragAndDropState = dragAndDropState, + onClick = onClick, + onResize = onResize, + ) + } + is SpacerGridCell -> SpacerGridCell() + } + } +} + +@Composable +private fun LazyGridItemScope.TileGridCell( + cell: TileGridCell, + index: Int, + dragAndDropState: DragAndDropState, + onClick: (TileSpec) -> Unit, + onResize: (TileSpec) -> Unit = {}, +) { + val onClickActionName = stringResource(id = R.string.accessibility_qs_edit_remove_tile_action) + val stateDescription = stringResource(id = R.string.accessibility_qs_edit_position, index + 1) + + EditTile( + tileViewModel = cell.tile, + iconOnly = cell.isIcon, + modifier = + Modifier.animateItem() + .semantics(mergeDescendants = true) { + onClick(onClickActionName) { false } + this.stateDescription = stateDescription + } + .dragAndDropTileSource( + SizedTileImpl(cell.tile, cell.width), + dragAndDropState, + onClick, + onResize, + ), + ) +} + +@Composable +private fun AvailableTileGridCell( + cell: TileGridCell, + index: Int, + dragAndDropState: DragAndDropState, + modifier: Modifier = Modifier, + onClick: (TileSpec) -> Unit, +) { + val onClickActionName = stringResource(id = R.string.accessibility_qs_edit_tile_add_action) + val stateDescription = stringResource(id = R.string.accessibility_qs_edit_position, index + 1) + val colors = EditModeTileDefaults.editTileColors() + + // Displays the tile as an icon tile with the label underneath + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = spacedBy(CommonTileDefaults.TilePadding, Alignment.Top), + modifier = modifier, + ) { + EditTile( + tileViewModel = cell.tile, + iconOnly = true, + colors = colors, + modifier = + Modifier.semantics(mergeDescendants = true) { + onClick(onClickActionName) { false } + this.stateDescription = stateDescription + } + .dragAndDropTileSource( + SizedTileImpl(cell.tile, cell.width), + dragAndDropState, + onTap = onClick, + ), + ) + Box(Modifier.fillMaxSize()) { + Text( + cell.tile.label.text, + maxLines = 2, + color = colors.label, + overflow = TextOverflow.Ellipsis, + textAlign = TextAlign.Center, + modifier = Modifier.align(Alignment.Center), + ) + } + } +} + +@Composable +private fun SpacerGridCell(modifier: Modifier = Modifier) { + // By default, spacers are invisible and exist purely to catch drag movements + Box(modifier.height(CommonTileDefaults.TileHeight).fillMaxWidth().tilePadding()) +} + +@Composable +fun EditTile( + tileViewModel: EditTileViewModel, + iconOnly: Boolean, + modifier: Modifier = Modifier, + colors: TileColors = EditModeTileDefaults.editTileColors(), +) { + EditTileContainer(colors = colors, modifier = modifier) { + if (iconOnly) { + SmallTileContent( + icon = tileViewModel.icon, + color = colors.icon, + modifier = Modifier.align(Alignment.Center), + ) + } else { + LargeTileContent( + label = tileViewModel.label.text, + secondaryLabel = tileViewModel.appName?.text, + icon = tileViewModel.icon, + colors = colors, + ) + } + } +} + +@Composable +private fun EditTileContainer( + colors: TileColors, + modifier: Modifier = Modifier, + content: @Composable BoxScope.() -> Unit, +) { + Box( + modifier = + modifier + .height(CommonTileDefaults.TileHeight) + .fillMaxWidth() + .drawBehind { + drawRoundRect( + SolidColor(colors.background), + cornerRadius = CornerRadius(InactiveCornerRadius.toPx()), + ) + } + .tilePadding(), + content = content, + ) +} + +private object EditModeTileDefaults { + const val PLACEHOLDER_ALPHA = .3f + val EditGridHeaderHeight = 60.dp + + @Composable + fun editTileColors(): TileColors = + TileColors( + background = MaterialTheme.colorScheme.surfaceVariant, + iconBackground = MaterialTheme.colorScheme.surfaceVariant, + label = MaterialTheme.colorScheme.onSurfaceVariant, + secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, + icon = MaterialTheme.colorScheme.onSurfaceVariant, + ) +} + +private const val CURRENT_TILES_GRID_TEST_TAG = "CurrentTilesGrid" +private const val AVAILABLE_TILES_GRID_TEST_TAG = "AvailableTilesGrid" diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt index c75b601ab4a8..f96c27dc3ef6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/InfiniteGridLayout.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.qs.panels.ui.compose +package com.android.systemui.qs.panels.ui.compose.infinitegrid import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridItemSpan @@ -26,6 +26,8 @@ import androidx.compose.ui.Modifier import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.systemui.dagger.SysUISingleton import com.android.systemui.qs.panels.shared.model.SizedTileImpl +import com.android.systemui.qs.panels.ui.compose.PaginatableGridLayout +import com.android.systemui.qs.panels.ui.compose.rememberEditListState import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel import com.android.systemui.qs.panels.ui.viewmodel.FixedColumnsSizeViewModel import com.android.systemui.qs.panels.ui.viewmodel.IconTilesViewModel @@ -61,7 +63,7 @@ constructor( Tile( tile = sizedTiles[index].tile, iconOnly = iconTilesViewModel.isIconTile(sizedTiles[index].tile.spec), - modifier = Modifier + modifier = Modifier, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt new file mode 100644 index 000000000000..45aad825a70f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt @@ -0,0 +1,330 @@ +/* + * 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(ExperimentalFoundationApi::class) + +package com.android.systemui.qs.panels.ui.compose.infinitegrid + +import android.content.res.Resources +import android.service.quicksettings.Tile.STATE_ACTIVE +import android.service.quicksettings.Tile.STATE_INACTIVE +import androidx.compose.animation.core.animateDpAsState +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.basicMarquee +import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Arrangement.spacedBy +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyGridScope +import androidx.compose.foundation.lazy.grid.LazyGridState +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.rememberLazyGridState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.stateDescription +import androidx.compose.ui.semantics.toggleableState +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.android.compose.animation.Expandable +import com.android.compose.modifiers.thenIf +import com.android.systemui.animation.Expandable +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.compose.modifiers.sysuiResTag +import com.android.systemui.plugins.qs.QSTile +import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.InactiveCornerRadius +import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.longPressLabel +import com.android.systemui.qs.panels.ui.viewmodel.TileUiState +import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel +import com.android.systemui.qs.panels.ui.viewmodel.toUiState +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.res.R +import java.util.function.Supplier + +private const val TEST_TAG_SMALL = "qs_tile_small" +private const val TEST_TAG_LARGE = "qs_tile_large" + +@Composable +fun TileLazyGrid( + columns: GridCells, + modifier: Modifier = Modifier, + state: LazyGridState = rememberLazyGridState(), + content: LazyGridScope.() -> Unit, +) { + LazyVerticalGrid( + state = state, + columns = columns, + verticalArrangement = spacedBy(CommonTileDefaults.TileArrangementPadding), + horizontalArrangement = spacedBy(CommonTileDefaults.TileArrangementPadding), + modifier = modifier, + content = content, + ) +} + +@Composable +fun Tile(tile: TileViewModel, iconOnly: Boolean, modifier: Modifier) { + val state by tile.state.collectAsStateWithLifecycle(tile.currentState) + val resources = resources() + val uiState = remember(state, resources) { state.toUiState(resources) } + val colors = TileDefaults.getColorForState(uiState) + + // TODO(b/361789146): Draw the shapes instead of clipping + val tileShape = TileDefaults.animateTileShape(uiState.state) + + TileContainer( + color = + if (iconOnly || !uiState.handlesSecondaryClick) { + colors.iconBackground + } else { + colors.background + }, + shape = tileShape, + iconOnly = iconOnly, + onClick = tile::onClick, + onLongClick = tile::onLongClick, + uiState = uiState, + modifier = modifier, + ) { expandable -> + val icon = getTileIcon(icon = uiState.icon) + if (iconOnly) { + SmallTileContent( + icon = icon, + color = colors.icon, + modifier = Modifier.align(Alignment.Center), + ) + } else { + val iconShape = TileDefaults.animateIconShape(uiState.state) + LargeTileContent( + label = uiState.label, + secondaryLabel = uiState.secondaryLabel, + icon = icon, + colors = colors, + iconShape = iconShape, + toggleClickSupported = state.handlesSecondaryClick, + onClick = { + if (state.handlesSecondaryClick) { + tile.onSecondaryClick() + } + }, + onLongClick = { tile.onLongClick(expandable) }, + accessibilityUiState = uiState.accessibilityUiState, + ) + } + } +} + +@Composable +private fun TileContainer( + color: Color, + shape: Shape, + iconOnly: Boolean, + uiState: TileUiState, + modifier: Modifier = Modifier, + onClick: (Expandable) -> Unit = {}, + onLongClick: (Expandable) -> Unit = {}, + content: @Composable BoxScope.(Expandable) -> Unit, +) { + Expandable(color = color, shape = shape, modifier = modifier.clip(shape)) { + val longPressLabel = longPressLabel() + Box( + modifier = + Modifier.height(CommonTileDefaults.TileHeight) + .fillMaxWidth() + .combinedClickable( + onClick = { onClick(it) }, + onLongClick = { onLongClick(it) }, + onClickLabel = uiState.accessibilityUiState.clickLabel, + onLongClickLabel = longPressLabel, + ) + .semantics { + role = uiState.accessibilityUiState.accessibilityRole + if (uiState.accessibilityUiState.accessibilityRole == Role.Switch) { + uiState.accessibilityUiState.toggleableState?.let { + toggleableState = it + } + } + stateDescription = uiState.accessibilityUiState.stateDescription + } + .sysuiResTag(if (iconOnly) TEST_TAG_SMALL else TEST_TAG_LARGE) + .thenIf(iconOnly) { + Modifier.semantics { + contentDescription = uiState.accessibilityUiState.contentDescription + } + } + .tilePadding() + ) { + content(it) + } + } +} + +@Composable +private fun getTileIcon(icon: Supplier<QSTile.Icon?>): Icon { + val context = LocalContext.current + return icon.get()?.let { + if (it is QSTileImpl.ResourceIcon) { + Icon.Resource(it.resId, null) + } else { + Icon.Loaded(it.getDrawable(context), null) + } + } ?: Icon.Resource(R.drawable.ic_error_outline, null) +} + +fun tileHorizontalArrangement(): Arrangement.Horizontal { + return spacedBy(space = CommonTileDefaults.TileArrangementPadding, alignment = Alignment.Start) +} + +fun Modifier.tileMarquee(): Modifier { + return basicMarquee(iterations = 1, initialDelayMillis = 200) +} + +fun Modifier.tilePadding(): Modifier { + return padding(CommonTileDefaults.TilePadding) +} + +data class TileColors( + val background: Color, + val iconBackground: Color, + val label: Color, + val secondaryLabel: Color, + val icon: Color, +) + +private object TileDefaults { + val ActiveIconCornerRadius = 16.dp + val ActiveTileCornerRadius = 24.dp + + /** An active tile without dual target uses the active color as background */ + @Composable + fun activeTileColors(): TileColors = + TileColors( + background = MaterialTheme.colorScheme.primary, + iconBackground = MaterialTheme.colorScheme.primary, + label = MaterialTheme.colorScheme.onPrimary, + secondaryLabel = MaterialTheme.colorScheme.onPrimary, + icon = MaterialTheme.colorScheme.onPrimary, + ) + + /** An active tile with dual target only show the active color on the icon */ + @Composable + fun activeDualTargetTileColors(): TileColors = + TileColors( + background = MaterialTheme.colorScheme.surfaceVariant, + iconBackground = MaterialTheme.colorScheme.primary, + label = MaterialTheme.colorScheme.onSurfaceVariant, + secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, + icon = MaterialTheme.colorScheme.onPrimary, + ) + + @Composable + fun inactiveTileColors(): TileColors = + TileColors( + background = MaterialTheme.colorScheme.surfaceVariant, + iconBackground = MaterialTheme.colorScheme.surfaceVariant, + label = MaterialTheme.colorScheme.onSurfaceVariant, + secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, + icon = MaterialTheme.colorScheme.onSurfaceVariant, + ) + + @Composable + fun unavailableTileColors(): TileColors = + TileColors( + background = MaterialTheme.colorScheme.surface, + iconBackground = MaterialTheme.colorScheme.surface, + label = MaterialTheme.colorScheme.onSurface, + secondaryLabel = MaterialTheme.colorScheme.onSurface, + icon = MaterialTheme.colorScheme.onSurface, + ) + + @Composable + fun getColorForState(uiState: TileUiState): TileColors { + return when (uiState.state) { + STATE_ACTIVE -> { + if (uiState.handlesSecondaryClick) { + activeDualTargetTileColors() + } else { + activeTileColors() + } + } + STATE_INACTIVE -> inactiveTileColors() + else -> unavailableTileColors() + } + } + + @Composable + fun animateIconShape(state: Int): Shape { + return animateShape( + state = state, + activeCornerRadius = ActiveIconCornerRadius, + label = "QSTileCornerRadius", + ) + } + + @Composable + fun animateTileShape(state: Int): Shape { + return animateShape( + state = state, + activeCornerRadius = ActiveTileCornerRadius, + label = "QSTileIconCornerRadius", + ) + } + + @Composable + fun animateShape(state: Int, activeCornerRadius: Dp, label: String): Shape { + val animatedCornerRadius by + animateDpAsState( + targetValue = + if (state == STATE_ACTIVE) { + activeCornerRadius + } else { + InactiveCornerRadius + }, + label = label, + ) + return RoundedCornerShape(animatedCornerRadius) + } +} + +/** + * A composable function that returns the [Resources]. It will be recomposed when [Configuration] + * gets updated. + */ +@Composable +@ReadOnlyComposable +private fun resources(): Resources { + LocalConfiguration.current + return LocalContext.current.resources +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/model/TileGridCell.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/model/TileGridCell.kt index 08ee856a0ec6..b16a7075607f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/model/TileGridCell.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/model/TileGridCell.kt @@ -24,7 +24,7 @@ import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel import com.android.systemui.qs.shared.model.CategoryAndName /** Represents an item from a grid associated with a row and a span */ -interface GridCell { +sealed interface GridCell { val row: Int val span: GridItemSpan } @@ -38,30 +38,26 @@ data class TileGridCell( override val tile: EditTileViewModel, override val row: Int, override val width: Int, - override val span: GridItemSpan = GridItemSpan(width) + override val span: GridItemSpan = GridItemSpan(width), ) : GridCell, SizedTile<EditTileViewModel>, CategoryAndName by tile { val key: String = "${tile.tileSpec.spec}-$row" constructor( sizedTile: SizedTile<EditTileViewModel>, - row: Int - ) : this( - tile = sizedTile.tile, - row = row, - width = sizedTile.width, - ) + row: Int, + ) : this(tile = sizedTile.tile, row = row, width = sizedTile.width) } /** Represents an empty space used to fill incomplete rows. Will always display as a 1x1 tile */ @Immutable data class SpacerGridCell( override val row: Int, - override val span: GridItemSpan = GridItemSpan(1) + override val span: GridItemSpan = GridItemSpan(1), ) : GridCell fun List<SizedTile<EditTileViewModel>>.toGridCells( columns: Int, - includeSpacers: Boolean = false + includeSpacers: Boolean = false, ): List<GridCell> { return splitInRowsSequence(this, columns) .flatMapIndexed { rowIndex, sizedTiles -> diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/startable/QSPipelineCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/startable/QSPipelineCoreStartable.kt index 0bcb6b7e7874..9677d47b38e8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/startable/QSPipelineCoreStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/startable/QSPipelineCoreStartable.kt @@ -18,8 +18,6 @@ package com.android.systemui.qs.pipeline.domain.startable import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.qs.flags.NewQsUI -import com.android.systemui.qs.panels.domain.interactor.GridConsistencyInteractor import com.android.systemui.qs.pipeline.domain.interactor.AccessibilityTilesInteractor import com.android.systemui.qs.pipeline.domain.interactor.AutoAddInteractor import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor @@ -36,16 +34,11 @@ constructor( private val autoAddInteractor: AutoAddInteractor, private val featureFlags: QSPipelineFlagsRepository, private val restoreReconciliationInteractor: RestoreReconciliationInteractor, - private val gridConsistencyInteractor: GridConsistencyInteractor, ) : CoreStartable { override fun start() { accessibilityTilesInteractor.init(currentTilesInteractor) autoAddInteractor.init(currentTilesInteractor) restoreReconciliationInteractor.start() - - if (NewQsUI.isEnabled) { - gridConsistencyInteractor.start() - } } } 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 b927134842df..a4fe4e3e1243 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -49,7 +49,7 @@ import com.android.systemui.animation.DialogTransitionAnimator; import com.android.systemui.animation.Expandable; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.flags.RefactorFlagUtils; +import com.android.systemui.modes.shared.ModesUi; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; @@ -108,8 +108,7 @@ public class DndTile extends QSTileImpl<BooleanState> { statusBarStateController, activityStarter, qsLogger); // If the flag is on, this shouldn't run at all since the modes tile replaces the DND tile. - RefactorFlagUtils.INSTANCE.assertInLegacyMode(android.app.Flags.modesUi(), - android.app.Flags.FLAG_MODES_UI); + ModesUi.assertInLegacyMode(); mController = zenModeController; mSharedPreferences = sharedPreferences; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt index 7d23fbdf2ece..cf2db6c66ce7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt @@ -16,7 +16,6 @@ package com.android.systemui.qs.tiles -import android.app.Flags import android.content.Intent import android.os.Handler import android.os.Looper @@ -30,7 +29,8 @@ import com.android.internal.logging.MetricsLogger import com.android.systemui.animation.Expandable import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.flags.RefactorFlagUtils.isUnexpectedlyInLegacyMode +import com.android.systemui.modes.shared.ModesUi +import com.android.systemui.modes.shared.ModesUiIcons import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.qs.QSTile @@ -77,14 +77,14 @@ constructor( metricsLogger, statusBarStateController, activityStarter, - qsLogger + qsLogger, ) { private lateinit var tileState: QSTileState private val config = qsTileConfigProvider.getConfig(TILE_SPEC) init { - /* Check if */ isUnexpectedlyInLegacyMode(Flags.modesUi(), Flags.FLAG_MODES_UI) + /* Check if */ ModesUiIcons.isUnexpectedlyInLegacyMode() lifecycle.coroutineScope.launch { lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) { @@ -93,7 +93,7 @@ constructor( } } - override fun isAvailable(): Boolean = Flags.modesUi() + override fun isAvailable(): Boolean = ModesUi.isEnabled override fun getTileLabel(): CharSequence = tileState.label diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt index 483373d8fb6d..5d44ead7c21a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt @@ -16,13 +16,14 @@ package com.android.systemui.qs.tiles.impl.modes.domain.interactor -import android.app.Flags import android.content.Context import android.os.UserHandle import com.android.app.tracing.coroutines.flow.map import com.android.systemui.common.shared.model.Icon import com.android.systemui.common.shared.model.asIcon import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.modes.shared.ModesUi +import com.android.systemui.modes.shared.ModesUiIcons import com.android.systemui.qs.tiles.ModesTile import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor @@ -47,7 +48,7 @@ constructor( override fun tileData( user: UserHandle, - triggers: Flow<DataUpdateTrigger> + triggers: Flow<DataUpdateTrigger>, ): Flow<ModesTileModel> = tileData() /** @@ -64,20 +65,20 @@ constructor( suspend fun getCurrentTileModel() = buildTileData(zenModeInteractor.getActiveModes()) private fun buildTileData(activeModes: ActiveZenModes): ModesTileModel { - if (usesModeIcons()) { + if (ModesUiIcons.isEnabled) { val tileIcon = getTileIcon(activeModes.mainMode) return ModesTileModel( isActivated = activeModes.isAnyActive(), icon = tileIcon.icon, iconResId = tileIcon.resId, - activeModes = activeModes.modeNames + activeModes = activeModes.modeNames, ) } else { return ModesTileModel( isActivated = activeModes.isAnyActive(), icon = context.getDrawable(ModesTile.ICON_RES_ID)!!.asIcon(), iconResId = ModesTile.ICON_RES_ID, - activeModes = activeModes.modeNames + activeModes = activeModes.modeNames, ) } } @@ -97,7 +98,5 @@ constructor( } } - override fun availability(user: UserHandle): Flow<Boolean> = flowOf(Flags.modesUi()) - - private fun usesModeIcons() = Flags.modesApi() && Flags.modesUi() && Flags.modesUiIcons() + override fun availability(user: UserHandle): Flow<Boolean> = flowOf(ModesUi.isEnabled) } diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt index e11ffccb0be3..b7e2cf23e3a8 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt @@ -61,6 +61,7 @@ import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.session.shared.SessionStorage import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.logger.SceneLogger +import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.statusbar.NotificationShadeWindowController @@ -228,8 +229,10 @@ constructor( is ObservableTransitionState.Idle -> { if (state.currentScene != Scenes.Gone) { true to "scene is not Gone" + } else if (state.currentOverlays.isNotEmpty()) { + true to "overlay is shown" } else { - false to "scene is Gone" + false to "scene is Gone and no overlays are shown" } } is ObservableTransitionState.Transition -> { @@ -712,19 +715,21 @@ constructor( if (isDeviceLocked) { sceneInteractor.transitionState .mapNotNull { it as? ObservableTransitionState.Idle } - .map { it.currentScene } + .map { it.currentScene to it.currentOverlays } .distinctUntilChanged() - .map { sceneKey -> - when (sceneKey) { + .map { (sceneKey, currentOverlays) -> + when { // When locked, showing the lockscreen scene should be reported // as "interacting" while showing other scenes should report as // "not interacting". // // This is done here in order to match the legacy // implementation. The real reason why is lost to lore and myth. - Scenes.Lockscreen -> true - Scenes.Bouncer -> false - Scenes.Shade -> false + Overlays.NotificationsShade in currentOverlays -> false + Overlays.QuickSettingsShade in currentOverlays -> null + sceneKey == Scenes.Lockscreen -> true + sceneKey == Scenes.Bouncer -> false + sceneKey == Scenes.Shade -> false else -> null } } diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt index 751448fe607e..7b6b0f614cc2 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt @@ -26,7 +26,6 @@ import com.android.systemui.flags.RefactorFlagUtils import com.android.systemui.keyguard.KeyguardBottomAreaRefactor import com.android.systemui.keyguard.KeyguardWmStateRefactor import com.android.systemui.keyguard.MigrateClocksToBlueprint -import com.android.systemui.keyguard.shared.ComposeLockscreen import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun import com.android.systemui.statusbar.phone.PredictiveBackSysUiFlag @@ -39,7 +38,6 @@ object SceneContainerFlag { inline val isEnabled get() = sceneContainer() && // mainAconfigFlag - ComposeLockscreen.isEnabled && KeyguardBottomAreaRefactor.isEnabled && KeyguardWmStateRefactor.isEnabled && MigrateClocksToBlueprint.isEnabled && @@ -55,7 +53,6 @@ object SceneContainerFlag { /** The set of secondary flags which must be enabled for scene container to work properly */ inline fun getSecondaryFlags(): Sequence<FlagToken> = sequenceOf( - ComposeLockscreen.token, KeyguardBottomAreaRefactor.token, KeyguardWmStateRefactor.token, MigrateClocksToBlueprint.token, diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index 42499f043457..f76c5fd4ca83 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -137,7 +137,6 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver; -import com.android.systemui.keyguard.shared.ComposeLockscreen; import com.android.systemui.keyguard.shared.model.Edge; import com.android.systemui.keyguard.shared.model.TransitionState; import com.android.systemui.keyguard.shared.model.TransitionStep; @@ -186,6 +185,7 @@ import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.notification.AnimatableProperty; import com.android.systemui.statusbar.notification.ConversationNotificationManager; import com.android.systemui.statusbar.notification.DynamicPrivacyController; +import com.android.systemui.statusbar.notification.HeadsUpTouchHelper; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.PropertyAnimator; import com.android.systemui.statusbar.notification.ViewGroupFadeHelper; @@ -207,7 +207,6 @@ import com.android.systemui.statusbar.phone.BounceInterpolator; import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; -import com.android.systemui.statusbar.notification.HeadsUpTouchHelper; import com.android.systemui.statusbar.phone.KeyguardBottomAreaView; import com.android.systemui.statusbar.phone.KeyguardBottomAreaViewController; import com.android.systemui.statusbar.phone.KeyguardBypassController; @@ -2511,11 +2510,6 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump return 0; } - if (ComposeLockscreen.isEnabled()) { - return (int) mKeyguardInteractor.getNotificationContainerBounds() - .getValue().getTop(); - } - if (!mKeyguardBypassController.getBypassEnabled()) { if (MigrateClocksToBlueprint.isEnabled() && !mSplitShadeEnabled) { return (int) mKeyguardInteractor.getNotificationContainerBounds() diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java index 3f3ad13f9b12..4f47536f6b32 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java @@ -28,6 +28,7 @@ import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.PixelFormat; +import android.graphics.Rect; import android.graphics.Region; import android.os.Binder; import android.os.Build; @@ -987,6 +988,19 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW @Override public void onConfigChanged(Configuration newConfig) { + // If the shade window is not visible, the bounds will not update until it becomes visible. + // Touches that should invoke shade expansion but are not within those incorrect bounds + // (because the shape of the shade window remains portrait after flipping to landscape) will + // be dropped, causing the shade expansion to fail silently. Since the shade doesn't open, + // it doesn't become visible, and the bounds will never update. Therefore, we must detect + // the incorrect bounds here and force the update so that touches are routed correctly. + if (SceneContainerFlag.isEnabled() && mWindowRootView.getVisibility() == View.INVISIBLE) { + Rect bounds = newConfig.windowConfiguration.getBounds(); + if (mWindowRootView.getWidth() != bounds.width()) { + mLogger.logConfigChangeWidthAdjust(mWindowRootView.getWidth(), bounds.width()); + updateRootViewBounds(bounds); + } + } final boolean newScreenRotationAllowed = mKeyguardStateController .isKeyguardScreenRotationAllowed(); @@ -996,6 +1010,16 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } } + private void updateRootViewBounds(Rect bounds) { + int originalMlpWidth = mLp.width; + int originalMlpHeight = mLp.height; + mLp.width = bounds.width(); + mLp.height = bounds.height(); + mWindowManager.updateViewLayout(mWindowRootView, mLp); + mLp.width = originalMlpWidth; + mLp.height = originalMlpHeight; + } + /** * When keyguard will be dismissed but didn't start animation yet. */ diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt index e7a397b0fa09..1693e62c89fb 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt @@ -31,18 +31,13 @@ class ShadeWindowLogger @Inject constructor(@ShadeWindowLog private val buffer: ConstantStringsLogger by ConstantStringsLoggerImpl(buffer, TAG) { fun logNewState(state: Any) { - buffer.log( - TAG, - DEBUG, - { str1 = state.toString() }, - { "Applying new state: $str1" } - ) + buffer.log(TAG, DEBUG, { str1 = state.toString() }, { "Applying new state: $str1" }) } private inline fun log( logLevel: LogLevel, initializer: LogMessage.() -> Unit, - noinline printer: LogMessage.() -> String + noinline printer: LogMessage.() -> String, ) { buffer.log(TAG, logLevel, initializer, printer) } @@ -52,7 +47,8 @@ class ShadeWindowLogger @Inject constructor(@ShadeWindowLog private val buffer: TAG, DEBUG, { bool1 = visible }, - { "Updating visibility, should be visible : $bool1" }) + { "Updating visibility, should be visible : $bool1" }, + ) } fun logIsExpanded( @@ -65,7 +61,7 @@ class ShadeWindowLogger @Inject constructor(@ShadeWindowLog private val buffer: headsUpNotificationShowing: Boolean, scrimsVisibilityNotTransparent: Boolean, backgroundBlurRadius: Boolean, - launchingActivityFromNotification: Boolean + launchingActivityFromNotification: Boolean, ) { buffer.log( TAG, @@ -82,11 +78,13 @@ class ShadeWindowLogger @Inject constructor(@ShadeWindowLog private val buffer: long2 = if (backgroundBlurRadius) 1 else 0 double1 = if (launchingActivityFromNotification) 1.0 else 0.0 }, - { "Setting isExpanded to $str1: forceWindowCollapsed $bool1, " + + { + "Setting isExpanded to $str1: forceWindowCollapsed $bool1, " + "isKeyguardShowingAndNotOccluded $bool2, panelVisible $bool3, " + "keyguardFadingAway $bool4, bouncerShowing $int1," + "headsUpNotificationShowing $int2, scrimsVisibilityNotTransparent $long1," + - "backgroundBlurRadius $long2, launchingActivityFromNotification $double1"} + "backgroundBlurRadius $long2, launchingActivityFromNotification $double1" + }, ) } @@ -95,7 +93,7 @@ class ShadeWindowLogger @Inject constructor(@ShadeWindowLog private val buffer: TAG, DEBUG, { bool1 = visible }, - { "Updating shade, should be visible and focusable: $bool1" } + { "Updating shade, should be visible and focusable: $bool1" }, ) } @@ -104,7 +102,19 @@ class ShadeWindowLogger @Inject constructor(@ShadeWindowLog private val buffer: TAG, DEBUG, { bool1 = focusable }, - { "Updating shade, should be focusable : $bool1" } + { "Updating shade, should be focusable : $bool1" }, + ) + } + + fun logConfigChangeWidthAdjust(originalWidth: Int, newWidth: Int) { + buffer.log( + TAG, + DEBUG, + { + int1 = originalWidth + int2 = newWidth + }, + { "Config changed. SceneWindowRootView width updating from $int1 to $int2." }, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 87f360eb9712..ad3afd4d1756 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -61,6 +61,7 @@ import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.statusbar.StatusBarIcon.Shape; import com.android.internal.util.ContrastColorUtil; import com.android.systemui.Flags; +import com.android.systemui.modes.shared.ModesUiIcons; import com.android.systemui.res.R; import com.android.systemui.statusbar.notification.NotificationContentDescription; import com.android.systemui.statusbar.notification.NotificationDozeHelper; @@ -215,7 +216,7 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi // We scale notification icons (on the left) plus icons on the right that explicitly // want FIXED_SPACE. boolean useNonSystemIconScaling = isNotification() - || (usesModeIcons() && mIcon != null && mIcon.shape == Shape.FIXED_SPACE); + || (ModesUiIcons.isEnabled() && mIcon != null && mIcon.shape == Shape.FIXED_SPACE); if (useNonSystemIconScaling) { updateIconScaleForNonSystemIcons(); @@ -415,7 +416,7 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi if (!levelEquals) { setImageLevel(icon.iconLevel); } - if (usesModeIcons() && icon.shape == Shape.FIXED_SPACE) { + if (ModesUiIcons.isEnabled() && icon.shape == Shape.FIXED_SPACE) { setScaleType(ScaleType.FIT_CENTER); } if (!visibilityEquals) { @@ -506,7 +507,7 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi @Nullable private Drawable loadDrawable(Context context, StatusBarIcon statusBarIcon) { - if (usesModeIcons() && statusBarIcon.preloadedIcon != null) { + if (ModesUiIcons.isEnabled() && statusBarIcon.preloadedIcon != null) { Drawable.ConstantState cached = statusBarIcon.preloadedIcon.getConstantState(); if (cached != null) { return cached.newDrawable(mContext.getResources()).mutate(); @@ -1041,9 +1042,4 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi public boolean showsConversation() { return mShowsConversation; } - - private static boolean usesModeIcons() { - return android.app.Flags.modesApi() && android.app.Flags.modesUi() - && android.app.Flags.modesUiIcons(); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt index 4056e7b89c2c..975b92e632b8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt @@ -16,11 +16,12 @@ package com.android.systemui.statusbar.core import android.app.Fragment -import com.android.systemui.res.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.fragments.FragmentHostManager +import com.android.systemui.res.R +import com.android.systemui.statusbar.core.StatusBarInitializer.OnStatusBarViewInitializedListener +import com.android.systemui.statusbar.core.StatusBarInitializer.OnStatusBarViewUpdatedListener import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions -import com.android.systemui.statusbar.phone.PhoneStatusBarView import com.android.systemui.statusbar.phone.PhoneStatusBarViewController import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent @@ -33,50 +34,16 @@ import javax.inject.Provider * Responsible for creating the status bar window and initializing the root components of that * window (see [CollapsedStatusBarFragment]) */ -@SysUISingleton -class StatusBarInitializer @Inject constructor( - private val windowController: StatusBarWindowController, - private val collapsedStatusBarFragmentProvider: Provider<CollapsedStatusBarFragment>, - private val creationListeners: Set<@JvmSuppressWildcards OnStatusBarViewInitializedListener>, -) { +interface StatusBarInitializer { - var statusBarViewUpdatedListener: OnStatusBarViewUpdatedListener? = null + var statusBarViewUpdatedListener: OnStatusBarViewUpdatedListener? /** * Creates the status bar window and root views, and initializes the component. * * TODO(b/277764509): Initialize the status bar via [CoreStartable#start]. */ - fun initializeStatusBar() { - windowController.fragmentHostManager.addTagListener( - CollapsedStatusBarFragment.TAG, - object : FragmentHostManager.FragmentListener { - override fun onFragmentViewCreated(tag: String, fragment: Fragment) { - val statusBarFragmentComponent = (fragment as CollapsedStatusBarFragment) - .statusBarFragmentComponent ?: throw IllegalStateException() - statusBarViewUpdatedListener?.onStatusBarViewUpdated( - statusBarFragmentComponent.phoneStatusBarView, - statusBarFragmentComponent.phoneStatusBarViewController, - statusBarFragmentComponent.phoneStatusBarTransitions - ) - creationListeners.forEach { listener -> - listener.onStatusBarViewInitialized(statusBarFragmentComponent) - } - } - - override fun onFragmentViewDestroyed(tag: String?, fragment: Fragment?) { - // nop - } - } - ).fragmentManager - .beginTransaction() - .replace( - R.id.status_bar_container, - collapsedStatusBarFragmentProvider.get(), - CollapsedStatusBarFragment.TAG - ) - .commit() - } + fun initializeStatusBar() interface OnStatusBarViewInitializedListener { @@ -84,16 +51,61 @@ class StatusBarInitializer @Inject constructor( * The status bar view has been initialized. * * @param component Dagger component that is created when the status bar view is created. - * Can be used to retrieve dependencies from that scope, including the status bar root view. + * Can be used to retrieve dependencies from that scope, including the status bar root + * view. */ fun onStatusBarViewInitialized(component: StatusBarFragmentComponent) } interface OnStatusBarViewUpdatedListener { fun onStatusBarViewUpdated( - statusBarView: PhoneStatusBarView, statusBarViewController: PhoneStatusBarViewController, - statusBarTransitions: PhoneStatusBarTransitions + statusBarTransitions: PhoneStatusBarTransitions, ) } } + +@SysUISingleton +class StatusBarInitializerImpl +@Inject +constructor( + private val windowController: StatusBarWindowController, + private val collapsedStatusBarFragmentProvider: Provider<CollapsedStatusBarFragment>, + private val creationListeners: Set<@JvmSuppressWildcards OnStatusBarViewInitializedListener>, +) : StatusBarInitializer { + + override var statusBarViewUpdatedListener: OnStatusBarViewUpdatedListener? = null + + override fun initializeStatusBar() { + windowController.fragmentHostManager + .addTagListener( + CollapsedStatusBarFragment.TAG, + object : FragmentHostManager.FragmentListener { + override fun onFragmentViewCreated(tag: String, fragment: Fragment) { + val statusBarFragmentComponent = + (fragment as CollapsedStatusBarFragment).statusBarFragmentComponent + ?: throw IllegalStateException() + statusBarViewUpdatedListener?.onStatusBarViewUpdated( + statusBarFragmentComponent.phoneStatusBarViewController, + statusBarFragmentComponent.phoneStatusBarTransitions, + ) + creationListeners.forEach { listener -> + listener.onStatusBarViewInitialized(statusBarFragmentComponent) + } + } + + override fun onFragmentViewDestroyed(tag: String?, fragment: Fragment?) { + // nop + } + }, + ) + .fragmentManager + .beginTransaction() + .replace( + R.id.status_bar_container, + collapsedStatusBarFragmentProvider.get(), + CollapsedStatusBarFragment.TAG, + ) + .commit() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/ComposeLockscreen.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarSimpleFragment.kt index 601fbfaf1b64..214151383dc6 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/ComposeLockscreen.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarSimpleFragment.kt @@ -14,17 +14,16 @@ * limitations under the License. */ -package com.android.systemui.keyguard.shared +package com.android.systemui.statusbar.core import com.android.systemui.Flags import com.android.systemui.flags.FlagToken import com.android.systemui.flags.RefactorFlagUtils -/** Helper for reading or using the compose lockscreen flag state. */ -@Suppress("NOTHING_TO_INLINE") -object ComposeLockscreen { - /** The aconfig flag name */ - const val FLAG_NAME = Flags.FLAG_COMPOSE_LOCKSCREEN +/** Helper for reading and using the status bar simple fragment flag state */ +object StatusBarSimpleFragment { + /** Aconfig flag for removing the fragment */ + const val FLAG_NAME = Flags.FLAG_STATUS_BAR_SIMPLE_FRAGMENT /** A token used for dependency declaration */ val token: FlagToken @@ -33,7 +32,7 @@ object ComposeLockscreen { /** Is the refactor enabled */ @JvmStatic inline val isEnabled - get() = Flags.composeLockscreen() + get() = Flags.statusBarSimpleFragment() /** * Called to ensure code is only run when the flag is enabled. This protects users from the @@ -46,6 +45,14 @@ object ComposeLockscreen { /** * Called to ensure code is only run when the flag is disabled. This will throw an exception if + * the flag is not enabled to ensure that the refactor author catches issues in testing. + * Caution!! Using this check incorrectly will cause crashes in nextfood builds! + */ + @JvmStatic + inline fun assertInNewMode() = RefactorFlagUtils.assertInNewMode(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 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt index 406a66449f82..526c64c15696 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt @@ -20,12 +20,16 @@ import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogBufferFactory +import com.android.systemui.statusbar.core.StatusBarInitializer +import com.android.systemui.statusbar.core.StatusBarInitializerImpl import com.android.systemui.statusbar.data.StatusBarDataLayerModule import com.android.systemui.statusbar.phone.LightBarController import com.android.systemui.statusbar.phone.StatusBarSignalPolicy import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLog import com.android.systemui.statusbar.ui.SystemBarUtilsProxyImpl +import com.android.systemui.statusbar.window.StatusBarWindowController +import com.android.systemui.statusbar.window.StatusBarWindowControllerImpl import dagger.Binds import dagger.Module import dagger.Provides @@ -57,6 +61,13 @@ abstract class StatusBarModule { @ClassKey(StatusBarSignalPolicy::class) abstract fun bindStatusBarSignalPolicy(impl: StatusBarSignalPolicy): CoreStartable + @Binds abstract fun statusBarInitializer(impl: StatusBarInitializerImpl): StatusBarInitializer + + @Binds + abstract fun statusBarWindowController( + impl: StatusBarWindowControllerImpl + ): StatusBarWindowController + companion object { @Provides @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/RemoteInputRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/RemoteInputRepository.kt index c0302bc348b6..9af4b8c18c86 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/RemoteInputRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/RemoteInputRepository.kt @@ -25,6 +25,7 @@ import dagger.Module import javax.inject.Inject import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow /** * Repository used for tracking the state of notification remote input (e.g. when the user presses @@ -33,14 +34,21 @@ import kotlinx.coroutines.flow.Flow interface RemoteInputRepository { /** Whether remote input is currently active for any notification. */ val isRemoteInputActive: Flow<Boolean> + + /** + * The bottom bound of the currently focused remote input notification row, or null if there + * isn't one. + */ + val remoteInputRowBottomBound: Flow<Float?> + + fun setRemoteInputRowBottomBound(bottom: Float?) } @SysUISingleton class RemoteInputRepositoryImpl @Inject -constructor( - private val notificationRemoteInputManager: NotificationRemoteInputManager, -) : RemoteInputRepository { +constructor(private val notificationRemoteInputManager: NotificationRemoteInputManager) : + RemoteInputRepository { override val isRemoteInputActive: Flow<Boolean> = conflatedCallbackFlow { trySend(false) // initial value is false val callback = @@ -52,6 +60,12 @@ constructor( notificationRemoteInputManager.addControllerCallback(callback) awaitClose { notificationRemoteInputManager.removeControllerCallback(callback) } } + + override val remoteInputRowBottomBound = MutableStateFlow<Float?>(null) + + override fun setRemoteInputRowBottomBound(bottom: Float?) { + remoteInputRowBottomBound.value = bottom + } } @Module diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractor.kt index 68f727b046c0..b83b0cc8d2c9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractor.kt @@ -20,13 +20,24 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.data.repository.RemoteInputRepository import javax.inject.Inject import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.mapNotNull /** * Interactor used for business logic pertaining to the notification remote input (e.g. when the * user presses "reply" on a notification and the keyboard opens). */ @SysUISingleton -class RemoteInputInteractor @Inject constructor(remoteInputRepository: RemoteInputRepository) { +class RemoteInputInteractor +@Inject +constructor(private val remoteInputRepository: RemoteInputRepository) { /** Is remote input currently active for a notification? */ val isRemoteInputActive: Flow<Boolean> = remoteInputRepository.isRemoteInputActive + + /** The bottom bound of the currently focused remote input notification row. */ + val remoteInputRowBottomBound: Flow<Float> = + remoteInputRepository.remoteInputRowBottomBound.mapNotNull { it } + + fun setRemoteInputRowBottomBound(bottom: Float?) { + remoteInputRepository.setRemoteInputRowBottomBound(bottom) + } } 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 cb3e26b9f8ea..5003a6af5c4c 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 @@ -21,6 +21,7 @@ import static android.service.notification.NotificationListenerService.REASON_CA import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.PARENT_DISMISSED; import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP; +import static com.android.systemui.statusbar.policy.RemoteInputView.FOCUS_ANIMATION_MIN_SCALE; import static com.android.systemui.util.ColorUtilKt.hexColorString; import android.animation.Animator; @@ -83,6 +84,7 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.res.R; +import com.android.systemui.scene.shared.flag.SceneContainerFlag; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.StatusBarIconView; @@ -118,6 +120,7 @@ import com.android.systemui.statusbar.phone.ExpandHeadsUpOnInlineReply; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.InflatedSmartReplyState; +import com.android.systemui.statusbar.policy.RemoteInputView; import com.android.systemui.statusbar.policy.SmartReplyConstants; import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent; import com.android.systemui.util.Compile; @@ -830,6 +833,20 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mPrivateLayout.setRemoteInputController(r); } + /** + * Return the cumulative y-value that the actions container expands via its scale animator when + * remote input is activated. + */ + public float getRemoteInputActionsContainerExpandedOffset() { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return 0f; + RemoteInputView expandedRemoteInput = mPrivateLayout.getExpandedRemoteInput(); + if (expandedRemoteInput == null) return 0f; + View actionsContainerLayout = expandedRemoteInput.getActionsContainerLayout(); + if (actionsContainerLayout == null) return 0f; + + return actionsContainerLayout.getHeight() * (1 - FOCUS_ANIMATION_MIN_SCALE) * 0.5f; + } + public void addChildNotification(ExpandableNotificationRow row) { addChildNotification(row, -1); } 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 7543f3b48e48..e7c67f93eb78 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 @@ -99,6 +99,7 @@ import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.ColorUpdateLogger; import com.android.systemui.statusbar.notification.FakeShadowView; +import com.android.systemui.statusbar.notification.HeadsUpTouchHelper; import com.android.systemui.statusbar.notification.LaunchAnimationParameters; import com.android.systemui.statusbar.notification.NotificationTransitionAnimatorController; import com.android.systemui.statusbar.notification.NotificationUtils; @@ -120,7 +121,6 @@ import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrim import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape; import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView; import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; -import com.android.systemui.statusbar.notification.HeadsUpTouchHelper; import com.android.systemui.statusbar.phone.ScreenOffAnimationController; import com.android.systemui.statusbar.policy.HeadsUpUtil; import com.android.systemui.statusbar.policy.ScrollAdapter; @@ -740,6 +740,15 @@ public class NotificationStackScrollLayout updateFooter(); } + void sendRemoteInputRowBottomBound(Float bottom) { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return; + if (bottom != null) { + bottom += getResources().getDimensionPixelSize( + com.android.internal.R.dimen.notification_content_margin); + } + mScrollViewFields.sendRemoteInputRowBottomBound(bottom); + } + /** Setter for filtered notifs, to be removed with the FooterViewRefactor flag. */ public void setHasFilteredOutSeenNotifications(boolean hasFilteredOutSeenNotifications) { FooterViewRefactor.assertInLegacyMode(); @@ -1274,6 +1283,11 @@ public class NotificationStackScrollLayout } @Override + public void setRemoteInputRowBottomBoundConsumer(@Nullable Consumer<Float> consumer) { + mScrollViewFields.setRemoteInputRowBottomBoundConsumer(consumer); + } + + @Override public void setHeadsUpHeightConsumer(@Nullable Consumer<Float> consumer) { mScrollViewFields.setHeadsUpHeightConsumer(consumer); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index e5f63c1cb480..dad6894a43ce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -98,6 +98,9 @@ import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.ColorUpdateLogger; import com.android.systemui.statusbar.notification.DynamicPrivacyController; +import com.android.systemui.statusbar.notification.HeadsUpNotificationViewControllerEmptyImpl; +import com.android.systemui.statusbar.notification.HeadsUpTouchHelper; +import com.android.systemui.statusbar.notification.HeadsUpTouchHelper.HeadsUpNotificationViewController; import com.android.systemui.statusbar.notification.LaunchAnimationParameters; import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; @@ -129,9 +132,6 @@ import com.android.systemui.statusbar.notification.row.NotificationSnooze; import com.android.systemui.statusbar.notification.shared.GroupHunAnimationFix; import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationListViewBinder; import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; -import com.android.systemui.statusbar.notification.HeadsUpNotificationViewControllerEmptyImpl; -import com.android.systemui.statusbar.notification.HeadsUpTouchHelper; -import com.android.systemui.statusbar.notification.HeadsUpTouchHelper.HeadsUpNotificationViewController; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; @@ -1605,6 +1605,9 @@ public class NotificationStackScrollLayoutController implements Dumpable { return new RemoteInputController.Delegate() { public void setRemoteInputActive(NotificationEntry entry, boolean remoteInputActive) { + if (SceneContainerFlag.isEnabled()) { + sendRemoteInputRowBottomBound(entry, remoteInputActive); + } mHeadsUpManager.setRemoteInputActive(entry, remoteInputActive); entry.notifyHeightChanged(true /* needsAnimation */); if (!FooterViewRefactor.isEnabled()) { @@ -1620,6 +1623,15 @@ public class NotificationStackScrollLayoutController implements Dumpable { mView.requestDisallowLongPress(); mView.requestDisallowDismiss(); } + + private void sendRemoteInputRowBottomBound(NotificationEntry entry, + boolean remoteInputActive) { + ExpandableNotificationRow row = entry.getRow(); + float top = row.getTranslationY(); + int height = row.getActualHeight(); + float bottom = top + height + row.getRemoteInputActionsContainerExpandedOffset(); + mView.sendRemoteInputRowBottomBound(remoteInputActive ? bottom : null); + } }; } 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 aa3953987c10..c08ed6120832 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 @@ -57,6 +57,13 @@ class ScrollViewFields { * guts off of this gesture, we can notify the placeholder through here. */ var currentGestureInGutsConsumer: Consumer<Boolean>? = null + + /** + * When a notification begins remote input, its bottom Y bound is sent to the placeholder + * through here in order to adjust to accommodate the IME. + */ + var remoteInputRowBottomBoundConsumer: Consumer<Float?>? = null + /** * Any time the heads up height is recalculated, it should be updated here to be used by the * placeholder @@ -75,6 +82,10 @@ class ScrollViewFields { fun sendCurrentGestureInGuts(isCurrentGestureInGuts: Boolean) = currentGestureInGutsConsumer?.accept(isCurrentGestureInGuts) + /** send [bottomY] to the [remoteInputRowBottomBoundConsumer], if present. */ + fun sendRemoteInputRowBottomBound(bottomY: Float?) = + remoteInputRowBottomBoundConsumer?.accept(bottomY) + /** send the [headsUpHeight] to the [headsUpHeightConsumer], if present. */ fun sendHeadsUpHeight(headsUpHeight: Float) = headsUpHeightConsumer?.accept(headsUpHeight) 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 235b4da3f029..41c02934efa6 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 @@ -74,6 +74,9 @@ interface NotificationScrollView { /** Set a consumer for current gesture in guts events */ fun setCurrentGestureInGutsConsumer(consumer: Consumer<Boolean>?) + /** 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>?) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt index 6d5553fec6b4..2e37dead8787 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt @@ -108,10 +108,14 @@ constructor( view.setSyntheticScrollConsumer(viewModel.syntheticScrollConsumer) view.setCurrentGestureOverscrollConsumer(viewModel.currentGestureOverscrollConsumer) view.setCurrentGestureInGutsConsumer(viewModel.currentGestureInGutsConsumer) + view.setRemoteInputRowBottomBoundConsumer( + viewModel.remoteInputRowBottomBoundConsumer + ) DisposableHandle { view.setSyntheticScrollConsumer(null) view.setCurrentGestureOverscrollConsumer(null) view.setCurrentGestureInGutsConsumer(null) + view.setRemoteInputRowBottomBoundConsumer(null) } } } 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 8d7007b2fba4..5b2e02d446cf 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 @@ -31,6 +31,7 @@ import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.shade.shared.model.ShadeMode +import com.android.systemui.statusbar.domain.interactor.RemoteInputInteractor import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimClipping import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape @@ -56,6 +57,7 @@ constructor( dumpManager: DumpManager, stackAppearanceInteractor: NotificationStackAppearanceInteractor, shadeInteractor: ShadeInteractor, + private val remoteInputInteractor: RemoteInputInteractor, private val sceneInteractor: SceneInteractor, // TODO(b/336364825) Remove Lazy when SceneContainerFlag is released - // while the flag is off, creating this object too early results in a crash @@ -240,6 +242,10 @@ constructor( val currentGestureInGutsConsumer: (Boolean) -> Unit = stackAppearanceInteractor::setCurrentGestureInGuts + /** Receives the bottom bound of the currently focused remote input notification row. */ + val remoteInputRowBottomBoundConsumer: (Float?) -> Unit = + remoteInputInteractor::setRemoteInputRowBottomBound + /** Whether the notification stack is scrollable or not. */ val isScrollable: Flow<Boolean> = combine(sceneInteractor.currentScene, sceneInteractor.currentOverlays) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt index 69c1bf3b61b7..c8e83581e831 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt @@ -24,6 +24,7 @@ import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.domain.interactor.ShadeInteractor +import com.android.systemui.statusbar.domain.interactor.RemoteInputInteractor import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds @@ -49,6 +50,7 @@ constructor( private val sceneInteractor: SceneInteractor, private val shadeInteractor: ShadeInteractor, private val headsUpNotificationInteractor: HeadsUpNotificationInteractor, + remoteInputInteractor: RemoteInputInteractor, featureFlags: FeatureFlagsClassic, dumpManager: DumpManager, ) : @@ -132,6 +134,12 @@ constructor( val isCurrentGestureOverscroll: Flow<Boolean> = interactor.isCurrentGestureOverscroll.dumpWhileCollecting("isCurrentGestureOverScroll") + /** Whether remote input is currently active for any notification. */ + val isRemoteInputActive = remoteInputInteractor.isRemoteInputActive + + /** The bottom bound of the currently focused remote input notification row. */ + val remoteInputRowBottomBound = remoteInputInteractor.remoteInputRowBottomBound + /** Sets whether the notification stack is scrolled to the top. */ fun setScrolledToTop(scrolledToTop: Boolean) { interactor.setScrolledToTop(scrolledToTop) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 50e92498b114..59533b343a57 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -372,7 +372,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { private final Point mCurrentDisplaySize = new Point(); - protected PhoneStatusBarView mStatusBarView; private PhoneStatusBarViewController mPhoneStatusBarViewController; private PhoneStatusBarTransitions mStatusBarTransitions; private final AuthRippleController mAuthRippleController; @@ -1191,8 +1190,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { // Set up CollapsedStatusBarFragment and PhoneStatusBarView mStatusBarInitializer.setStatusBarViewUpdatedListener( - (statusBarView, statusBarViewController, statusBarTransitions) -> { - mStatusBarView = statusBarView; + (statusBarViewController, statusBarTransitions) -> { mPhoneStatusBarViewController = statusBarViewController; mStatusBarTransitions = statusBarTransitions; getNotificationShadeWindowViewController() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index ba39c3bb4124..8c0353813ec6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -51,6 +51,7 @@ import com.android.systemui.dagger.qualifiers.DisplayId; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor; +import com.android.systemui.modes.shared.ModesUiIcons; import com.android.systemui.privacy.PrivacyItem; import com.android.systemui.privacy.PrivacyItemController; import com.android.systemui.privacy.PrivacyType; @@ -360,7 +361,7 @@ public class PhoneStatusBarPolicy mBluetooth.addCallback(this); mProvisionedController.addCallback(this); mCurrentUserSetup = mProvisionedController.isCurrentUserSetup(); - if (usesModeIcons()) { + if (ModesUiIcons.isEnabled()) { // Note that we're not fully replacing ZenModeController with ZenModeInteractor, so // we listen for the extra event here but still add the ZMC callback. mJavaAdapter.alwaysCollectFlow(mZenModeInteractor.getMainActiveMode(), @@ -397,8 +398,7 @@ public class PhoneStatusBarPolicy } private void onMainActiveModeChanged(@Nullable ZenModeInfo mainActiveMode) { - if (!usesModeIcons()) { - Log.wtf(TAG, "onMainActiveModeChanged shouldn't run if MODES_UI_ICONS is disabled"); + if (ModesUiIcons.isUnexpectedlyInLegacyMode()) { return; } @@ -458,14 +458,14 @@ public class PhoneStatusBarPolicy private void updateVolumeZen() { int zen = mZenController.getZen(); - if (!usesModeIcons()) { + if (!ModesUiIcons.isEnabled()) { updateZenIcon(zen); } updateRingerAndAlarmIcons(zen); } private void updateZenIcon(int zen) { - if (usesModeIcons()) { + if (ModesUiIcons.isEnabled()) { Log.wtf(TAG, "updateZenIcon shouldn't be called if MODES_UI_ICONS is enabled"); return; } @@ -942,9 +942,4 @@ public class PhoneStatusBarPolicy mIconController.setIconVisibility(mSlotConnectedDisplay, visible); } - - private static boolean usesModeIcons() { - return android.app.Flags.modesApi() && android.app.Flags.modesUi() - && android.app.Flags.modesUiIcons(); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java index c0e36b2ab42a..f026b99af49c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java @@ -27,7 +27,6 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions; import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.phone.PhoneStatusBarViewController; import com.android.systemui.statusbar.phone.StatusBarLocation; -import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer; import com.android.systemui.statusbar.policy.Clock; import com.android.systemui.statusbar.window.StatusBarWindowController; @@ -114,14 +113,6 @@ public interface StatusBarFragmentModule { /** */ @Provides @StatusBarFragmentScope - static StatusBarUserSwitcherContainer provideStatusBarUserSwitcherContainer( - @RootView PhoneStatusBarView view) { - return view.findViewById(R.id.user_switcher_container); - } - - /** */ - @Provides - @StatusBarFragmentScope static PhoneStatusBarViewController providePhoneStatusBarViewController( PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory, @RootView PhoneStatusBarView phoneStatusBarView) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/IconManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/IconManager.java index 91ead614ffa4..fd16c6090cb1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/IconManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/IconManager.java @@ -20,7 +20,6 @@ import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_BIND import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON; import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE_NEW; import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI_NEW; -import static com.android.systemui.statusbar.phone.ui.StatusBarIconControllerImpl.usesModeIcons; import android.annotation.Nullable; import android.content.Context; @@ -31,6 +30,7 @@ import android.widget.LinearLayout; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.statusbar.StatusBarIcon.Shape; import com.android.systemui.demomode.DemoModeCommandReceiver; +import com.android.systemui.modes.shared.ModesUiIcons; import com.android.systemui.statusbar.BaseStatusBarFrameLayout; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.StatusIconDisplayable; @@ -233,7 +233,7 @@ public class IconManager implements DemoModeCommandReceiver { } protected LinearLayout.LayoutParams onCreateLayoutParams(Shape shape) { - int width = usesModeIcons() && shape == StatusBarIcon.Shape.FIXED_SPACE + int width = ModesUiIcons.isEnabled() && shape == StatusBarIcon.Shape.FIXED_SPACE ? mIconSize : ViewGroup.LayoutParams.WRAP_CONTENT; @@ -259,7 +259,7 @@ public class IconManager implements DemoModeCommandReceiver { /** Called once an icon has been set. */ public void onSetIcon(int viewIndex, StatusBarIcon icon) { StatusBarIconView view = (StatusBarIconView) mGroup.getChildAt(viewIndex); - if (usesModeIcons()) { + if (ModesUiIcons.isEnabled()) { ViewGroup.LayoutParams current = view.getLayoutParams(); ViewGroup.LayoutParams desired = onCreateLayoutParams(icon.shape); if (desired.width != current.width || desired.height != current.height) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java index 9b6d32bd179d..e66e8138102e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java @@ -42,6 +42,7 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.demomode.DemoMode; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; +import com.android.systemui.modes.shared.ModesUiIcons; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.StatusIconDisplayable; import com.android.systemui.statusbar.phone.StatusBarIconHolder; @@ -242,10 +243,7 @@ public class StatusBarIconControllerImpl implements Tunable, public void setResourceIcon(String slot, @Nullable String resPackage, @DrawableRes int iconResId, @Nullable Drawable preloadedIcon, CharSequence contentDescription, StatusBarIcon.Shape shape) { - if (!usesModeIcons()) { - Log.wtf("TAG", - "StatusBarIconController.setResourceIcon() should not be called without " - + "MODES_UI & MODES_UI_ICONS!"); + if (ModesUiIcons.isUnexpectedlyInLegacyMode()) { // Fall back to old implementation, although it will not load the icon if it's from a // different package. setIcon(slot, iconResId, contentDescription); @@ -580,9 +578,4 @@ public class StatusBarIconControllerImpl implements Tunable, return slot + EXTERNAL_SLOT_SUFFIX; } } - - static boolean usesModeIcons() { - return android.app.Flags.modesApi() && android.app.Flags.modesUi() - && android.app.Flags.modesUiIcons(); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt index cf9f9f4a2a81..3cb7090ea6d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt @@ -21,6 +21,7 @@ import android.os.UserManager.DISALLOW_CONFIG_LOCATION import android.os.UserManager.DISALLOW_MICROPHONE_TOGGLE import android.os.UserManager.DISALLOW_SHARE_LOCATION import com.android.systemui.Flags +import com.android.systemui.modes.shared.ModesUi import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.pipeline.shared.TileSpec import com.android.systemui.qs.shared.model.TileCategory @@ -142,7 +143,7 @@ interface PolicyModule { dndTile: Provider<DndTile>, modesTile: Provider<ModesTile>, ): QSTileImpl<*> { - return if (android.app.Flags.modesUi()) modesTile.get() else dndTile.get() + return if (ModesUi.isEnabled) modesTile.get() else dndTile.get() } /** Inject flashlight config */ @@ -169,7 +170,7 @@ interface PolicyModule { factory: QSTileViewModelFactory.Static<FlashlightTileModel>, mapper: FlashlightMapper, stateInteractor: FlashlightTileDataInteractor, - userActionInteractor: FlashlightTileUserActionInteractor + userActionInteractor: FlashlightTileUserActionInteractor, ): QSTileViewModel = factory.create( TileSpec.create(FLASHLIGHT_TILE_SPEC), @@ -206,7 +207,7 @@ interface PolicyModule { factory: QSTileViewModelFactory.Static<LocationTileModel>, mapper: LocationTileMapper, stateInteractor: LocationTileDataInteractor, - userActionInteractor: LocationTileUserActionInteractor + userActionInteractor: LocationTileUserActionInteractor, ): QSTileViewModel = factory.create( TileSpec.create(LOCATION_TILE_SPEC), @@ -239,7 +240,7 @@ interface PolicyModule { factory: QSTileViewModelFactory.Static<AlarmTileModel>, mapper: AlarmTileMapper, stateInteractor: AlarmTileDataInteractor, - userActionInteractor: AlarmTileUserActionInteractor + userActionInteractor: AlarmTileUserActionInteractor, ): QSTileViewModel = factory.create( TileSpec.create(ALARM_TILE_SPEC), @@ -272,7 +273,7 @@ interface PolicyModule { factory: QSTileViewModelFactory.Static<UiModeNightTileModel>, mapper: UiModeNightTileMapper, stateInteractor: UiModeNightTileDataInteractor, - userActionInteractor: UiModeNightTileUserActionInteractor + userActionInteractor: UiModeNightTileUserActionInteractor, ): QSTileViewModel = factory.create( TileSpec.create(UIMODENIGHT_TILE_SPEC), @@ -306,7 +307,7 @@ interface PolicyModule { factory: QSTileViewModelFactory.Static<WorkModeTileModel>, mapper: WorkModeTileMapper, stateInteractor: WorkModeTileDataInteractor, - userActionInteractor: WorkModeTileUserActionInteractor + userActionInteractor: WorkModeTileUserActionInteractor, ): QSTileViewModel = factory.create( TileSpec.create(WORK_MODE_TILE_SPEC), @@ -406,7 +407,7 @@ interface PolicyModule { @IntoMap @StringKey(DND_TILE_SPEC) fun provideDndOrModesTileConfig(uiEventLogger: QsEventLogger): QSTileConfig = - if (android.app.Flags.modesUi()) { + if (ModesUi.isEnabled) { QSTileConfig( tileSpec = TileSpec.create(DND_TILE_SPEC), uiConfig = @@ -438,9 +439,9 @@ interface PolicyModule { factory: QSTileViewModelFactory.Static<ModesTileModel>, mapper: ModesTileMapper, stateInteractor: ModesTileDataInteractor, - userActionInteractor: ModesTileUserActionInteractor + userActionInteractor: ModesTileUserActionInteractor, ): QSTileViewModel = - if (android.app.Flags.modesUi() && Flags.qsNewTilesFuture()) + if (ModesUi.isEnabled && Flags.qsNewTilesFuture()) factory.create( TileSpec.create(DND_TILE_SPEC), userActionInteractor, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java index 31776cf5ad1b..16d5f8d30593 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -106,7 +106,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene private static final long FOCUS_ANIMATION_CROSSFADE_DURATION = 50; private static final long FOCUS_ANIMATION_FADE_IN_DELAY = 33; private static final long FOCUS_ANIMATION_FADE_IN_DURATION = 83; - private static final float FOCUS_ANIMATION_MIN_SCALE = 0.5f; + public static final float FOCUS_ANIMATION_MIN_SCALE = 0.5f; private static final long DEFOCUS_ANIMATION_FADE_OUT_DELAY = 120; private static final long DEFOCUS_ANIMATION_CROSSFADE_DELAY = 180; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt index dbeaa59cd219..ba45942177a2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt @@ -27,7 +27,10 @@ import com.android.settingslib.notification.modes.ZenIcon import com.android.settingslib.notification.modes.ZenIconLoader import com.android.settingslib.notification.modes.ZenMode import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.modes.shared.ModesUi import com.android.systemui.shared.notifications.data.repository.NotificationSettingsRepository +import com.android.systemui.statusbar.policy.data.repository.DeviceProvisioningRepository +import com.android.systemui.statusbar.policy.data.repository.UserSetupRepository import com.android.systemui.statusbar.policy.domain.model.ActiveZenModes import com.android.systemui.statusbar.policy.domain.model.ZenModeInfo import java.time.Duration @@ -51,7 +54,17 @@ constructor( private val notificationSettingsRepository: NotificationSettingsRepository, @Background private val bgDispatcher: CoroutineDispatcher, private val iconLoader: ZenIconLoader, + private val deviceProvisioningRepository: DeviceProvisioningRepository, + private val userSetupRepository: UserSetupRepository, ) { + val isZenAvailable: Flow<Boolean> = + combine( + deviceProvisioningRepository.isDeviceProvisioned, + userSetupRepository.isUserSetUp, + ) { isDeviceProvisioned, isUserSetUp -> + isDeviceProvisioned && isUserSetUp + } + val isZenModeEnabled: Flow<Boolean> = zenModeRepository.globalZenMode .map { @@ -80,6 +93,18 @@ constructor( val modes: Flow<List<ZenMode>> = zenModeRepository.modes + /** + * Returns the special "manual DND" mode. + * + * This is only meant as a temporary solution for "legacy" UI pieces that handle DND + * specifically; any new or migrated features should use modes more generally, through [modes] + * or [activeModes]. + */ + val dndMode: Flow<ZenMode?> by lazy { + ModesUi.assertInNewMode() + zenModeRepository.modes.map { modes -> modes.singleOrNull { it.isManualDnd } } + } + /** Flow returning the currently active mode(s), if any. */ val activeModes: Flow<ActiveZenModes> = modes @@ -113,10 +138,11 @@ constructor( Log.e( TAG, "Interactor cannot handle showing the zen duration prompt. " + - "Please use EnableZenModeDialog when this setting is active." + "Please use EnableZenModeDialog when this setting is active.", ) null } + ZEN_DURATION_FOREVER -> null else -> Duration.ofMinutes(zenDuration.toLong()) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt index af93880bad51..27bc6d36c1e6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt @@ -59,32 +59,26 @@ fun ModeTile(viewModel: ModeTileViewModel) { ) CompositionLocalProvider(LocalContentColor provides contentColor) { - Surface( - color = tileColor, - shape = RoundedCornerShape(16.dp), - ) { + Surface(color = tileColor, shape = RoundedCornerShape(16.dp)) { Row( modifier = Modifier.combinedClickable( onClick = viewModel.onClick, onLongClick = viewModel.onLongClick, - onLongClickLabel = viewModel.onLongClickLabel + onLongClickLabel = viewModel.onLongClickLabel, ) - .padding(20.dp) + .padding(16.dp) .semantics { stateDescription = viewModel.stateDescription }, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = - Arrangement.spacedBy( - space = 10.dp, - alignment = Alignment.Start, - ), + Arrangement.spacedBy(space = 8.dp, alignment = Alignment.Start), ) { Icon(icon = viewModel.icon, modifier = Modifier.size(24.dp)) Column { Text( viewModel.text, fontWeight = FontWeight.W500, - modifier = Modifier.tileMarquee().testTag("name") + modifier = Modifier.tileMarquee().testTag("name"), ) Text( viewModel.subtext, @@ -94,7 +88,7 @@ fun ModeTile(viewModel: ModeTileViewModel) { .testTag(if (viewModel.enabled) "stateOn" else "stateOff") .clearAndSetSemantics { contentDescription = viewModel.subtextDescription - } + }, ) } } @@ -103,8 +97,5 @@ fun ModeTile(viewModel: ModeTileViewModel) { } private fun Modifier.tileMarquee(): Modifier { - return this.basicMarquee( - iterations = 1, - initialDelayMillis = 200, - ) + return this.basicMarquee(iterations = 1) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTileGrid.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTileGrid.kt index 73d361f69eac..5953ea598929 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTileGrid.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTileGrid.kt @@ -19,7 +19,6 @@ package com.android.systemui.statusbar.policy.ui.dialog.composable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.runtime.Composable @@ -27,23 +26,20 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.android.systemui.Flags import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.ModesDialogViewModel @Composable fun ModeTileGrid(viewModel: ModesDialogViewModel) { val tiles by viewModel.tiles.collectAsStateWithLifecycle(initialValue = emptyList()) - // TODO(b/346519570): Handle what happens when we have more than a few modes. LazyVerticalGrid( - columns = GridCells.Fixed(2), - modifier = Modifier.padding(8.dp).fillMaxWidth().heightIn(max = 300.dp), + columns = GridCells.Fixed(if (Flags.modesDialogSingleRows()) 1 else 2), + modifier = Modifier.fillMaxWidth().heightIn(max = 300.dp), verticalArrangement = Arrangement.spacedBy(8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), ) { - items( - tiles.size, - key = { index -> tiles[index].id }, - ) { index -> + items(tiles.size, key = { index -> tiles[index].id }) { index -> ModeTile(viewModel = tiles[index]) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.kt new file mode 100644 index 000000000000..421e5c45bbfe --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.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.statusbar.window + +import android.view.View +import android.view.ViewGroup +import com.android.systemui.animation.ActivityTransitionAnimator +import com.android.systemui.fragments.FragmentHostManager +import java.util.Optional + +/** Encapsulates all logic for the status bar window state management. */ +interface StatusBarWindowController { + val statusBarHeight: Int + + /** Rereads the status bar height and reapplies the current state if the height is different. */ + fun refreshStatusBarHeight() + + /** Adds the status bar view to the window manager. */ + fun attach() + + /** Adds the given view to the status bar window view. */ + fun addViewToWindow(view: View, layoutParams: ViewGroup.LayoutParams) + + /** Returns the status bar window's background view. */ + val backgroundView: View + + /** Returns a fragment host manager for the status bar window view. */ + val fragmentHostManager: FragmentHostManager + + /** + * Provides an updated animation controller if we're animating a view in the status bar. + * + * This is needed because we have to make sure that the status bar window matches the full + * screen during the animation and that we are expanding the view below the other status bar + * text. + * + * @param rootView the root view of the animation + * @param animationController the default animation controller to use + * @return If the animation is on a view in the status bar, returns an Optional containing an + * updated animation controller that handles status-bar-related animation details. Returns an + * empty optional if the animation is *not* on a view in the status bar. + */ + fun wrapAnimationControllerIfInStatusBar( + rootView: View, + animationController: ActivityTransitionAnimator.Controller, + ): Optional<ActivityTransitionAnimator.Controller> + + /** Set force status bar visible. */ + fun setForceStatusBarVisible(forceStatusBarVisible: Boolean) + + /** + * Sets whether an ongoing process requires the status bar to be forced visible. + * + * This method is separate from {@link this#setForceStatusBarVisible} because the ongoing + * process **takes priority**. For example, if {@link this#setForceStatusBarVisible} is set to + * false but this method is set to true, then the status bar **will** be visible. + * + * TODO(b/195839150): We should likely merge this method and {@link + * this#setForceStatusBarVisible} together and use some sort of ranking system instead. + */ + fun setOngoingProcessRequiresStatusBarVisible(visible: Boolean) +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerImpl.java index c30a6b7d0f17..1a0327cdd809 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowControllerImpl.java @@ -46,6 +46,8 @@ import android.view.ViewGroup; import android.view.WindowInsets; import android.view.WindowManager; +import androidx.annotation.NonNull; + import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.internal.policy.SystemBarUtils; import com.android.systemui.animation.ActivityTransitionAnimator; @@ -67,7 +69,7 @@ import javax.inject.Inject; * Encapsulates all logic for the status bar window state management. */ @SysUISingleton -public class StatusBarWindowController { +public class StatusBarWindowControllerImpl implements StatusBarWindowController { private static final String TAG = "StatusBarWindowController"; private static final boolean DEBUG = false; @@ -89,7 +91,7 @@ public class StatusBarWindowController { private final Binder mInsetsSourceOwner = new Binder(); @Inject - public StatusBarWindowController( + public StatusBarWindowControllerImpl( Context context, @StatusBarWindowModule.InternalWindowView StatusBarWindowView statusBarWindowView, ViewCaptureAwareWindowManager viewCaptureAwareWindowManager, @@ -117,14 +119,12 @@ public class StatusBarWindowController { /* attachedViewProvider=*/ () -> mStatusBarWindowView))); } + @Override public int getStatusBarHeight() { return mBarHeight; } - /** - * Rereads the status bar height and reapplys the current state if the height - * is different. - */ + @Override public void refreshStatusBarHeight() { Trace.beginSection("StatusBarWindowController#refreshStatusBarHeight"); try { @@ -141,9 +141,7 @@ public class StatusBarWindowController { } } - /** - * Adds the status bar view to the window manager. - */ + @Override public void attach() { // Now that the status bar window encompasses the sliding panel and its // translucent backdrop, the entire thing is made TRANSLUCENT and is @@ -161,54 +159,47 @@ public class StatusBarWindowController { apply(mCurrentState); } - /** Adds the given view to the status bar window view. */ - public void addViewToWindow(View view, ViewGroup.LayoutParams layoutParams) { + @Override + public void addViewToWindow(@NonNull View view, @NonNull ViewGroup.LayoutParams layoutParams) { mStatusBarWindowView.addView(view, layoutParams); } - /** Returns the status bar window's background view. */ + @NonNull + @Override public View getBackgroundView() { return mStatusBarWindowView.findViewById(R.id.status_bar_container); } - /** Returns a fragment host manager for the status bar window view. */ + @NonNull + @Override public FragmentHostManager getFragmentHostManager() { return mFragmentService.getFragmentHostManager(mStatusBarWindowView); } - /** - * Provides an updated animation controller if we're animating a view in the status bar. - * - * This is needed because we have to make sure that the status bar window matches the full - * screen during the animation and that we are expanding the view below the other status bar - * text. - * - * @param rootView the root view of the animation - * @param animationController the default animation controller to use - * @return If the animation is on a view in the status bar, returns an Optional containing an - * updated animation controller that handles status-bar-related animation details. Returns an - * empty optional if the animation is *not* on a view in the status bar. - */ + @NonNull + @Override public Optional<ActivityTransitionAnimator.Controller> wrapAnimationControllerIfInStatusBar( - View rootView, ActivityTransitionAnimator.Controller animationController) { + @NonNull View rootView, + @NonNull ActivityTransitionAnimator.Controller animationController) { if (rootView != mStatusBarWindowView) { return Optional.empty(); } animationController.setTransitionContainer(mLaunchAnimationContainer); - return Optional.of(new DelegateTransitionAnimatorController(animationController) { - @Override - public void onTransitionAnimationStart(boolean isExpandingFullyAbove) { - getDelegate().onTransitionAnimationStart(isExpandingFullyAbove); - setLaunchAnimationRunning(true); - } - - @Override - public void onTransitionAnimationEnd(boolean isExpandingFullyAbove) { - getDelegate().onTransitionAnimationEnd(isExpandingFullyAbove); - setLaunchAnimationRunning(false); - } - }); + return Optional.of( + new DelegateTransitionAnimatorController(animationController) { + @Override + public void onTransitionAnimationStart(boolean isExpandingFullyAbove) { + getDelegate().onTransitionAnimationStart(isExpandingFullyAbove); + setLaunchAnimationRunning(true); + } + + @Override + public void onTransitionAnimationEnd(boolean isExpandingFullyAbove) { + getDelegate().onTransitionAnimationEnd(isExpandingFullyAbove); + setLaunchAnimationRunning(false); + } + }); } private WindowManager.LayoutParams getBarLayoutParams(int rotation) { @@ -275,22 +266,13 @@ public class StatusBarWindowController { } } - /** Set force status bar visible. */ + @Override public void setForceStatusBarVisible(boolean forceStatusBarVisible) { mCurrentState.mForceStatusBarVisible = forceStatusBarVisible; apply(mCurrentState); } - /** - * Sets whether an ongoing process requires the status bar to be forced visible. - * - * This method is separate from {@link this#setForceStatusBarVisible} because the ongoing - * process **takes priority**. For example, if {@link this#setForceStatusBarVisible} is set to - * false but this method is set to true, then the status bar **will** be visible. - * - * TODO(b/195839150): We should likely merge this method and - * {@link this#setForceStatusBarVisible} together and use some sort of ranking system instead. - */ + @Override public void setOngoingProcessRequiresStatusBarVisible(boolean visible) { mCurrentState.mOngoingProcessRequiresStatusBarVisible = visible; apply(mCurrentState); diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/domain/interactor/TouchpadGesturesInteractor.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/domain/interactor/TouchpadGesturesInteractor.kt index 1a41987a8e5b..80ea925eabc7 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/domain/interactor/TouchpadGesturesInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/domain/interactor/TouchpadGesturesInteractor.kt @@ -30,12 +30,12 @@ class TouchpadGesturesInteractor( private val logger: InputDeviceTutorialLogger, ) { fun disableGestures() { - logger.log("Disabling touchpad gestures across the system") + logger.d("Disabling touchpad gestures across the system") setGesturesState(disabled = true) } fun enableGestures() { - logger.log("Enabling touchpad gestures across the system") + logger.d("Enabling touchpad gestures across the system") setGesturesState(disabled = false) } 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 5a77c04924dd..6acc891e93d5 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 @@ -78,21 +78,21 @@ private fun TutorialSelectionButtons( modifier = modifier ) { TutorialButton( - text = stringResource(R.string.touchpad_tutorial_back_gesture_button), - onClick = onBackTutorialClicked, + text = stringResource(R.string.touchpad_tutorial_home_gesture_button), + onClick = onHomeTutorialClicked, color = MaterialTheme.colorScheme.primary, modifier = Modifier.weight(1f) ) TutorialButton( - text = stringResource(R.string.touchpad_tutorial_home_gesture_button), - onClick = onHomeTutorialClicked, - color = MaterialTheme.colorScheme.secondary, + text = stringResource(R.string.touchpad_tutorial_back_gesture_button), + onClick = onBackTutorialClicked, + color = MaterialTheme.colorScheme.tertiary, modifier = Modifier.weight(1f) ) TutorialButton( text = stringResource(R.string.touchpad_tutorial_recent_apps_gesture_button), onClick = onRecentAppsTutorialClicked, - color = MaterialTheme.colorScheme.tertiary, + color = MaterialTheme.colorScheme.secondary, modifier = Modifier.weight(1f) ) } diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt index 46ea352ff85a..d03b2e717398 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt @@ -29,12 +29,10 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.compose.theme.PlatformTheme import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger.TutorialContext -import com.android.systemui.inputdevice.tutorial.ui.composable.ActionKeyTutorialScreen import com.android.systemui.touchpad.tutorial.ui.composable.BackGestureTutorialScreen import com.android.systemui.touchpad.tutorial.ui.composable.HomeGestureTutorialScreen import com.android.systemui.touchpad.tutorial.ui.composable.RecentAppsGestureTutorialScreen import com.android.systemui.touchpad.tutorial.ui.composable.TutorialSelectionScreen -import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen.ACTION_KEY import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen.BACK_GESTURE import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen.HOME_GESTURE import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen.RECENT_APPS_GESTURE @@ -59,7 +57,7 @@ constructor( } // required to handle 3+ fingers on touchpad window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY) - window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS) + logger.logOpenTutorial(TutorialContext.TOUCHPAD_TUTORIAL) } private fun finishTutorial() { @@ -104,10 +102,5 @@ fun TouchpadTutorialScreen(vm: TouchpadTutorialViewModel, closeTutorial: () -> U onDoneButtonClicked = { vm.goTo(TUTORIAL_SELECTION) }, onBack = { vm.goTo(TUTORIAL_SELECTION) }, ) - ACTION_KEY -> // TODO(b/358105049) move action key tutorial to OOBE flow - ActionKeyTutorialScreen( - onDoneButtonClicked = { vm.goTo(TUTORIAL_SELECTION) }, - onBack = { vm.goTo(TUTORIAL_SELECTION) }, - ) } } diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialViewModel.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialViewModel.kt index 599e1b1eff75..c56dcf3bf062 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialViewModel.kt @@ -65,5 +65,4 @@ enum class Screen { BACK_GESTURE, HOME_GESTURE, RECENT_APPS_GESTURE, - ACTION_KEY, } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index db4f9ef13bd6..7166428d863f 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -35,7 +35,6 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static com.android.internal.jank.InteractionJankMonitor.CUJ_VOLUME_CONTROL; import static com.android.internal.jank.InteractionJankMonitor.Configuration.Builder; import static com.android.settingslib.flags.Flags.volumeDialogAudioSharingFix; -import static com.android.systemui.Flags.hapticVolumeSlider; import static com.android.systemui.volume.Events.DISMISS_REASON_POSTURE_CHANGED; import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED; @@ -928,10 +927,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, } private void addSliderHapticsToRow(VolumeRow row) { - if (hapticVolumeSlider()) { - row.createPlugin(mVibratorHelper, mSystemClock); - HapticSliderViewBinder.bind(row.slider, row.mHapticPlugin); - } + row.createPlugin(mVibratorHelper, mSystemClock); + HapticSliderViewBinder.bind(row.slider, row.mHapticPlugin); } @VisibleForTesting void addSliderHapticsToRows() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java index 530ae158cf43..5e9f2a2fbe97 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java @@ -104,6 +104,7 @@ public class FullscreenMagnificationControllerTest extends SysuiTestCase { mContext = spy(mContext); Display display = mock(Display.class); when(display.getUniqueId()).thenReturn(UNIQUE_DISPLAY_ID_PRIMARY); + when(display.getType()).thenReturn(Display.TYPE_INTERNAL); when(mContext.getDisplayNoVerify()).thenReturn(display); // Override the resources to Display Primary @@ -360,6 +361,7 @@ public class FullscreenMagnificationControllerTest extends SysuiTestCase { Display newDisplay = mock(Display.class); when(newDisplay.getUniqueId()).thenReturn(UNIQUE_DISPLAY_ID_SECONDARY); + when(newDisplay.getType()).thenReturn(Display.TYPE_INTERNAL); when(mContext.getDisplayNoVerify()).thenReturn(newDisplay); // Override the resources to Display Secondary mContext.getOrCreateTestableResources() diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java index 103449b6b0f7..ee8ce17cecd4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import android.app.UiModeManager; +import android.content.res.Configuration; import android.graphics.Rect; import android.graphics.drawable.GradientDrawable; import android.platform.test.annotations.EnableFlags; @@ -78,6 +79,12 @@ public class MenuViewTest extends SysuiTestCase { mNightMode = mUiModeManager.getNightMode(); mUiModeManager.setNightMode(MODE_NIGHT_YES); + // Programmatically update the resource's configuration to night mode to reduce flakiness + Configuration nightConfig = new Configuration(mContext.getResources().getConfiguration()); + nightConfig.uiMode = Configuration.UI_MODE_NIGHT_YES; + mContext.getResources().updateConfiguration(nightConfig, + mContext.getResources().getDisplayMetrics(), null); + mSpyContext = spy(mContext); doNothing().when(mSpyContext).startActivity(any()); @@ -101,6 +108,8 @@ public class MenuViewTest extends SysuiTestCase { @Test public void insetsOnDarkTheme_menuOnLeft_matchInsets() { + // In dark theme, the inset is not 0 to avoid weird spacing issue between the menu and + // the edge of the screen. mMenuView.onConfigurationChanged(/* newConfig= */ null); final InstantInsetLayerDrawable insetLayerDrawable = (InstantInsetLayerDrawable) mMenuView.getBackground(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt index 9aaf2958031a..a940bc9b3e20 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt @@ -8,7 +8,8 @@ import android.content.pm.ApplicationInfo import android.graphics.Point import android.graphics.Rect import android.os.Looper -import android.platform.test.flag.junit.SetFlagsRule +import android.platform.test.annotations.DisableFlags +import android.platform.test.annotations.EnableFlags import android.testing.TestableLooper.RunWithLooper import android.view.IRemoteAnimationFinishedCallback import android.view.RemoteAnimationAdapter @@ -63,7 +64,6 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { private lateinit var activityTransitionAnimator: ActivityTransitionAnimator @get:Rule val rule = MockitoJUnit.rule() - @get:Rule val setFlagsRule = SetFlagsRule() @Before fun setup() { @@ -90,7 +90,7 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { animator: ActivityTransitionAnimator = this.activityTransitionAnimator, controller: ActivityTransitionAnimator.Controller? = this.controller, animate: Boolean = true, - intentStarter: (RemoteAnimationAdapter?) -> Int + intentStarter: (RemoteAnimationAdapter?) -> Int, ) { // We start in a new thread so that we can ensure that the callbacks are called in the main // thread. @@ -98,7 +98,7 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { animator.startIntentWithAnimation( controller = controller, animate = animate, - intentStarter = intentStarter + intentStarter = intentStarter, ) } .join() @@ -175,9 +175,9 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { assertFalse(willAnimateCaptor.value) } + @EnableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY) @Test fun registersReturnIffCookieIsPresent() { - setFlagsRule.enableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY) `when`(callback.isOnKeyguard()).thenReturn(false) startIntentWithAnimation(activityTransitionAnimator, controller) { _ -> @@ -203,10 +203,12 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { assertTrue(testShellTransitions.remotesForTakeover.isEmpty()) } + @EnableFlags( + Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY, + Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED, + ) @Test fun registersLongLivedTransition() { - setFlagsRule.enableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY) - activityTransitionAnimator.register( object : DelegateTransitionAnimatorController(controller) { override val transitionCookie = @@ -226,10 +228,12 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { assertEquals(4, testShellTransitions.remotes.size) } + @EnableFlags( + Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY, + Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED, + ) @Test fun registersLongLivedTransitionOverridingPreviousRegistration() { - setFlagsRule.enableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY) - val cookie = ActivityTransitionAnimator.TransitionCookie("test_cookie") activityTransitionAnimator.register( object : DelegateTransitionAnimatorController(controller) { @@ -251,9 +255,9 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { } } + @DisableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED) @Test fun doesNotRegisterLongLivedTransitionIfFlagIsDisabled() { - setFlagsRule.disableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY) val controller = object : DelegateTransitionAnimatorController(controller) { @@ -266,9 +270,9 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { } } + @EnableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED) @Test fun doesNotRegisterLongLivedTransitionIfMissingRequiredProperties() { - setFlagsRule.enableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY) // No TransitionCookie val controllerWithoutCookie = @@ -310,9 +314,12 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { } } + @EnableFlags( + Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY, + Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED, + ) @Test fun unregistersLongLivedTransition() { - setFlagsRule.enableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY) val cookies = arrayOfNulls<ActivityTransitionAnimator.TransitionCookie>(3) @@ -411,7 +418,7 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() { SurfaceControl(), Rect(), taskInfo, - false + false, ) } } @@ -430,7 +437,7 @@ private class FakeShellTransitions : ShellTransitions { override fun registerRemoteForTakeover( filter: TransitionFilter, - remoteTransition: RemoteTransition + remoteTransition: RemoteTransition, ) { remotesForTakeover[filter] = remoteTransition } @@ -460,7 +467,7 @@ private class TestTransitionAnimatorController(override var transitionContainer: left = 300, right = 400, topCornerRadius = 10f, - bottomCornerRadius = 20f + bottomCornerRadius = 20f, ) private fun assertOnMainThread() { @@ -480,7 +487,7 @@ private class TestTransitionAnimatorController(override var transitionContainer: override fun onTransitionAnimationProgress( state: TransitionAnimator.State, progress: Float, - linearProgress: Float + linearProgress: Float, ) { assertOnMainThread() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/PatternBouncerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/PatternBouncerTest.kt index 4b61a0d02f1e..088bb02512b5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/PatternBouncerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/PatternBouncerTest.kt @@ -25,6 +25,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import com.android.systemui.SysuiTestCase import com.android.systemui.bouncer.ui.viewmodel.patternBouncerViewModelFactory +import com.android.systemui.haptics.msdl.bouncerHapticPlayer import com.android.systemui.lifecycle.activateIn import com.android.systemui.motion.createSysUiComposeMotionTestRule import com.android.systemui.testKosmos @@ -55,6 +56,7 @@ class PatternBouncerTest : SysuiTestCase() { kosmos.patternBouncerViewModelFactory.create( isInputEnabled = MutableStateFlow(true).asStateFlow(), onIntentionalUserInput = {}, + bouncerHapticPlayer = kosmos.bouncerHapticPlayer, ) @Before @@ -75,11 +77,11 @@ class PatternBouncerTest : SysuiTestCase() { content = { play -> if (play) PatternBouncerUnderTest() }, ComposeRecordingSpec.until( recordBefore = false, - checkDone = { motionTestValueOfNode(MotionTestKeys.entryCompleted) } + checkDone = { motionTestValueOfNode(MotionTestKeys.entryCompleted) }, ) { feature(MotionTestKeys.dotAppearFadeIn, floatArray) feature(MotionTestKeys.dotAppearMoveUp, floatArray) - } + }, ) assertThat(motion).timeSeriesMatchesGolden() @@ -100,7 +102,7 @@ class PatternBouncerTest : SysuiTestCase() { viewModel.onDragEnd() // Failure animation starts when animateFailure flips to true... viewModel.animateFailure.takeWhile { !it }.collect {} - } + }, ) { // ... and ends when the composable flips it back to false. viewModel.animateFailure.takeWhile { it }.collect {} @@ -111,7 +113,7 @@ class PatternBouncerTest : SysuiTestCase() { content = { PatternBouncerUnderTest() }, ComposeRecordingSpec(failureAnimationMotionControl) { feature(MotionTestKeys.dotScaling, floatArray) - } + }, ) assertThat(motion).timeSeriesMatchesGolden() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java index c65a1176a55b..d72b72c3d21e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java @@ -32,6 +32,7 @@ import android.content.ClipData; import android.content.ClipDescription; import android.content.ClipboardManager; import android.os.PersistableBundle; +import android.os.UserHandle; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.provider.Settings; @@ -101,8 +102,18 @@ public class ClipboardListenerTest extends SysuiTestCase { when(mClipboardManager.getPrimaryClip()).thenReturn(mSampleClipData); when(mClipboardManager.getPrimaryClipSource()).thenReturn(mSampleSource); - mClipboardListener = new ClipboardListener(getContext(), mOverlayControllerProvider, - mClipboardToast, mClipboardManager, mKeyguardManager, mUiEventLogger); + mClipboardListener = new ClipboardListener( + getContext(), + mOverlayControllerProvider, + mClipboardToast, + user -> { + if (UserHandle.CURRENT.equals(user)) { + return mClipboardManager; + } + return null; + }, + mKeyguardManager, + mUiEventLogger); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt index 823a23dec4ea..d32d8cc4bd51 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt @@ -82,6 +82,7 @@ import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.After @@ -200,7 +201,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa Settings.Secure.getInt( context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, - 1 + 1, ) private lateinit var staticMockSession: MockitoSession @@ -221,9 +222,8 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa Settings.Secure.putInt( context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, - 1 + 1, ) - mediaDataManager = LegacyMediaDataManagerImpl( context = context, @@ -334,7 +334,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa Settings.Secure.putInt( context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, - originalSmartspaceSetting + originalSmartspaceSetting, ) } @@ -365,7 +365,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa session.sessionToken, APP_NAME, pendingIntent, - PACKAGE_NAME + PACKAGE_NAME, ) runCurrent() @@ -378,7 +378,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) mediaDataManager.setInactive(PACKAGE_NAME, timedOut = true) @@ -404,7 +404,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa metadataBuilder .putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, - MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT + MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT, ) .build() ) @@ -420,7 +420,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value!!.isExplicit).isTrue() } @@ -438,7 +438,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value!!.isExplicit).isFalse() } @@ -451,7 +451,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa anyInt(), eq(PACKAGE_NAME), eq(mediaDataCaptor.value.instanceId), - eq(MediaData.PLAYBACK_LOCAL) + eq(MediaData.PLAYBACK_LOCAL), ) } @@ -467,7 +467,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value!!.active).isTrue() } @@ -483,7 +483,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa anyInt(), eq(SYSTEM_PACKAGE_NAME), eq(mediaDataCaptor.value.instanceId), - eq(MediaData.PLAYBACK_CAST_REMOTE) + eq(MediaData.PLAYBACK_CAST_REMOTE), ) } @@ -511,7 +511,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value!!.app).isEqualTo(subName) @@ -597,7 +597,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) val placeholderTitle = context.getString(R.string.controls_media_empty_title, APP_NAME) assertThat(mediaDataCaptor.value.song).isEqualTo(placeholderTitle) @@ -627,7 +627,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) val placeholderTitle = context.getString(R.string.controls_media_empty_title, APP_NAME) assertThat(mediaDataCaptor.value.song).isEqualTo(placeholderTitle) @@ -668,7 +668,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.song).isEqualTo(SESSION_TITLE) } @@ -683,7 +683,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa mediaDataManager.onMediaDataLoaded( KEY, null, - data.copy(song = SESSION_EMPTY_TITLE, resumeAction = Runnable {}) + data.copy(song = SESSION_EMPTY_TITLE, resumeAction = Runnable {}), ) // WHEN the notification is removed @@ -698,7 +698,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) verify(logger, never()) .logActiveConvertedToResume(anyInt(), eq(PACKAGE_NAME), eq(instanceId)) @@ -716,7 +716,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa mediaDataManager.onMediaDataLoaded( KEY, null, - data.copy(song = SESSION_BLANK_TITLE, resumeAction = Runnable {}) + data.copy(song = SESSION_BLANK_TITLE, resumeAction = Runnable {}), ) // WHEN the notification is removed @@ -731,7 +731,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) verify(logger, never()) .logActiveConvertedToResume(anyInt(), eq(PACKAGE_NAME), eq(instanceId)) @@ -756,7 +756,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.isPlaying).isFalse() @@ -777,7 +777,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() @@ -789,7 +789,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) val data2 = mediaDataCaptor.value assertThat(data2.resumption).isFalse() @@ -807,7 +807,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() verify(listener, never()).onMediaDataRemoved(eq(KEY), eq(false)) @@ -821,7 +821,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() verify(listener).onMediaDataRemoved(eq(KEY_2), eq(false)) @@ -842,7 +842,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa anyInt(), eq(PACKAGE_NAME), eq(mediaDataCaptor.value.instanceId), - eq(MediaData.PLAYBACK_CAST_LOCAL) + eq(MediaData.PLAYBACK_CAST_LOCAL), ) // WHEN the notification is removed @@ -878,7 +878,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() } @@ -932,7 +932,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.isPlaying).isFalse() @@ -982,7 +982,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa // WHEN resumption controls are added with explicit indicator bundle.putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, - MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT + MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT, ) val desc = MediaDescription.Builder().run { @@ -1015,7 +1015,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa Bundle().apply { putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, - MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED + MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED, ) putDouble(MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, progress) } @@ -1041,7 +1041,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa Bundle().apply { putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, - MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED + MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED, ) } val desc = @@ -1066,7 +1066,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa Bundle().apply { putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, - MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED + MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED, ) } val desc = @@ -1118,7 +1118,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa session.sessionToken, APP_NAME, pendingIntent, - PACKAGE_NAME + PACKAGE_NAME, ) // Resumption controls are not added. @@ -1130,7 +1130,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) } @@ -1151,7 +1151,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa session.sessionToken, APP_NAME, pendingIntent, - PACKAGE_NAME + PACKAGE_NAME, ) // Resumption controls are not added. @@ -1163,7 +1163,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) } @@ -1230,7 +1230,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) } @@ -1256,7 +1256,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) } @@ -1280,7 +1280,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) } @@ -1312,7 +1312,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) } @@ -1359,7 +1359,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) } @@ -1393,7 +1393,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) } @@ -1424,7 +1424,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) verify(listener, never()).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(false)) } @@ -1456,7 +1456,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) } @@ -1466,7 +1466,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa Settings.Secure.putInt( context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, - 0 + 0, ) tunableCaptor.value.onTuningChanged(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, "0") @@ -1488,7 +1488,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa Settings.Secure.putInt( context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, - 0 + 0, ) tunableCaptor.value.onTuningChanged(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, "0") @@ -1526,7 +1526,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.lastActive).isAtLeast(currentTime) } @@ -1553,7 +1553,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.lastActive).isAtLeast(currentTime) @@ -1573,7 +1573,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa mediaDataManager.onMediaDataLoaded( KEY, null, - data.copy(resumeAction = Runnable {}, active = false) + data.copy(resumeAction = Runnable {}, active = false), ) // WHEN the notification is removed @@ -1589,7 +1589,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTime) @@ -1629,7 +1629,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.actionsToShowInCompact.size) .isEqualTo(LegacyMediaDataManagerImpl.MAX_COMPACT_ACTIONS) @@ -1664,7 +1664,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.actions.size) .isEqualTo(LegacyMediaDataManagerImpl.MAX_NOTIFICATION_ACTIONS) @@ -1695,7 +1695,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value!!.semanticActions).isNull() @@ -1868,7 +1868,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa anyInt(), eq(PACKAGE_NAME), eq(instanceId), - eq(MediaData.PLAYBACK_CAST_LOCAL) + eq(MediaData.PLAYBACK_CAST_LOCAL), ) // update to remote cast @@ -1879,7 +1879,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa anyInt(), eq(SYSTEM_PACKAGE_NAME), eq(instanceId), - eq(MediaData.PLAYBACK_CAST_REMOTE) + eq(MediaData.PLAYBACK_CAST_REMOTE), ) } @@ -1900,7 +1900,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.isPlaying).isTrue() } @@ -1948,7 +1948,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.isPlaying).isFalse() assertThat(mediaDataCaptor.value.semanticActions).isNotNull() @@ -1977,7 +1977,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa session.sessionToken, APP_NAME, pendingIntent, - PACKAGE_NAME + PACKAGE_NAME, ) runCurrent() backgroundExecutor.runAllReady() @@ -1992,7 +1992,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.isPlaying).isFalse() assertThat(mediaDataCaptor.value.semanticActions).isNotNull() @@ -2017,7 +2017,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.isPlaying).isFalse() assertThat(mediaDataCaptor.value.semanticActions).isNull() @@ -2074,7 +2074,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.active).isFalse() @@ -2082,7 +2082,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa .logActiveConvertedToResume( anyInt(), eq(PACKAGE_NAME), - eq(mediaDataCaptor.value.instanceId) + eq(mediaDataCaptor.value.instanceId), ) } @@ -2141,7 +2141,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.active).isFalse() @@ -2149,7 +2149,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa .logActiveConvertedToResume( anyInt(), eq(PACKAGE_NAME), - eq(mediaDataCaptor.value.instanceId) + eq(mediaDataCaptor.value.instanceId), ) } @@ -2193,7 +2193,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.active).isFalse() @@ -2201,7 +2201,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa .logActiveConvertedToResume( anyInt(), eq(PACKAGE_NAME), - eq(mediaDataCaptor.value.instanceId) + eq(mediaDataCaptor.value.instanceId), ) } @@ -2245,7 +2245,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.active).isFalse() @@ -2253,7 +2253,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa .logActiveConvertedToResume( anyInt(), eq(PACKAGE_NAME), - eq(mediaDataCaptor.value.instanceId) + eq(mediaDataCaptor.value.instanceId), ) } @@ -2279,7 +2279,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) } @@ -2321,7 +2321,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.active).isFalse() @@ -2329,7 +2329,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa .logActiveConvertedToResume( anyInt(), eq(PACKAGE_NAME), - eq(mediaDataCaptor.value.instanceId) + eq(mediaDataCaptor.value.instanceId), ) } @@ -2355,7 +2355,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa any(), any(), anyInt(), - anyInt() + anyInt(), ) ) .thenReturn(1) @@ -2385,7 +2385,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa any(), any(), anyInt(), - anyInt() + anyInt(), ) ) .thenThrow(SecurityException("Test no permission")) @@ -2421,7 +2421,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) verify(kosmos.mediaLogger).logDuplicateMediaNotification(eq(KEY)) } @@ -2440,7 +2440,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY)) } @@ -2448,6 +2448,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa private fun TestScope.assertRunAllReady(foreground: Int = 0, background: Int = 0) { runCurrent() if (Flags.mediaLoadMetadataViaMediaDataLoader()) { + advanceUntilIdle() // It doesn't make much sense to count tasks when we use coroutines in loader // so this check is skipped in that scenario. backgroundExecutor.runAllReady() @@ -2478,7 +2479,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) } @@ -2493,7 +2494,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa /** Helper function to add a resumption control and capture the resulting MediaData */ private fun addResumeControlAndLoad( desc: MediaDescription, - packageName: String = PACKAGE_NAME + packageName: String = PACKAGE_NAME, ) { mediaDataManager.addResumptionControls( USER_ID, @@ -2502,7 +2503,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa session.sessionToken, APP_NAME, pendingIntent, - packageName + packageName, ) testScope.assertRunAllReady(foreground = 1, background = 1) @@ -2514,7 +2515,7 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt index 4cf7de3d7a63..90af93292de1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt @@ -90,6 +90,7 @@ import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runCurrent import org.junit.After import org.junit.Before @@ -212,7 +213,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { Settings.Secure.getInt( context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, - 1 + 1, ) private lateinit var staticMockSession: MockitoSession @@ -233,7 +234,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { Settings.Secure.putInt( context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, - 1 + 1, ) mediaDataProcessor = MediaDataProcessor( @@ -274,7 +275,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { mediaDataCombineLatest = mediaDataCombineLatest, mediaDataFilter = mediaDataFilter, mediaFilterRepository = mediaFilterRepository, - mediaFlags = kosmos.mediaFlags + mediaFlags = kosmos.mediaFlags, ) mediaCarouselInteractor.start() verify(mediaTimeoutListener).stateCallback = capture(stateCallbackCaptor) @@ -356,7 +357,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { Settings.Secure.putInt( context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, - originalSmartspaceSetting + originalSmartspaceSetting, ) } @@ -386,7 +387,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { session.sessionToken, APP_NAME, pendingIntent, - PACKAGE_NAME + PACKAGE_NAME, ) testScope.runCurrent() @@ -399,7 +400,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) mediaDataProcessor.setInactive(PACKAGE_NAME, timedOut = true) @@ -425,7 +426,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { metadataBuilder .putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, - MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT + MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT, ) .build() ) @@ -440,7 +441,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value!!.isExplicit).isTrue() } @@ -457,7 +458,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value!!.isExplicit).isFalse() } @@ -470,7 +471,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { anyInt(), eq(PACKAGE_NAME), eq(mediaDataCaptor.value.instanceId), - eq(MediaData.PLAYBACK_LOCAL) + eq(MediaData.PLAYBACK_LOCAL), ) } @@ -485,7 +486,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value!!.active).isTrue() } @@ -501,7 +502,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { anyInt(), eq(SYSTEM_PACKAGE_NAME), eq(mediaDataCaptor.value.instanceId), - eq(MediaData.PLAYBACK_CAST_REMOTE) + eq(MediaData.PLAYBACK_CAST_REMOTE), ) } @@ -529,7 +530,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value!!.app).isEqualTo(subName) @@ -615,7 +616,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) val placeholderTitle = context.getString(R.string.controls_media_empty_title, APP_NAME) assertThat(mediaDataCaptor.value.song).isEqualTo(placeholderTitle) @@ -645,7 +646,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) val placeholderTitle = context.getString(R.string.controls_media_empty_title, APP_NAME) assertThat(mediaDataCaptor.value.song).isEqualTo(placeholderTitle) @@ -686,7 +687,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.song).isEqualTo(SESSION_TITLE) } @@ -701,7 +702,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { mediaDataProcessor.onMediaDataLoaded( KEY, null, - data.copy(song = SESSION_EMPTY_TITLE, resumeAction = Runnable {}) + data.copy(song = SESSION_EMPTY_TITLE, resumeAction = Runnable {}), ) // WHEN the notification is removed @@ -716,7 +717,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) verify(logger, never()) .logActiveConvertedToResume(anyInt(), eq(PACKAGE_NAME), eq(instanceId)) @@ -734,7 +735,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { mediaDataProcessor.onMediaDataLoaded( KEY, null, - data.copy(song = SESSION_BLANK_TITLE, resumeAction = Runnable {}) + data.copy(song = SESSION_BLANK_TITLE, resumeAction = Runnable {}), ) // WHEN the notification is removed @@ -749,7 +750,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) verify(logger, never()) .logActiveConvertedToResume(anyInt(), eq(PACKAGE_NAME), eq(instanceId)) @@ -774,7 +775,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.isPlaying).isFalse() @@ -795,7 +796,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() @@ -807,7 +808,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) val data2 = mediaDataCaptor.value assertThat(data2.resumption).isFalse() @@ -825,7 +826,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() verify(listener, never()).onMediaDataRemoved(eq(KEY), anyBoolean()) @@ -839,7 +840,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() verify(listener).onMediaDataRemoved(eq(KEY_2), eq(false)) @@ -860,7 +861,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { anyInt(), eq(PACKAGE_NAME), eq(mediaDataCaptor.value.instanceId), - eq(MediaData.PLAYBACK_CAST_LOCAL) + eq(MediaData.PLAYBACK_CAST_LOCAL), ) // WHEN the notification is removed @@ -896,7 +897,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() } @@ -950,7 +951,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.isPlaying).isFalse() @@ -1000,7 +1001,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { // WHEN resumption controls are added with explicit indicator bundle.putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, - MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT + MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT, ) val desc = MediaDescription.Builder().run { @@ -1033,7 +1034,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { Bundle().apply { putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, - MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED + MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED, ) putDouble(MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, progress) } @@ -1059,7 +1060,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { Bundle().apply { putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, - MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED + MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED, ) } val desc = @@ -1084,7 +1085,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { Bundle().apply { putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, - MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED + MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED, ) } val desc = @@ -1136,7 +1137,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { session.sessionToken, APP_NAME, pendingIntent, - PACKAGE_NAME + PACKAGE_NAME, ) // Resumption controls are not added. @@ -1148,7 +1149,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) } @@ -1169,7 +1170,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { session.sessionToken, APP_NAME, pendingIntent, - PACKAGE_NAME + PACKAGE_NAME, ) // Resumption controls are not added. @@ -1181,7 +1182,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) } @@ -1248,7 +1249,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) } @@ -1274,7 +1275,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) } @@ -1298,7 +1299,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) } @@ -1330,7 +1331,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) } @@ -1377,7 +1378,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) } @@ -1411,7 +1412,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) } @@ -1442,7 +1443,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) verify(listener, never()).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(false)) } @@ -1474,7 +1475,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { expiryTimeMs = SMARTSPACE_EXPIRY_TIME, ) ), - eq(false) + eq(false), ) } @@ -1536,7 +1537,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.lastActive).isAtLeast(currentTime) } @@ -1563,7 +1564,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.lastActive).isAtLeast(currentTime) @@ -1583,7 +1584,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { mediaDataProcessor.onMediaDataLoaded( KEY, null, - data.copy(resumeAction = Runnable {}, active = false) + data.copy(resumeAction = Runnable {}, active = false), ) // WHEN the notification is removed @@ -1599,7 +1600,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTime) @@ -1639,7 +1640,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.actionsToShowInCompact.size) .isEqualTo(MediaDataProcessor.MAX_COMPACT_ACTIONS) @@ -1674,7 +1675,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.actions.size) .isEqualTo(MediaDataProcessor.MAX_NOTIFICATION_ACTIONS) @@ -1705,7 +1706,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value!!.semanticActions).isNull() @@ -1944,7 +1945,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { anyInt(), eq(PACKAGE_NAME), eq(instanceId), - eq(MediaData.PLAYBACK_CAST_LOCAL) + eq(MediaData.PLAYBACK_CAST_LOCAL), ) // update to remote cast @@ -1955,7 +1956,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { anyInt(), eq(SYSTEM_PACKAGE_NAME), eq(instanceId), - eq(MediaData.PLAYBACK_CAST_REMOTE) + eq(MediaData.PLAYBACK_CAST_REMOTE), ) } @@ -1976,7 +1977,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.isPlaying).isTrue() } @@ -2024,7 +2025,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.isPlaying).isFalse() assertThat(mediaDataCaptor.value.semanticActions).isNotNull() @@ -2052,7 +2053,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { session.sessionToken, APP_NAME, pendingIntent, - PACKAGE_NAME + PACKAGE_NAME, ) testScope.runCurrent() backgroundExecutor.runAllReady() @@ -2067,7 +2068,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.isPlaying).isFalse() assertThat(mediaDataCaptor.value.semanticActions).isNotNull() @@ -2092,7 +2093,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.isPlaying).isFalse() assertThat(mediaDataCaptor.value.semanticActions).isNull() @@ -2149,7 +2150,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.active).isFalse() @@ -2157,7 +2158,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { .logActiveConvertedToResume( anyInt(), eq(PACKAGE_NAME), - eq(mediaDataCaptor.value.instanceId) + eq(mediaDataCaptor.value.instanceId), ) } @@ -2216,7 +2217,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.active).isFalse() @@ -2224,7 +2225,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { .logActiveConvertedToResume( anyInt(), eq(PACKAGE_NAME), - eq(mediaDataCaptor.value.instanceId) + eq(mediaDataCaptor.value.instanceId), ) } @@ -2268,7 +2269,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.active).isFalse() @@ -2276,7 +2277,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { .logActiveConvertedToResume( anyInt(), eq(PACKAGE_NAME), - eq(mediaDataCaptor.value.instanceId) + eq(mediaDataCaptor.value.instanceId), ) } @@ -2320,7 +2321,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.active).isFalse() @@ -2328,7 +2329,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { .logActiveConvertedToResume( anyInt(), eq(PACKAGE_NAME), - eq(mediaDataCaptor.value.instanceId) + eq(mediaDataCaptor.value.instanceId), ) } @@ -2354,7 +2355,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) } @@ -2396,7 +2397,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.active).isFalse() @@ -2404,7 +2405,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { .logActiveConvertedToResume( anyInt(), eq(PACKAGE_NAME), - eq(mediaDataCaptor.value.instanceId) + eq(mediaDataCaptor.value.instanceId), ) } @@ -2430,7 +2431,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { any(), any(), anyInt(), - anyInt() + anyInt(), ) ) .thenReturn(1) @@ -2460,7 +2461,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { any(), any(), anyInt(), - anyInt() + anyInt(), ) ) .thenThrow(SecurityException("Test no permission")) @@ -2501,7 +2502,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) verify(kosmos.mediaLogger).logDuplicateMediaNotification(eq(KEY)) } @@ -2525,7 +2526,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY)) } @@ -2533,6 +2534,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { private fun TestScope.assertRunAllReady(foreground: Int = 0, background: Int = 0) { runCurrent() if (Flags.mediaLoadMetadataViaMediaDataLoader()) { + advanceUntilIdle() // It doesn't make much sense to count tasks when we use coroutines in loader // so this check is skipped in that scenario. backgroundExecutor.runAllReady() @@ -2563,7 +2565,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) } @@ -2578,7 +2580,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { /** Helper function to add a resumption control and capture the resulting MediaData */ private fun addResumeControlAndLoad( desc: MediaDescription, - packageName: String = PACKAGE_NAME + packageName: String = PACKAGE_NAME, ) { mediaDataProcessor.addResumptionControls( USER_ID, @@ -2587,7 +2589,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { session.sessionToken, APP_NAME, pendingIntent, - packageName + packageName, ) testScope.assertRunAllReady(foreground = 1, background = 1) @@ -2598,7 +2600,7 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() { capture(mediaDataCaptor), eq(true), eq(0), - eq(false) + eq(false), ) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt index 2370bca52951..0508c2cf0426 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt @@ -25,6 +25,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardViewController import com.android.systemui.SysuiTestCase +import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.communal.ui.viewmodel.communalTransitionViewModel @@ -34,6 +35,7 @@ import com.android.systemui.flags.DisableSceneContainer import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.keyguardRepository import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.kosmos.testScope @@ -80,6 +82,8 @@ import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit import org.mockito.kotlin.any import org.mockito.kotlin.anyOrNull +import org.mockito.kotlin.atLeastOnce +import org.mockito.kotlin.lastValue @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @@ -118,6 +122,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() { private lateinit var mediaHierarchyManager: MediaHierarchyManager private lateinit var isQsBypassingShade: MutableStateFlow<Boolean> private lateinit var shadeExpansion: MutableStateFlow<Float> + private lateinit var anyShadeExpanded: MutableStateFlow<Boolean> private lateinit var mediaFrame: ViewGroup private val configurationController = FakeConfigurationController() private val settings = FakeSettings() @@ -137,8 +142,10 @@ class MediaHierarchyManagerTest : SysuiTestCase() { whenever(mediaCarouselController.mediaFrame).thenReturn(mediaFrame) isQsBypassingShade = MutableStateFlow(false) shadeExpansion = MutableStateFlow(0f) + anyShadeExpanded = MutableStateFlow(false) whenever(shadeInteractor.isQsBypassingShade).thenReturn(isQsBypassingShade) whenever(shadeInteractor.shadeExpansion).thenReturn(shadeExpansion) + whenever(shadeInteractor.isAnyFullyExpanded).thenReturn(anyShadeExpanded) mediaHierarchyManager = MediaHierarchyManager( context, @@ -574,6 +581,72 @@ class MediaHierarchyManagerTest : SysuiTestCase() { } @Test + fun testCommunalLocationVisibilityWithShadeShowing() = + testScope.runTest { + whenever(mediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(true) + keyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.GLANCEABLE_HUB, + testScope = testScope, + ) + kosmos.fakeCommunalSceneRepository.changeScene(CommunalScenes.Communal) + runCurrent() + verify(mediaCarouselController) + .onDesiredLocationChanged( + eq(MediaHierarchyManager.LOCATION_COMMUNAL_HUB), + nullable(), + eq(false), + anyLong(), + anyLong() + ) + + val captor = ArgumentCaptor.forClass(Boolean::class.java) + verify(mediaCarouselScrollHandler, atLeastOnce()).visibleToUser = captor.capture() + + assertThat(captor.lastValue).isTrue() + + clearInvocations(mediaCarouselScrollHandler) + anyShadeExpanded.value = true + runCurrent() + verify(mediaCarouselScrollHandler, atLeastOnce()).visibleToUser = captor.capture() + + assertThat(captor.lastValue).isFalse() + } + + @Test + fun testCommunalLocationVisibilityWithPrimaryBouncerShowing() = + testScope.runTest { + whenever(mediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(true) + keyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.GLANCEABLE_HUB, + testScope = testScope, + ) + kosmos.fakeCommunalSceneRepository.changeScene(CommunalScenes.Communal) + runCurrent() + verify(mediaCarouselController) + .onDesiredLocationChanged( + eq(MediaHierarchyManager.LOCATION_COMMUNAL_HUB), + nullable(), + eq(false), + anyLong(), + anyLong() + ) + + val captor = ArgumentCaptor.forClass(Boolean::class.java) + verify(mediaCarouselScrollHandler, atLeastOnce()).visibleToUser = captor.capture() + + assertThat(captor.lastValue).isTrue() + + clearInvocations(mediaCarouselScrollHandler) + kosmos.keyguardBouncerRepository.setPrimaryShow(true) + runCurrent() + verify(mediaCarouselScrollHandler, atLeastOnce()).visibleToUser = captor.capture() + + assertThat(captor.lastValue).isFalse() + } + + @Test fun testCommunalLocation_showsOverLockscreen() = testScope.runTest { // Device is on lock screen. diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java index 411ff91ebc2f..8731853e4939 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java @@ -77,7 +77,8 @@ public class MediaOutputAdapterTest extends SysuiTestCase { private static final int TEST_CURRENT_VOLUME = 10; // Mock - private MediaOutputController mMediaOutputController = mock(MediaOutputController.class); + private MediaSwitchingController mMediaSwitchingController = + mock(MediaSwitchingController.class); private MediaOutputDialog mMediaOutputDialog = mock(MediaOutputDialog.class); private MediaDevice mMediaDevice1 = mock(MediaDevice.class); private MediaDevice mMediaDevice2 = mock(MediaDevice.class); @@ -95,13 +96,13 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Before public void setUp() { - when(mMediaOutputController.getMediaItemList()).thenReturn(mMediaItems); - when(mMediaOutputController.hasAdjustVolumeUserRestriction()).thenReturn(false); - when(mMediaOutputController.isAnyDeviceTransferring()).thenReturn(false); - when(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).thenReturn(mIconCompat); - when(mMediaOutputController.getDeviceIconCompat(mMediaDevice2)).thenReturn(mIconCompat); - when(mMediaOutputController.getCurrentConnectedMediaDevice()).thenReturn(mMediaDevice1); - when(mMediaOutputController.isActiveRemoteDevice(mMediaDevice1)).thenReturn(true); + when(mMediaSwitchingController.getMediaItemList()).thenReturn(mMediaItems); + when(mMediaSwitchingController.hasAdjustVolumeUserRestriction()).thenReturn(false); + when(mMediaSwitchingController.isAnyDeviceTransferring()).thenReturn(false); + when(mMediaSwitchingController.getDeviceIconCompat(mMediaDevice1)).thenReturn(mIconCompat); + when(mMediaSwitchingController.getDeviceIconCompat(mMediaDevice2)).thenReturn(mIconCompat); + when(mMediaSwitchingController.getCurrentConnectedMediaDevice()).thenReturn(mMediaDevice1); + when(mMediaSwitchingController.isActiveRemoteDevice(mMediaDevice1)).thenReturn(true); when(mIconCompat.toIcon(mContext)).thenReturn(mIcon); when(mMediaDevice1.getName()).thenReturn(TEST_DEVICE_NAME_1); when(mMediaDevice1.getId()).thenReturn(TEST_DEVICE_ID_1); @@ -116,7 +117,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { mMediaItems.add(MediaItem.createDeviceMediaItem(mMediaDevice1)); mMediaItems.add(MediaItem.createDeviceMediaItem(mMediaDevice2)); - mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController); + mMediaOutputAdapter = new MediaOutputAdapter(mMediaSwitchingController); mMediaOutputAdapter.updateItems(); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); @@ -142,7 +143,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_bindPairNew_verifyView() { - mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController); + mMediaOutputAdapter = new MediaOutputAdapter(mMediaSwitchingController); mMediaOutputAdapter.updateItems(); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); @@ -161,11 +162,13 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_bindGroup_withSessionName_verifyView() { - when(mMediaOutputController.getSelectedMediaDevice()).thenReturn( - mMediaItems.stream().map((item) -> item.getMediaDevice().get()).collect( - Collectors.toList())); - when(mMediaOutputController.getSessionName()).thenReturn(TEST_SESSION_NAME); - mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController); + when(mMediaSwitchingController.getSelectedMediaDevice()) + .thenReturn( + mMediaItems.stream() + .map((item) -> item.getMediaDevice().get()) + .collect(Collectors.toList())); + when(mMediaSwitchingController.getSessionName()).thenReturn(TEST_SESSION_NAME); + mMediaOutputAdapter = new MediaOutputAdapter(mMediaSwitchingController); mMediaOutputAdapter.updateItems(); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); @@ -181,11 +184,13 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_bindGroup_noSessionName_verifyView() { - when(mMediaOutputController.getSelectedMediaDevice()).thenReturn( - mMediaItems.stream().map((item) -> item.getMediaDevice().get()).collect( - Collectors.toList())); - when(mMediaOutputController.getSessionName()).thenReturn(null); - mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController); + when(mMediaSwitchingController.getSelectedMediaDevice()) + .thenReturn( + mMediaItems.stream() + .map((item) -> item.getMediaDevice().get()) + .collect(Collectors.toList())); + when(mMediaSwitchingController.getSessionName()).thenReturn(null); + mMediaOutputAdapter = new MediaOutputAdapter(mMediaSwitchingController); mMediaOutputAdapter.updateItems(); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); @@ -214,7 +219,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_bindNonRemoteConnectedDevice_verifyView() { - when(mMediaOutputController.isActiveRemoteDevice(mMediaDevice1)).thenReturn(false); + when(mMediaSwitchingController.isActiveRemoteDevice(mMediaDevice1)).thenReturn(false); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); @@ -230,9 +235,9 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_bindConnectedRemoteDevice_verifyView() { - when(mMediaOutputController.getSelectableMediaDevice()).thenReturn( - ImmutableList.of(mMediaDevice2)); - when(mMediaOutputController.isCurrentConnectedDeviceRemote()).thenReturn(true); + when(mMediaSwitchingController.getSelectableMediaDevice()) + .thenReturn(ImmutableList.of(mMediaDevice2)); + when(mMediaSwitchingController.isCurrentConnectedDeviceRemote()).thenReturn(true); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); @@ -249,9 +254,9 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_bindConnectedRemoteDevice_verifyContentDescriptionNotNull() { - when(mMediaOutputController.getSelectableMediaDevice()).thenReturn( - ImmutableList.of(mMediaDevice2)); - when(mMediaOutputController.isCurrentConnectedDeviceRemote()).thenReturn(true); + when(mMediaSwitchingController.getSelectableMediaDevice()) + .thenReturn(ImmutableList.of(mMediaDevice2)); + when(mMediaSwitchingController.isCurrentConnectedDeviceRemote()).thenReturn(true); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); @@ -263,9 +268,8 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_bindSingleConnectedRemoteDevice_verifyView() { - when(mMediaOutputController.getSelectableMediaDevice()).thenReturn( - ImmutableList.of()); - when(mMediaOutputController.isCurrentConnectedDeviceRemote()).thenReturn(true); + when(mMediaSwitchingController.getSelectableMediaDevice()).thenReturn(ImmutableList.of()); + when(mMediaSwitchingController.isCurrentConnectedDeviceRemote()).thenReturn(true); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); @@ -283,9 +287,8 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_bindConnectedRemoteDeviceWithOnGoingSession_verifyView() { when(mMediaDevice1.hasOngoingSession()).thenReturn(true); - when(mMediaOutputController.getSelectableMediaDevice()).thenReturn( - ImmutableList.of()); - when(mMediaOutputController.isCurrentConnectedDeviceRemote()).thenReturn(true); + when(mMediaSwitchingController.getSelectableMediaDevice()).thenReturn(ImmutableList.of()); + when(mMediaSwitchingController.isCurrentConnectedDeviceRemote()).thenReturn(true); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); @@ -305,9 +308,8 @@ public class MediaOutputAdapterTest extends SysuiTestCase { public void onBindViewHolder_bindConnectedRemoteDeviceWithHostOnGoingSession_verifyView() { when(mMediaDevice1.hasOngoingSession()).thenReturn(true); when(mMediaDevice1.isHostForOngoingSession()).thenReturn(true); - when(mMediaOutputController.getSelectableMediaDevice()).thenReturn( - ImmutableList.of()); - when(mMediaOutputController.isCurrentConnectedDeviceRemote()).thenReturn(true); + when(mMediaSwitchingController.getSelectableMediaDevice()).thenReturn(ImmutableList.of()); + when(mMediaSwitchingController.isCurrentConnectedDeviceRemote()).thenReturn(true); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); @@ -326,8 +328,8 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_bindConnectedDeviceWithMutingExpectedDeviceExist_verifyView() { - when(mMediaOutputController.hasMutingExpectedDevice()).thenReturn(true); - when(mMediaOutputController.isCurrentConnectedDeviceRemote()).thenReturn(false); + when(mMediaSwitchingController.hasMutingExpectedDevice()).thenReturn(true); + when(mMediaSwitchingController.isCurrentConnectedDeviceRemote()).thenReturn(false); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE); @@ -340,8 +342,8 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_isMutingExpectedDevice_verifyView() { when(mMediaDevice1.isMutingExpectedDevice()).thenReturn(true); - when(mMediaOutputController.isCurrentConnectedDeviceRemote()).thenReturn(false); - when(mMediaOutputController.isActiveRemoteDevice(mMediaDevice1)).thenReturn(false); + when(mMediaSwitchingController.isCurrentConnectedDeviceRemote()).thenReturn(false); + when(mMediaSwitchingController.isActiveRemoteDevice(mMediaDevice1)).thenReturn(false); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); @@ -378,14 +380,14 @@ public class MediaOutputAdapterTest extends SysuiTestCase { mOnSeekBarChangeListenerCaptor.getValue().onStopTrackingTouch(mViewHolder.mSeekBar); assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE); - verify(mMediaOutputController).logInteractionAdjustVolume(mMediaDevice1); + verify(mMediaSwitchingController).logInteractionAdjustVolume(mMediaDevice1); } @Test public void onBindViewHolder_bindSelectableDevice_verifyView() { List<MediaDevice> selectableDevices = new ArrayList<>(); selectableDevices.add(mMediaDevice2); - when(mMediaOutputController.getSelectableMediaDevice()).thenReturn(selectableDevices); + when(mMediaSwitchingController.getSelectableMediaDevice()).thenReturn(selectableDevices); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1); assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE); @@ -440,7 +442,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void subStatusSupported_onBindViewHolder_bindHostDeviceWithOngoingSession_verifyView() { - when(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).thenReturn(true); + when(mMediaSwitchingController.isVolumeControlEnabled(mMediaDevice1)).thenReturn(true); when(mMediaDevice1.isHostForOngoingSession()).thenReturn(true); when(mMediaDevice1.hasSubtext()).thenReturn(true); when(mMediaDevice1.getSubtext()).thenReturn(SUBTEXT_CUSTOM); @@ -540,7 +542,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_inTransferring_bindTransferringDevice_verifyView() { - when(mMediaOutputController.isAnyDeviceTransferring()).thenReturn(true); + when(mMediaSwitchingController.isAnyDeviceTransferring()).thenReturn(true); when(mMediaDevice1.getState()).thenReturn( LocalMediaManager.MediaDeviceState.STATE_CONNECTING); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); @@ -556,7 +558,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_bindGroupingDevice_verifyView() { - when(mMediaOutputController.isAnyDeviceTransferring()).thenReturn(false); + when(mMediaSwitchingController.isAnyDeviceTransferring()).thenReturn(false); when(mMediaDevice1.getState()).thenReturn( LocalMediaManager.MediaDeviceState.STATE_GROUPING); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); @@ -572,7 +574,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_inTransferring_bindNonTransferringDevice_verifyView() { - when(mMediaOutputController.isAnyDeviceTransferring()).thenReturn(true); + when(mMediaSwitchingController.isAnyDeviceTransferring()).thenReturn(true); when(mMediaDevice2.getState()).thenReturn( LocalMediaManager.MediaDeviceState.STATE_CONNECTING); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); @@ -586,7 +588,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onItemClick_clickPairNew_verifyLaunchBluetoothPairing() { - mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController); + mMediaOutputAdapter = new MediaOutputAdapter(mMediaSwitchingController); mMediaOutputAdapter.updateItems(); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); @@ -595,16 +597,16 @@ public class MediaOutputAdapterTest extends SysuiTestCase { mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2); mViewHolder.mContainerLayout.performClick(); - verify(mMediaOutputController).launchBluetoothPairing(mViewHolder.mContainerLayout); + verify(mMediaSwitchingController).launchBluetoothPairing(mViewHolder.mContainerLayout); } @Test public void onItemClick_clickDevice_verifyConnectDevice() { - when(mMediaOutputController.isCurrentOutputDeviceHasSessionOngoing()).thenReturn(false); + when(mMediaSwitchingController.isCurrentOutputDeviceHasSessionOngoing()).thenReturn(false); assertThat(mMediaDevice2.getState()).isEqualTo( LocalMediaManager.MediaDeviceState.STATE_DISCONNECTED); when(mMediaDevice2.getSelectionBehavior()).thenReturn(SELECTION_BEHAVIOR_TRANSFER); - mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController); + mMediaOutputAdapter = new MediaOutputAdapter(mMediaSwitchingController); mMediaOutputAdapter.updateItems(); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); @@ -613,16 +615,16 @@ public class MediaOutputAdapterTest extends SysuiTestCase { mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1); mViewHolder.mContainerLayout.performClick(); - verify(mMediaOutputController).connectDevice(mMediaDevice2); + verify(mMediaSwitchingController).connectDevice(mMediaDevice2); } @Test public void onItemClick_clickDeviceWithSessionOngoing_verifyShowsDialog() { - when(mMediaOutputController.isCurrentOutputDeviceHasSessionOngoing()).thenReturn(true); + when(mMediaSwitchingController.isCurrentOutputDeviceHasSessionOngoing()).thenReturn(true); assertThat(mMediaDevice2.getState()).isEqualTo( LocalMediaManager.MediaDeviceState.STATE_DISCONNECTED); when(mMediaDevice2.getSelectionBehavior()).thenReturn(SELECTION_BEHAVIOR_TRANSFER); - mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController); + mMediaOutputAdapter = new MediaOutputAdapter(mMediaSwitchingController); mMediaOutputAdapter.updateItems(); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); @@ -633,66 +635,68 @@ public class MediaOutputAdapterTest extends SysuiTestCase { mMediaOutputAdapter.onBindViewHolder(spyMediaDeviceViewHolder, 1); spyMediaDeviceViewHolder.mContainerLayout.performClick(); - verify(mMediaOutputController, never()).connectDevice(mMediaDevice2); + verify(mMediaSwitchingController, never()).connectDevice(mMediaDevice2); verify(spyMediaDeviceViewHolder).showCustomEndSessionDialog(mMediaDevice2); } @Test public void onItemClick_clicksWithMutingExpectedDeviceExist_cancelsMuteAwaitConnection() { - when(mMediaOutputController.isAnyDeviceTransferring()).thenReturn(false); - when(mMediaOutputController.hasMutingExpectedDevice()).thenReturn(true); - when(mMediaOutputController.isCurrentConnectedDeviceRemote()).thenReturn(false); + when(mMediaSwitchingController.isAnyDeviceTransferring()).thenReturn(false); + when(mMediaSwitchingController.hasMutingExpectedDevice()).thenReturn(true); + when(mMediaSwitchingController.isCurrentConnectedDeviceRemote()).thenReturn(false); when(mMediaDevice1.isMutingExpectedDevice()).thenReturn(false); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); mViewHolder.mContainerLayout.performClick(); - verify(mMediaOutputController).cancelMuteAwaitConnection(); + verify(mMediaSwitchingController).cancelMuteAwaitConnection(); } @Test public void onGroupActionTriggered_clicksEndAreaOfSelectableDevice_triggerGrouping() { List<MediaDevice> selectableDevices = new ArrayList<>(); selectableDevices.add(mMediaDevice2); - when(mMediaOutputController.getSelectableMediaDevice()).thenReturn(selectableDevices); + when(mMediaSwitchingController.getSelectableMediaDevice()).thenReturn(selectableDevices); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1); mViewHolder.mEndTouchArea.performClick(); - verify(mMediaOutputController).addDeviceToPlayMedia(mMediaDevice2); + verify(mMediaSwitchingController).addDeviceToPlayMedia(mMediaDevice2); } @Test public void onGroupActionTriggered_clickSelectedRemoteDevice_triggerUngrouping() { - when(mMediaOutputController.getSelectableMediaDevice()).thenReturn( - ImmutableList.of(mMediaDevice2)); - when(mMediaOutputController.getDeselectableMediaDevice()).thenReturn( - ImmutableList.of(mMediaDevice1)); - when(mMediaOutputController.isCurrentConnectedDeviceRemote()).thenReturn(true); + when(mMediaSwitchingController.getSelectableMediaDevice()) + .thenReturn(ImmutableList.of(mMediaDevice2)); + when(mMediaSwitchingController.getDeselectableMediaDevice()) + .thenReturn(ImmutableList.of(mMediaDevice1)); + when(mMediaSwitchingController.isCurrentConnectedDeviceRemote()).thenReturn(true); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); mViewHolder.mEndTouchArea.performClick(); - verify(mMediaOutputController).removeDeviceFromPlayMedia(mMediaDevice1); + verify(mMediaSwitchingController).removeDeviceFromPlayMedia(mMediaDevice1); } @Test public void onItemClick_onGroupActionTriggered_verifySeekbarDisabled() { - when(mMediaOutputController.getSelectedMediaDevice()).thenReturn( - mMediaItems.stream().map((item) -> item.getMediaDevice().get()).collect( - Collectors.toList())); - mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController); + when(mMediaSwitchingController.getSelectedMediaDevice()) + .thenReturn( + mMediaItems.stream() + .map((item) -> item.getMediaDevice().get()) + .collect(Collectors.toList())); + mMediaOutputAdapter = new MediaOutputAdapter(mMediaSwitchingController); mMediaOutputAdapter.updateItems(); mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter .onCreateViewHolder(new LinearLayout(mContext), 0); List<MediaDevice> selectableDevices = new ArrayList<>(); selectableDevices.add(mMediaDevice1); - when(mMediaOutputController.getSelectableMediaDevice()).thenReturn(selectableDevices); - when(mMediaOutputController.hasAdjustVolumeUserRestriction()).thenReturn(true); + when(mMediaSwitchingController.getSelectableMediaDevice()).thenReturn(selectableDevices); + when(mMediaSwitchingController.hasAdjustVolumeUserRestriction()).thenReturn(true); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); mViewHolder.mContainerLayout.performClick(); @@ -702,11 +706,11 @@ public class MediaOutputAdapterTest extends SysuiTestCase { @Test public void onBindViewHolder_volumeControlChangeToEnabled_enableSeekbarAgain() { - when(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).thenReturn(false); + when(mMediaSwitchingController.isVolumeControlEnabled(mMediaDevice1)).thenReturn(false); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); assertThat(mViewHolder.mSeekBar.isEnabled()).isFalse(); - when(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).thenReturn(true); + when(mMediaSwitchingController.isVolumeControlEnabled(mMediaDevice1)).thenReturn(true); mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0); assertThat(mViewHolder.mSeekBar.isEnabled()).isTrue(); @@ -719,7 +723,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { mMediaOutputAdapter.updateColorScheme(wallpaperColors, true); - verify(mMediaOutputController).setCurrentColorScheme(wallpaperColors, true); + verify(mMediaSwitchingController).setCurrentColorScheme(wallpaperColors, true); } @Test @@ -727,7 +731,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase { mMediaOutputAdapter.updateItems(); List<MediaItem> updatedList = new ArrayList<>(); updatedList.add(MediaItem.createPairNewDeviceMediaItem()); - when(mMediaOutputController.getMediaItemList()).thenReturn(updatedList); + when(mMediaSwitchingController.getMediaItemList()).thenReturn(updatedList); assertThat(mMediaOutputAdapter.getItemCount()).isEqualTo(mMediaItems.size()); mMediaOutputAdapter.updateItems(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java index c8cc6b5fdf93..47371dfd8895 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java @@ -104,7 +104,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { private List<MediaController> mMediaControllers = new ArrayList<>(); private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl; - private MediaOutputController mMediaOutputController; + private MediaSwitchingController mMediaSwitchingController; private int mHeaderIconRes; private IconCompat mIconCompat; private CharSequence mHeaderTitle; @@ -132,8 +132,8 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { VolumePanelGlobalStateInteractorKosmosKt.getVolumePanelGlobalStateInteractor( mKosmos); - mMediaOutputController = - new MediaOutputController( + mMediaSwitchingController = + new MediaSwitchingController( mContext, TEST_PACKAGE, mContext.getUser(), @@ -153,12 +153,13 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { // Using a fake package will cause routing operations to fail, so we intercept // scanning-related operations. - mMediaOutputController.mLocalMediaManager = mock(LocalMediaManager.class); - doNothing().when(mMediaOutputController.mLocalMediaManager).startScan(); - doNothing().when(mMediaOutputController.mLocalMediaManager).stopScan(); + mMediaSwitchingController.mLocalMediaManager = mock(LocalMediaManager.class); + doNothing().when(mMediaSwitchingController.mLocalMediaManager).startScan(); + doNothing().when(mMediaSwitchingController.mLocalMediaManager).stopScan(); - mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender, - mMediaOutputController); + mMediaOutputBaseDialogImpl = + new MediaOutputBaseDialogImpl( + mContext, mBroadcastSender, mMediaSwitchingController); mMediaOutputBaseDialogImpl.onCreate(new Bundle()); } @@ -176,7 +177,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { public void refresh_withIconCompat_iconIsVisible() { mIconCompat = IconCompat.createWithBitmap( Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)); - when(mMediaOutputBaseAdapter.getController()).thenReturn(mMediaOutputController); + when(mMediaOutputBaseAdapter.getController()).thenReturn(mMediaSwitchingController); mMediaOutputBaseDialogImpl.refresh(); final ImageView view = mMediaOutputBaseDialogImpl.mDialogView.requireViewById( @@ -263,7 +264,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { when(mMediaOutputBaseAdapter.isDragging()).thenReturn(true); mMediaOutputBaseDialogImpl.refresh(); - assertThat(mMediaOutputController.isRefreshing()).isFalse(); + assertThat(mMediaSwitchingController.isRefreshing()).isFalse(); } @Test @@ -335,12 +336,14 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { class MediaOutputBaseDialogImpl extends MediaOutputBaseDialog { - MediaOutputBaseDialogImpl(Context context, BroadcastSender broadcastSender, - MediaOutputController mediaOutputController) { + MediaOutputBaseDialogImpl( + Context context, + BroadcastSender broadcastSender, + MediaSwitchingController mediaSwitchingController) { super( context, broadcastSender, - mediaOutputController, /* includePlaybackAndAppMetadata */ + mediaSwitchingController, /* includePlaybackAndAppMetadata */ true); mAdapter = mMediaOutputBaseAdapter; diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java index 189a56145d27..f0902e35b837 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java @@ -119,7 +119,7 @@ public class MediaOutputBroadcastDialogTest extends SysuiTestCase { private UserTracker mUserTracker = mock(UserTracker.class); private MediaOutputBroadcastDialog mMediaOutputBroadcastDialog; - private MediaOutputController mMediaOutputController; + private MediaSwitchingController mMediaSwitchingController; @Before public void setUp() { @@ -133,8 +133,8 @@ public class MediaOutputBroadcastDialogTest extends SysuiTestCase { VolumePanelGlobalStateInteractorKosmosKt.getVolumePanelGlobalStateInteractor( mKosmos); - mMediaOutputController = - new MediaOutputController( + mMediaSwitchingController = + new MediaSwitchingController( mContext, TEST_PACKAGE, mContext.getUser(), @@ -151,9 +151,10 @@ public class MediaOutputBroadcastDialogTest extends SysuiTestCase { mFlags, volumePanelGlobalStateInteractor, mUserTracker); - mMediaOutputController.mLocalMediaManager = mLocalMediaManager; - mMediaOutputBroadcastDialog = new MediaOutputBroadcastDialog(mContext, false, - mBroadcastSender, mMediaOutputController); + mMediaSwitchingController.mLocalMediaManager = mLocalMediaManager; + mMediaOutputBroadcastDialog = + new MediaOutputBroadcastDialog( + mContext, false, mBroadcastSender, mMediaSwitchingController); mMediaOutputBroadcastDialog.show(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java index 90c2930f8e49..d3ecb3d8c944 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java @@ -119,7 +119,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { private List<MediaController> mMediaControllers = new ArrayList<>(); private MediaOutputDialog mMediaOutputDialog; - private MediaOutputController mMediaOutputController; + private MediaSwitchingController mMediaSwitchingController; private final List<String> mFeatures = new ArrayList<>(); @Override @@ -146,8 +146,8 @@ public class MediaOutputDialogTest extends SysuiTestCase { VolumePanelGlobalStateInteractorKosmosKt.getVolumePanelGlobalStateInteractor( mKosmos); - mMediaOutputController = - new MediaOutputController( + mMediaSwitchingController = + new MediaSwitchingController( mContext, TEST_PACKAGE, mContext.getUser(), @@ -164,8 +164,8 @@ public class MediaOutputDialogTest extends SysuiTestCase { mFlags, volumePanelGlobalStateInteractor, mUserTracker); - mMediaOutputController.mLocalMediaManager = mLocalMediaManager; - mMediaOutputDialog = makeTestDialog(mMediaOutputController); + mMediaSwitchingController.mLocalMediaManager = mLocalMediaManager; + mMediaOutputDialog = makeTestDialog(mMediaSwitchingController); mMediaOutputDialog.show(); when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice); @@ -388,12 +388,15 @@ public class MediaOutputDialogTest extends SysuiTestCase { public void getStopButtonText_notSupportsBroadcast_returnsDefaultText() { String stopText = mContext.getText( R.string.media_output_dialog_button_stop_casting).toString(); - MediaOutputController mockMediaOutputController = mock(MediaOutputController.class); - when(mockMediaOutputController.isBroadcastSupported()).thenReturn(false); - - withTestDialog(mockMediaOutputController, testDialog -> { - assertThat(testDialog.getStopButtonText().toString()).isEqualTo(stopText); - }); + MediaSwitchingController mockMediaSwitchingController = + mock(MediaSwitchingController.class); + when(mockMediaSwitchingController.isBroadcastSupported()).thenReturn(false); + + withTestDialog( + mockMediaSwitchingController, + testDialog -> { + assertThat(testDialog.getStopButtonText().toString()).isEqualTo(stopText); + }); } @Test @@ -401,28 +404,35 @@ public class MediaOutputDialogTest extends SysuiTestCase { public void getStopButtonText_supportsBroadcast_returnsBroadcastText() { String stopText = mContext.getText(R.string.media_output_broadcast).toString(); MediaDevice mMediaDevice = mock(MediaDevice.class); - MediaOutputController mockMediaOutputController = mock(MediaOutputController.class); - when(mockMediaOutputController.isBroadcastSupported()).thenReturn(true); - when(mockMediaOutputController.getCurrentConnectedMediaDevice()).thenReturn(mMediaDevice); - when(mockMediaOutputController.isBluetoothLeDevice(any())).thenReturn(true); - when(mockMediaOutputController.isPlaying()).thenReturn(true); - when(mockMediaOutputController.isBluetoothLeBroadcastEnabled()).thenReturn(false); - withTestDialog(mockMediaOutputController, testDialog -> { - assertThat(testDialog.getStopButtonText().toString()).isEqualTo(stopText); - }); + MediaSwitchingController mockMediaSwitchingController = + mock(MediaSwitchingController.class); + when(mockMediaSwitchingController.isBroadcastSupported()).thenReturn(true); + when(mockMediaSwitchingController.getCurrentConnectedMediaDevice()) + .thenReturn(mMediaDevice); + when(mockMediaSwitchingController.isBluetoothLeDevice(any())).thenReturn(true); + when(mockMediaSwitchingController.isPlaying()).thenReturn(true); + when(mockMediaSwitchingController.isBluetoothLeBroadcastEnabled()).thenReturn(false); + withTestDialog( + mockMediaSwitchingController, + testDialog -> { + assertThat(testDialog.getStopButtonText().toString()).isEqualTo(stopText); + }); } @Test public void onStopButtonClick_notPlaying_releaseSession() { - MediaOutputController mockMediaOutputController = mock(MediaOutputController.class); - when(mockMediaOutputController.isBroadcastSupported()).thenReturn(false); - when(mockMediaOutputController.getCurrentConnectedMediaDevice()).thenReturn(null); - when(mockMediaOutputController.isPlaying()).thenReturn(false); - withTestDialog(mockMediaOutputController, testDialog -> { - testDialog.onStopButtonClick(); - }); - - verify(mockMediaOutputController).releaseSession(); + MediaSwitchingController mockMediaSwitchingController = + mock(MediaSwitchingController.class); + when(mockMediaSwitchingController.isBroadcastSupported()).thenReturn(false); + when(mockMediaSwitchingController.getCurrentConnectedMediaDevice()).thenReturn(null); + when(mockMediaSwitchingController.isPlaying()).thenReturn(false); + withTestDialog( + mockMediaSwitchingController, + testDialog -> { + testDialog.onStopButtonClick(); + }); + + verify(mockMediaSwitchingController).releaseSession(); verify(mDialogTransitionAnimator).disableAllCurrentDialogsExitAnimations(); } @@ -430,14 +440,14 @@ public class MediaOutputDialogTest extends SysuiTestCase { // Check the visibility metric logging by creating a new MediaOutput dialog, // and verify if the calling times increases. public void onCreate_ShouldLogVisibility() { - withTestDialog(mMediaOutputController, testDialog -> {}); + withTestDialog(mMediaSwitchingController, testDialog -> {}); verify(mUiEventLogger, times(2)) .log(MediaOutputDialog.MediaOutputEvent.MEDIA_OUTPUT_DIALOG_SHOW); } @NonNull - private MediaOutputDialog makeTestDialog(MediaOutputController controller) { + private MediaOutputDialog makeTestDialog(MediaSwitchingController controller) { return new MediaOutputDialog( mContext, false, @@ -448,7 +458,8 @@ public class MediaOutputDialogTest extends SysuiTestCase { true); } - private void withTestDialog(MediaOutputController controller, Consumer<MediaOutputDialog> c) { + private void withTestDialog( + MediaSwitchingController controller, Consumer<MediaOutputDialog> c) { MediaOutputDialog testDialog = makeTestDialog(controller); testDialog.show(); c.accept(testDialog); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaSwitchingControllerTest.java index 714fad9d7478..d3e20c6e39b7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaSwitchingControllerTest.java @@ -43,6 +43,7 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.media.AudioDeviceAttributes; +import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.media.MediaDescription; import android.media.MediaMetadata; @@ -58,6 +59,7 @@ import android.os.Bundle; import android.os.PowerExemptionManager; import android.os.RemoteException; import android.os.UserHandle; +import android.platform.test.annotations.EnableFlags; import android.service.notification.StatusBarNotification; import android.testing.TestableLooper; import android.text.TextUtils; @@ -67,8 +69,10 @@ import androidx.core.graphics.drawable.IconCompat; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.media.flags.Flags; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.media.InputMediaDevice; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; import com.android.systemui.SysuiTestCase; @@ -101,7 +105,7 @@ import java.util.List; @SmallTest @RunWith(AndroidJUnit4.class) @TestableLooper.RunWithLooper(setAsMainLooper = true) -public class MediaOutputControllerTest extends SysuiTestCase { +public class MediaSwitchingControllerTest extends SysuiTestCase { private static final String TEST_DEVICE_1_ID = "test_device_1_id"; private static final String TEST_DEVICE_2_ID = "test_device_2_id"; private static final String TEST_DEVICE_3_ID = "test_device_3_id"; @@ -126,8 +130,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager; @Mock private LocalBluetoothManager mLocalBluetoothManager; - @Mock - private MediaOutputController.Callback mCb; + @Mock private MediaSwitchingController.Callback mCb; @Mock private MediaDevice mMediaDevice1; @Mock @@ -166,7 +169,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { private FeatureFlags mFlags = mock(FeatureFlags.class); private View mDialogLaunchView = mock(View.class); - private MediaOutputController.Callback mCallback = mock(MediaOutputController.Callback.class); + private MediaSwitchingController.Callback mCallback = + mock(MediaSwitchingController.Callback.class); final Notification mNotification = mock(Notification.class); private final VolumePanelGlobalStateInteractor mVolumePanelGlobalStateInteractor = @@ -175,7 +179,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { private Context mSpyContext; private String mPackageName = null; - private MediaOutputController mMediaOutputController; + private MediaSwitchingController mMediaSwitchingController; private LocalMediaManager mLocalMediaManager; private List<MediaController> mMediaControllers = new ArrayList<>(); private List<MediaDevice> mMediaDevices = new ArrayList<>(); @@ -203,9 +207,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn( mCachedBluetoothDeviceManager); - - mMediaOutputController = - new MediaOutputController( + mMediaSwitchingController = + new MediaSwitchingController( mSpyContext, mPackageName, mContext.getUser(), @@ -222,9 +225,9 @@ public class MediaOutputControllerTest extends SysuiTestCase { mFlags, mVolumePanelGlobalStateInteractor, mUserTracker); - mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager); + mLocalMediaManager = spy(mMediaSwitchingController.mLocalMediaManager); when(mLocalMediaManager.isPreferenceRouteListingExist()).thenReturn(false); - mMediaOutputController.mLocalMediaManager = mLocalMediaManager; + mMediaSwitchingController.mLocalMediaManager = mLocalMediaManager; MediaDescription.Builder builder = new MediaDescription.Builder(); builder.setTitle(TEST_SONG); builder.setSubtitle(TEST_ARTIST); @@ -264,26 +267,26 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void start_verifyLocalMediaManagerInit() { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); - verify(mLocalMediaManager).registerCallback(mMediaOutputController); + verify(mLocalMediaManager).registerCallback(mMediaSwitchingController); verify(mLocalMediaManager).startScan(); } @Test public void stop_verifyLocalMediaManagerDeinit() { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mLocalMediaManager); - mMediaOutputController.stop(); + mMediaSwitchingController.stop(); - verify(mLocalMediaManager).unregisterCallback(mMediaOutputController); + verify(mLocalMediaManager).unregisterCallback(mMediaSwitchingController); verify(mLocalMediaManager).stopScan(); } @Test public void start_notificationNotFound_mediaControllerInitFromSession() { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); verify(mSessionMediaController).registerCallback(any()); } @@ -291,7 +294,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void start_MediaNotificationFound_mediaControllerNotInitFromSession() { when(mNotification.isMediaNotification()).thenReturn(true); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); verify(mSessionMediaController, never()).registerCallback(any()); verifyZeroInteractions(mMediaSessionManager); @@ -299,8 +302,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void start_withoutPackageName_verifyMediaControllerInit() { - mMediaOutputController = - new MediaOutputController( + mMediaSwitchingController = + new MediaSwitchingController( mSpyContext, null, mContext.getUser(), @@ -318,32 +321,32 @@ public class MediaOutputControllerTest extends SysuiTestCase { mVolumePanelGlobalStateInteractor, mUserTracker); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); verify(mSessionMediaController, never()).registerCallback(any()); } @Test public void start_nearbyMediaDevicesManagerNotNull_registersNearbyDevicesCallback() { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); verify(mNearbyMediaDevicesManager).registerNearbyDevicesCallback(any()); } @Test public void stop_withPackageName_verifyMediaControllerDeinit() { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mSessionMediaController); - mMediaOutputController.stop(); + mMediaSwitchingController.stop(); verify(mSessionMediaController).unregisterCallback(any()); } @Test public void stop_withoutPackageName_verifyMediaControllerDeinit() { - mMediaOutputController = - new MediaOutputController( + mMediaSwitchingController = + new MediaSwitchingController( mSpyContext, null, mSpyContext.getUser(), @@ -361,26 +364,26 @@ public class MediaOutputControllerTest extends SysuiTestCase { mVolumePanelGlobalStateInteractor, mUserTracker); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); - mMediaOutputController.stop(); + mMediaSwitchingController.stop(); verify(mSessionMediaController, never()).unregisterCallback(any()); } @Test public void stop_nearbyMediaDevicesManagerNotNull_unregistersNearbyDevicesCallback() { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mSessionMediaController); - mMediaOutputController.stop(); + mMediaSwitchingController.stop(); verify(mNearbyMediaDevicesManager).unregisterNearbyDevicesCallback(any()); } @Test public void tryToLaunchMediaApplication_nullIntent_skip() { - mMediaOutputController.tryToLaunchMediaApplication(mDialogLaunchView); + mMediaSwitchingController.tryToLaunchMediaApplication(mDialogLaunchView); verify(mCb, never()).dismissDialog(); } @@ -391,9 +394,9 @@ public class MediaOutputControllerTest extends SysuiTestCase { .thenReturn(mController); Intent intent = new Intent(mPackageName); doReturn(intent).when(mPackageManager).getLaunchIntentForPackage(mPackageName); - mMediaOutputController.start(mCallback); + mMediaSwitchingController.start(mCallback); - mMediaOutputController.tryToLaunchMediaApplication(mDialogLaunchView); + mMediaSwitchingController.tryToLaunchMediaApplication(mDialogLaunchView); verify(mStarter).startActivity(any(Intent.class), anyBoolean(), Mockito.eq(mController)); @@ -403,11 +406,12 @@ public class MediaOutputControllerTest extends SysuiTestCase { public void tryToLaunchInAppRoutingIntent_componentNameNotNull_startActivity() { when(mDialogTransitionAnimator.createActivityTransitionController(any(View.class))) .thenReturn(mController); - mMediaOutputController.start(mCallback); + mMediaSwitchingController.start(mCallback); when(mLocalMediaManager.getLinkedItemComponentName()).thenReturn( new ComponentName(mPackageName, "")); - mMediaOutputController.tryToLaunchInAppRoutingIntent(TEST_DEVICE_1_ID, mDialogLaunchView); + mMediaSwitchingController.tryToLaunchInAppRoutingIntent( + TEST_DEVICE_1_ID, mDialogLaunchView); verify(mStarter).startActivity(any(Intent.class), anyBoolean(), Mockito.eq(mController)); @@ -415,9 +419,9 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void onDevicesUpdated_unregistersNearbyDevicesCallback() throws RemoteException { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); - mMediaOutputController.onDevicesUpdated(ImmutableList.of()); + mMediaSwitchingController.onDevicesUpdated(ImmutableList.of()); verify(mNearbyMediaDevicesManager).unregisterNearbyDevicesCallback(any()); } @@ -425,11 +429,11 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void onDeviceListUpdate_withNearbyDevices_updatesRangeInformation() throws RemoteException { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.onDevicesUpdated(mNearbyDevices); - mMediaOutputController.onDeviceListUpdate(mMediaDevices); + mMediaSwitchingController.onDevicesUpdated(mNearbyDevices); + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); verify(mMediaDevice1).setRangeZone(NearbyDevice.RANGE_FAR); verify(mMediaDevice2).setRangeZone(NearbyDevice.RANGE_CLOSE); @@ -438,11 +442,11 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void onDeviceListUpdate_withNearbyDevices_rankByRangeInformation() throws RemoteException { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.onDevicesUpdated(mNearbyDevices); - mMediaOutputController.onDeviceListUpdate(mMediaDevices); + mMediaSwitchingController.onDevicesUpdated(mNearbyDevices); + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); assertThat(mMediaDevices.get(0).getId()).isEqualTo(TEST_DEVICE_1_ID); } @@ -451,11 +455,11 @@ public class MediaOutputControllerTest extends SysuiTestCase { public void routeProcessSupport_onDeviceListUpdate_preferenceExist_NotUpdatesRangeInformation() throws RemoteException { when(mLocalMediaManager.isPreferenceRouteListingExist()).thenReturn(true); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.onDevicesUpdated(mNearbyDevices); - mMediaOutputController.onDeviceListUpdate(mMediaDevices); + mMediaSwitchingController.onDevicesUpdated(mNearbyDevices); + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); verify(mMediaDevice1, never()).setRangeZone(anyInt()); verify(mMediaDevice2, never()).setRangeZone(anyInt()); @@ -463,7 +467,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void onDeviceListUpdate_verifyDeviceListCallback() { - // This test relies on mMediaOutputController.start being called while the selected device + // This test relies on mMediaSwitchingController.start being called while the selected + // device // list has exactly one item, and that item's id is: // - Different from both ids in mMediaDevices. // - Different from the id of the route published by the device under test (usually the @@ -475,12 +480,12 @@ public class MediaOutputControllerTest extends SysuiTestCase { .when(mLocalMediaManager) .getSelectedMediaDevice(); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.onDeviceListUpdate(mMediaDevices); + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); final List<MediaDevice> devices = new ArrayList<>(); - for (MediaItem item : mMediaOutputController.getMediaItemList()) { + for (MediaItem item : mMediaSwitchingController.getMediaItemList()) { if (item.getMediaDevice().isPresent()) { devices.add(item.getMediaDevice().get()); } @@ -488,14 +493,15 @@ public class MediaOutputControllerTest extends SysuiTestCase { assertThat(devices.containsAll(mMediaDevices)).isTrue(); assertThat(devices.size()).isEqualTo(mMediaDevices.size()); - assertThat(mMediaOutputController.getMediaItemList().size()).isEqualTo( - mMediaDevices.size() + 2); + assertThat(mMediaSwitchingController.getMediaItemList().size()) + .isEqualTo(mMediaDevices.size() + 2); verify(mCb).onDeviceListChanged(); } @Test public void advanced_onDeviceListUpdateWithConnectedDeviceRemote_verifyItemSize() { - // This test relies on mMediaOutputController.start being called while the selected device + // This test relies on mMediaSwitchingController.start being called while the selected + // device // list has exactly one item, and that item's id is: // - Different from both ids in mMediaDevices. // - Different from the id of the route published by the device under test (usually the @@ -510,12 +516,12 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(mMediaDevice1.getFeatures()).thenReturn( ImmutableList.of(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK)); when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice1); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.onDeviceListUpdate(mMediaDevices); + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); final List<MediaDevice> devices = new ArrayList<>(); - for (MediaItem item : mMediaOutputController.getMediaItemList()) { + for (MediaItem item : mMediaSwitchingController.getMediaItemList()) { if (item.getMediaDevice().isPresent()) { devices.add(item.getMediaDevice().get()); } @@ -523,23 +529,72 @@ public class MediaOutputControllerTest extends SysuiTestCase { assertThat(devices.containsAll(mMediaDevices)).isTrue(); assertThat(devices.size()).isEqualTo(mMediaDevices.size()); - assertThat(mMediaOutputController.getMediaItemList().size()).isEqualTo( - mMediaDevices.size() + 1); + assertThat(mMediaSwitchingController.getMediaItemList().size()) + .isEqualTo(mMediaDevices.size() + 1); verify(mCb).onDeviceListChanged(); } + @EnableFlags(Flags.FLAG_ENABLE_AUDIO_INPUT_DEVICE_ROUTING_AND_VOLUME_CONTROL) + @Test + public void onInputDeviceListUpdate_verifyDeviceListCallback() { + AudioDeviceInfo[] audioDeviceInfos = {}; + when(mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)) + .thenReturn(audioDeviceInfos); + mMediaSwitchingController.start(mCb); + + // Output devices have changed. + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); + + final int MAX_VOLUME = 1; + final int CURRENT_VOLUME = 0; + final boolean IS_VOLUME_FIXED = true; + final MediaDevice mediaDevice3 = + InputMediaDevice.create( + mContext, + TEST_DEVICE_3_ID, + AudioDeviceInfo.TYPE_BUILTIN_MIC, + MAX_VOLUME, + CURRENT_VOLUME, + IS_VOLUME_FIXED); + final MediaDevice mediaDevice4 = + InputMediaDevice.create( + mContext, + TEST_DEVICE_4_ID, + AudioDeviceInfo.TYPE_WIRED_HEADSET, + MAX_VOLUME, + CURRENT_VOLUME, + IS_VOLUME_FIXED); + final List<MediaDevice> inputDevices = new ArrayList<>(); + inputDevices.add(mediaDevice3); + inputDevices.add(mediaDevice4); + + // Input devices have changed. + mMediaSwitchingController.mInputDeviceCallback.onInputDeviceListUpdated(inputDevices); + + final List<MediaDevice> devices = new ArrayList<>(); + for (MediaItem item : mMediaSwitchingController.getMediaItemList()) { + if (item.getMediaDevice().isPresent()) { + devices.add(item.getMediaDevice().get()); + } + } + + assertThat(devices).containsAtLeastElementsIn(mMediaDevices); + assertThat(devices).hasSize(mMediaDevices.size() + inputDevices.size()); + verify(mCb, atLeastOnce()).onDeviceListChanged(); + } + @Test public void advanced_categorizeMediaItems_withSuggestedDevice_verifyDeviceListSize() { when(mMediaDevice1.isSuggestedDevice()).thenReturn(true); when(mMediaDevice2.isSuggestedDevice()).thenReturn(false); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.getMediaItemList().clear(); - mMediaOutputController.onDeviceListUpdate(mMediaDevices); + mMediaSwitchingController.getMediaItemList().clear(); + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); final List<MediaDevice> devices = new ArrayList<>(); int dividerSize = 0; - for (MediaItem item : mMediaOutputController.getMediaItemList()) { + for (MediaItem item : mMediaSwitchingController.getMediaItemList()) { if (item.getMediaDevice().isPresent()) { devices.add(item.getMediaDevice().get()); } @@ -556,33 +611,33 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void onDeviceListUpdate_isRefreshing_updatesNeedRefreshToTrue() { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.mIsRefreshing = true; + mMediaSwitchingController.mIsRefreshing = true; - mMediaOutputController.onDeviceListUpdate(mMediaDevices); + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); - assertThat(mMediaOutputController.mNeedRefresh).isTrue(); + assertThat(mMediaSwitchingController.mNeedRefresh).isTrue(); } @Test public void advanced_onDeviceListUpdate_isRefreshing_updatesNeedRefreshToTrue() { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.mIsRefreshing = true; + mMediaSwitchingController.mIsRefreshing = true; - mMediaOutputController.onDeviceListUpdate(mMediaDevices); + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); - assertThat(mMediaOutputController.mNeedRefresh).isTrue(); + assertThat(mMediaSwitchingController.mNeedRefresh).isTrue(); } @Test public void cancelMuteAwaitConnection_cancelsWithMediaManager() { when(mAudioManager.getMutingExpectedDevice()).thenReturn(mock(AudioDeviceAttributes.class)); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.cancelMuteAwaitConnection(); + mMediaSwitchingController.cancelMuteAwaitConnection(); verify(mAudioManager).cancelMuteAwaitConnection(any()); } @@ -590,17 +645,17 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void cancelMuteAwaitConnection_audioManagerIsNull_noAction() { when(mAudioManager.getMutingExpectedDevice()).thenReturn(null); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.cancelMuteAwaitConnection(); + mMediaSwitchingController.cancelMuteAwaitConnection(); verify(mAudioManager, never()).cancelMuteAwaitConnection(any()); } @Test public void getAppSourceName_packageNameIsNull_returnsNull() { - MediaOutputController testMediaOutputController = - new MediaOutputController( + MediaSwitchingController testMediaSwitchingController = + new MediaSwitchingController( mSpyContext, "", mSpyContext.getUser(), @@ -617,25 +672,25 @@ public class MediaOutputControllerTest extends SysuiTestCase { mFlags, mVolumePanelGlobalStateInteractor, mUserTracker); - testMediaOutputController.start(mCb); + testMediaSwitchingController.start(mCb); reset(mCb); - testMediaOutputController.getAppSourceName(); + testMediaSwitchingController.getAppSourceName(); - assertThat(testMediaOutputController.getAppSourceName()).isNull(); + assertThat(testMediaSwitchingController.getAppSourceName()).isNull(); } @Test public void isActiveItem_deviceNotConnected_returnsFalse() { when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2); - assertThat(mMediaOutputController.isActiveItem(mMediaDevice1)).isFalse(); + assertThat(mMediaSwitchingController.isActiveItem(mMediaDevice1)).isFalse(); } @Test public void getNotificationSmallIcon_packageNameIsNull_returnsNull() { - MediaOutputController testMediaOutputController = - new MediaOutputController( + MediaSwitchingController testMediaSwitchingController = + new MediaSwitchingController( mSpyContext, "", mSpyContext.getUser(), @@ -652,23 +707,23 @@ public class MediaOutputControllerTest extends SysuiTestCase { mFlags, mVolumePanelGlobalStateInteractor, mUserTracker); - testMediaOutputController.start(mCb); + testMediaSwitchingController.start(mCb); reset(mCb); - testMediaOutputController.getAppSourceName(); + testMediaSwitchingController.getAppSourceName(); - assertThat(testMediaOutputController.getNotificationSmallIcon()).isNull(); + assertThat(testMediaSwitchingController.getNotificationSmallIcon()).isNull(); } @Test public void refreshDataSetIfNeeded_needRefreshIsTrue_setsToFalse() { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.mNeedRefresh = true; + mMediaSwitchingController.mNeedRefresh = true; - mMediaOutputController.refreshDataSetIfNeeded(); + mMediaSwitchingController.refreshDataSetIfNeeded(); - assertThat(mMediaOutputController.mNeedRefresh).isFalse(); + assertThat(mMediaSwitchingController.mNeedRefresh).isFalse(); } @Test @@ -677,13 +732,13 @@ public class MediaOutputControllerTest extends SysuiTestCase { ImmutableList.of(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK)); when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice1); - assertThat(mMediaOutputController.isCurrentConnectedDeviceRemote()).isTrue(); + assertThat(mMediaSwitchingController.isCurrentConnectedDeviceRemote()).isTrue(); } @Test public void addDeviceToPlayMedia_callsLocalMediaManager() { - MediaOutputController testMediaOutputController = - new MediaOutputController( + MediaSwitchingController testMediaSwitchingController = + new MediaSwitchingController( mSpyContext, null, mSpyContext.getUser(), @@ -702,16 +757,16 @@ public class MediaOutputControllerTest extends SysuiTestCase { mUserTracker); LocalMediaManager mockLocalMediaManager = mock(LocalMediaManager.class); - testMediaOutputController.mLocalMediaManager = mockLocalMediaManager; + testMediaSwitchingController.mLocalMediaManager = mockLocalMediaManager; - testMediaOutputController.addDeviceToPlayMedia(mMediaDevice2); + testMediaSwitchingController.addDeviceToPlayMedia(mMediaDevice2); verify(mockLocalMediaManager).addDeviceToPlayMedia(mMediaDevice2); } @Test public void removeDeviceFromPlayMedia_callsLocalMediaManager() { - MediaOutputController testMediaOutputController = - new MediaOutputController( + MediaSwitchingController testMediaSwitchingController = + new MediaSwitchingController( mSpyContext, null, mSpyContext.getUser(), @@ -730,15 +785,15 @@ public class MediaOutputControllerTest extends SysuiTestCase { mUserTracker); LocalMediaManager mockLocalMediaManager = mock(LocalMediaManager.class); - testMediaOutputController.mLocalMediaManager = mockLocalMediaManager; + testMediaSwitchingController.mLocalMediaManager = mockLocalMediaManager; - testMediaOutputController.removeDeviceFromPlayMedia(mMediaDevice2); + testMediaSwitchingController.removeDeviceFromPlayMedia(mMediaDevice2); verify(mockLocalMediaManager).removeDeviceFromPlayMedia(mMediaDevice2); } @Test public void getDeselectableMediaDevice_triggersFromLocalMediaManager() { - mMediaOutputController.getDeselectableMediaDevice(); + mMediaSwitchingController.getDeselectableMediaDevice(); verify(mLocalMediaManager).getDeselectableMediaDevice(); } @@ -746,108 +801,108 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void adjustSessionVolume_adjustWithoutId_triggersFromLocalMediaManager() { int testVolume = 10; - mMediaOutputController.adjustSessionVolume(testVolume); + mMediaSwitchingController.adjustSessionVolume(testVolume); verify(mLocalMediaManager).adjustSessionVolume(testVolume); } @Test public void logInteractionAdjustVolume_triggersFromMetricLogger() { - MediaOutputMetricLogger spyMediaOutputMetricLogger = spy( - mMediaOutputController.mMetricLogger); - mMediaOutputController.mMetricLogger = spyMediaOutputMetricLogger; + MediaOutputMetricLogger spyMediaOutputMetricLogger = + spy(mMediaSwitchingController.mMetricLogger); + mMediaSwitchingController.mMetricLogger = spyMediaOutputMetricLogger; - mMediaOutputController.logInteractionAdjustVolume(mMediaDevice1); + mMediaSwitchingController.logInteractionAdjustVolume(mMediaDevice1); verify(spyMediaOutputMetricLogger).logInteractionAdjustVolume(mMediaDevice1); } @Test public void getSessionVolumeMax_triggersFromLocalMediaManager() { - mMediaOutputController.getSessionVolumeMax(); + mMediaSwitchingController.getSessionVolumeMax(); verify(mLocalMediaManager).getSessionVolumeMax(); } @Test public void getSessionVolume_triggersFromLocalMediaManager() { - mMediaOutputController.getSessionVolume(); + mMediaSwitchingController.getSessionVolume(); verify(mLocalMediaManager).getSessionVolume(); } @Test public void getSessionName_triggersFromLocalMediaManager() { - mMediaOutputController.getSessionName(); + mMediaSwitchingController.getSessionName(); verify(mLocalMediaManager).getSessionName(); } @Test public void releaseSession_triggersFromLocalMediaManager() { - mMediaOutputController.releaseSession(); + mMediaSwitchingController.releaseSession(); verify(mLocalMediaManager).releaseSession(); } @Test public void isAnyDeviceTransferring_noDevicesStateIsConnecting_returnsFalse() { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.onDeviceListUpdate(mMediaDevices); + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); - assertThat(mMediaOutputController.isAnyDeviceTransferring()).isFalse(); + assertThat(mMediaSwitchingController.isAnyDeviceTransferring()).isFalse(); } @Test public void isAnyDeviceTransferring_deviceStateIsConnecting_returnsTrue() { when(mMediaDevice1.getState()).thenReturn( LocalMediaManager.MediaDeviceState.STATE_CONNECTING); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.onDeviceListUpdate(mMediaDevices); + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); - assertThat(mMediaOutputController.isAnyDeviceTransferring()).isTrue(); + assertThat(mMediaSwitchingController.isAnyDeviceTransferring()).isTrue(); } @Test public void isAnyDeviceTransferring_advancedLayoutSupport() { when(mMediaDevice1.getState()).thenReturn( LocalMediaManager.MediaDeviceState.STATE_CONNECTING); - mMediaOutputController.start(mCb); - mMediaOutputController.onDeviceListUpdate(mMediaDevices); + mMediaSwitchingController.start(mCb); + mMediaSwitchingController.onDeviceListUpdate(mMediaDevices); - assertThat(mMediaOutputController.isAnyDeviceTransferring()).isTrue(); + assertThat(mMediaSwitchingController.isAnyDeviceTransferring()).isTrue(); } @Test public void isPlaying_stateIsNull() { when(mSessionMediaController.getPlaybackState()).thenReturn(null); - assertThat(mMediaOutputController.isPlaying()).isFalse(); + assertThat(mMediaSwitchingController.isPlaying()).isFalse(); } @Test public void onSelectedDeviceStateChanged_verifyCallback() { when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.connectDevice(mMediaDevice1); + mMediaSwitchingController.connectDevice(mMediaDevice1); - mMediaOutputController.onSelectedDeviceStateChanged(mMediaDevice1, - LocalMediaManager.MediaDeviceState.STATE_CONNECTED); + mMediaSwitchingController.onSelectedDeviceStateChanged( + mMediaDevice1, LocalMediaManager.MediaDeviceState.STATE_CONNECTED); verify(mCb).onRouteChanged(); } @Test public void onDeviceAttributesChanged_verifyCallback() { - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.onDeviceAttributesChanged(); + mMediaSwitchingController.onDeviceAttributesChanged(); verify(mCb).onRouteChanged(); } @@ -855,11 +910,11 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void onRequestFailed_verifyCallback() { when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice1); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); reset(mCb); - mMediaOutputController.connectDevice(mMediaDevice2); + mMediaSwitchingController.connectDevice(mMediaDevice2); - mMediaOutputController.onRequestFailed(0 /* reason */); + mMediaSwitchingController.onRequestFailed(0 /* reason */); verify(mCb, atLeastOnce()).onRouteChanged(); } @@ -868,37 +923,40 @@ public class MediaOutputControllerTest extends SysuiTestCase { public void getHeaderTitle_withoutMetadata_returnDefaultString() { when(mSessionMediaController.getMetadata()).thenReturn(null); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); - assertThat(mMediaOutputController.getHeaderTitle()).isEqualTo( - mContext.getText(R.string.controls_media_title)); + assertThat( + mMediaSwitchingController + .getHeaderTitle() + .equals(mContext.getText(R.string.controls_media_title))) + .isTrue(); } @Test public void getHeaderTitle_withMetadata_returnSongName() { when(mSessionMediaController.getMetadata()).thenReturn(mMediaMetadata); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); - assertThat(mMediaOutputController.getHeaderTitle()).isEqualTo(TEST_SONG); + assertThat(mMediaSwitchingController.getHeaderTitle().equals(TEST_SONG)).isTrue(); } @Test public void getHeaderSubTitle_withoutMetadata_returnNull() { when(mSessionMediaController.getMetadata()).thenReturn(null); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); - assertThat(mMediaOutputController.getHeaderSubTitle()).isNull(); + assertThat(mMediaSwitchingController.getHeaderSubTitle()).isNull(); } @Test public void getHeaderSubTitle_withMetadata_returnArtistName() { when(mSessionMediaController.getMetadata()).thenReturn(mMediaMetadata); - mMediaOutputController.start(mCb); + mMediaSwitchingController.start(mCb); - assertThat(mMediaOutputController.getHeaderSubTitle()).isEqualTo(TEST_ARTIST); + assertThat(mMediaSwitchingController.getHeaderSubTitle().equals(TEST_ARTIST)).isTrue(); } @Test @@ -911,8 +969,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { mRoutingSessionInfos.add(mRemoteSessionInfo); when(mLocalMediaManager.getRemoteRoutingSessions()).thenReturn(mRoutingSessionInfos); - assertThat(mMediaOutputController.getActiveRemoteMediaDevices()).containsExactly( - mRemoteSessionInfo); + assertThat(mMediaSwitchingController.getActiveRemoteMediaDevices()) + .containsExactly(mRemoteSessionInfo); } @Test @@ -933,7 +991,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { selectableMediaDevices.add(selectableMediaDevice2); doReturn(selectedMediaDevices).when(mLocalMediaManager).getSelectedMediaDevice(); doReturn(selectableMediaDevices).when(mLocalMediaManager).getSelectableMediaDevice(); - final List<MediaDevice> groupMediaDevices = mMediaOutputController.getGroupMediaDevices(); + final List<MediaDevice> groupMediaDevices = + mMediaSwitchingController.getGroupMediaDevices(); // Reset order selectedMediaDevices.clear(); selectedMediaDevices.add(selectedMediaDevice2); @@ -941,7 +1000,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { selectableMediaDevices.clear(); selectableMediaDevices.add(selectableMediaDevice2); selectableMediaDevices.add(selectableMediaDevice1); - final List<MediaDevice> newDevices = mMediaOutputController.getGroupMediaDevices(); + final List<MediaDevice> newDevices = mMediaSwitchingController.getGroupMediaDevices(); assertThat(newDevices.size()).isEqualTo(groupMediaDevices.size()); for (int i = 0; i < groupMediaDevices.size(); i++) { @@ -970,7 +1029,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { selectableMediaDevices.add(selectableMediaDevice2); doReturn(selectedMediaDevices).when(mLocalMediaManager).getSelectedMediaDevice(); doReturn(selectableMediaDevices).when(mLocalMediaManager).getSelectableMediaDevice(); - final List<MediaDevice> groupMediaDevices = mMediaOutputController.getGroupMediaDevices(); + final List<MediaDevice> groupMediaDevices = + mMediaSwitchingController.getGroupMediaDevices(); // Reset order selectedMediaDevices.clear(); selectedMediaDevices.add(selectedMediaDevice2); @@ -979,7 +1039,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { selectableMediaDevices.add(selectableMediaDevice3); selectableMediaDevices.add(selectableMediaDevice2); selectableMediaDevices.add(selectableMediaDevice1); - final List<MediaDevice> newDevices = mMediaOutputController.getGroupMediaDevices(); + final List<MediaDevice> newDevices = mMediaSwitchingController.getGroupMediaDevices(); assertThat(newDevices.size()).isEqualTo(5); for (int i = 0; i < groupMediaDevices.size(); i++) { @@ -991,8 +1051,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void getNotificationLargeIcon_withoutPackageName_returnsNull() { - mMediaOutputController = - new MediaOutputController( + mMediaSwitchingController = + new MediaSwitchingController( mSpyContext, null, mSpyContext.getUser(), @@ -1010,7 +1070,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mVolumePanelGlobalStateInteractor, mUserTracker); - assertThat(mMediaOutputController.getNotificationIcon()).isNull(); + assertThat(mMediaSwitchingController.getNotificationIcon()).isNull(); } @Test @@ -1028,7 +1088,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(notification.isMediaNotification()).thenReturn(true); when(notification.getLargeIcon()).thenReturn(null); - assertThat(mMediaOutputController.getNotificationIcon()).isNull(); + assertThat(mMediaSwitchingController.getNotificationIcon()).isNull(); } @Test @@ -1047,7 +1107,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(notification.isMediaNotification()).thenReturn(true); when(notification.getLargeIcon()).thenReturn(icon); - assertThat(mMediaOutputController.getNotificationIcon()).isInstanceOf(IconCompat.class); + assertThat(mMediaSwitchingController.getNotificationIcon()).isInstanceOf(IconCompat.class); } @Test @@ -1066,7 +1126,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(notification.isMediaNotification()).thenReturn(false); when(notification.getLargeIcon()).thenReturn(icon); - assertThat(mMediaOutputController.getNotificationIcon()).isNull(); + assertThat(mMediaSwitchingController.getNotificationIcon()).isNull(); } @Test @@ -1084,7 +1144,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(notification.isMediaNotification()).thenReturn(true); when(notification.getSmallIcon()).thenReturn(null); - assertThat(mMediaOutputController.getNotificationSmallIcon()).isNull(); + assertThat(mMediaSwitchingController.getNotificationSmallIcon()).isNull(); } @Test @@ -1103,8 +1163,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(notification.isMediaNotification()).thenReturn(true); when(notification.getSmallIcon()).thenReturn(icon); - assertThat(mMediaOutputController.getNotificationSmallIcon()).isInstanceOf( - IconCompat.class); + assertThat(mMediaSwitchingController.getNotificationSmallIcon()) + .isInstanceOf(IconCompat.class); } @Test @@ -1112,8 +1172,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2); when(mMediaDevice1.getIcon()).thenReturn(mDrawable); - assertThat(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).isInstanceOf( - IconCompat.class); + assertThat(mMediaSwitchingController.getDeviceIconCompat(mMediaDevice1)) + .isInstanceOf(IconCompat.class); } @Test @@ -1121,13 +1181,13 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2); when(mMediaDevice1.getIcon()).thenReturn(null); - assertThat(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).isInstanceOf( - IconCompat.class); + assertThat(mMediaSwitchingController.getDeviceIconCompat(mMediaDevice1)) + .isInstanceOf(IconCompat.class); } @Test public void setColorFilter_setColorFilterToDrawable() { - mMediaOutputController.setColorFilter(mDrawable, true); + mMediaSwitchingController.setColorFilter(mDrawable, true); verify(mDrawable).setColorFilter(any(PorterDuffColorFilter.class)); } @@ -1150,11 +1210,11 @@ public class MediaOutputControllerTest extends SysuiTestCase { selectableMediaDevices.add(selectableMediaDevice2); doReturn(selectedMediaDevices).when(mLocalMediaManager).getSelectedMediaDevice(); doReturn(selectableMediaDevices).when(mLocalMediaManager).getSelectableMediaDevice(); - assertThat(mMediaOutputController.getGroupMediaDevices().isEmpty()).isFalse(); + assertThat(mMediaSwitchingController.getGroupMediaDevices().isEmpty()).isFalse(); - mMediaOutputController.resetGroupMediaDevices(); + mMediaSwitchingController.resetGroupMediaDevices(); - assertThat(mMediaOutputController.mGroupMediaDevices.isEmpty()).isTrue(); + assertThat(mMediaSwitchingController.mGroupMediaDevices.isEmpty()).isTrue(); } @Test @@ -1164,7 +1224,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(mMediaDevice1.isVolumeFixed()).thenReturn(true); - assertThat(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).isFalse(); + assertThat(mMediaSwitchingController.isVolumeControlEnabled(mMediaDevice1)).isFalse(); } @Test @@ -1174,7 +1234,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(mMediaDevice1.isVolumeFixed()).thenReturn(false); - assertThat(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).isTrue(); + assertThat(mMediaSwitchingController.isVolumeControlEnabled(mMediaDevice1)).isTrue(); } @Test @@ -1187,7 +1247,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(mMediaDevice2.getDeviceType()).thenReturn( MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE); - mMediaOutputController.setTemporaryAllowListExceptionIfNeeded(mMediaDevice2); + mMediaSwitchingController.setTemporaryAllowListExceptionIfNeeded(mMediaDevice2); verify(mPowerExemptionManager).addToTemporaryAllowList(anyString(), anyInt(), anyString(), anyLong()); @@ -1195,8 +1255,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void setTemporaryAllowListExceptionIfNeeded_packageNameIsNull_NoAction() { - MediaOutputController testMediaOutputController = - new MediaOutputController( + MediaSwitchingController testMediaSwitchingController = + new MediaSwitchingController( mSpyContext, null, mSpyContext.getUser(), @@ -1214,7 +1274,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mVolumePanelGlobalStateInteractor, mUserTracker); - testMediaOutputController.setTemporaryAllowListExceptionIfNeeded(mMediaDevice2); + testMediaSwitchingController.setTemporaryAllowListExceptionIfNeeded(mMediaDevice2); verify(mPowerExemptionManager, never()).addToTemporaryAllowList(anyString(), anyInt(), anyString(), @@ -1223,22 +1283,22 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void onMetadataChanged_triggersOnMetadataChanged() { - mMediaOutputController.mCallback = this.mCallback; + mMediaSwitchingController.mCallback = this.mCallback; - mMediaOutputController.mCb.onMetadataChanged(mMediaMetadata); + mMediaSwitchingController.mCb.onMetadataChanged(mMediaMetadata); - verify(mMediaOutputController.mCallback).onMediaChanged(); + verify(mMediaSwitchingController.mCallback).onMediaChanged(); } @Test public void onPlaybackStateChanged_updateWithNullState_onMediaStoppedOrPaused() { when(mPlaybackState.getState()).thenReturn(PlaybackState.STATE_PLAYING); - mMediaOutputController.mCallback = this.mCallback; - mMediaOutputController.start(mCb); + mMediaSwitchingController.mCallback = this.mCallback; + mMediaSwitchingController.start(mCb); - mMediaOutputController.mCb.onPlaybackStateChanged(null); + mMediaSwitchingController.mCb.onPlaybackStateChanged(null); - verify(mMediaOutputController.mCallback).onMediaStoppedOrPaused(); + verify(mMediaSwitchingController.mCallback).onMediaStoppedOrPaused(); } @Test @@ -1246,9 +1306,9 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(mDialogTransitionAnimator.createActivityTransitionController(mDialogLaunchView)) .thenReturn(mActivityTransitionAnimatorController); when(mKeyguardManager.isKeyguardLocked()).thenReturn(true); - mMediaOutputController.mCallback = this.mCallback; + mMediaSwitchingController.mCallback = this.mCallback; - mMediaOutputController.launchBluetoothPairing(mDialogLaunchView); + mMediaSwitchingController.launchBluetoothPairing(mDialogLaunchView); verify(mCallback).dismissDialog(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt index 1ec4814181ec..b86d57114f85 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt @@ -17,8 +17,12 @@ package com.android.systemui.notetask import android.app.role.RoleManager import android.app.role.RoleManager.ROLE_NOTES +import android.hardware.input.InputManager +import android.hardware.input.KeyGestureEvent import android.os.UserHandle import android.os.UserManager +import android.platform.test.annotations.EnableFlags +import android.platform.test.flag.junit.SetFlagsRule import android.view.KeyEvent import android.view.KeyEvent.ACTION_DOWN import android.view.KeyEvent.ACTION_UP @@ -42,6 +46,7 @@ import com.google.common.truth.Truth.assertThat import java.util.Optional import kotlinx.coroutines.ExperimentalCoroutinesApi import org.junit.Before +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock @@ -57,7 +62,11 @@ import org.mockito.MockitoAnnotations.initMocks @RunWith(AndroidJUnit4::class) internal class NoteTaskInitializerTest : SysuiTestCase() { + @get:Rule + val setFlagsRule = SetFlagsRule() + @Mock lateinit var commandQueue: CommandQueue + @Mock lateinit var inputManager: InputManager @Mock lateinit var bubbles: Bubbles @Mock lateinit var controller: NoteTaskController @Mock lateinit var roleManager: RoleManager @@ -86,6 +95,7 @@ internal class NoteTaskInitializerTest : SysuiTestCase() { roleManager = roleManager, userTracker = userTracker, keyguardUpdateMonitor = keyguardMonitor, + inputManager = inputManager, backgroundExecutor = executor, ) @@ -172,6 +182,26 @@ internal class NoteTaskInitializerTest : SysuiTestCase() { } @Test + @EnableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER) + fun initialize_handleKeyGestureEvent() { + val gestureEvent = KeyGestureEvent.Builder() + .setKeycodes(intArrayOf(KeyEvent.KEYCODE_N)) + .setModifierState(KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON) + .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES) + .setAction(KeyGestureEvent.ACTION_GESTURE_COMPLETE) + .build() + val underTest = createUnderTest(isEnabled = true, bubbles = bubbles) + underTest.initialize() + val callback = + withArgCaptor { verify(inputManager).registerKeyGestureEventHandler(capture()) } + + assertThat(callback.handleKeyGestureEvent(gestureEvent, null)).isTrue() + + executor.runAllReady() + verify(controller).showNoteTask(any()) + } + + @Test fun initialize_userUnlocked_shouldUpdateNoteTask() { whenever(keyguardMonitor.isUserUnlocked(userTracker.userId)).thenReturn(false) val underTest = createUnderTest(isEnabled = true, bubbles = bubbles) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt index 70af5e75105d..755adc68192a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt @@ -26,7 +26,6 @@ import androidx.compose.ui.test.assert import androidx.compose.ui.test.hasContentDescription import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.junit4.createComposeRule -import androidx.compose.ui.test.onChildAt import androidx.compose.ui.test.onChildren import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithTag @@ -40,6 +39,7 @@ import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon import com.android.systemui.qs.panels.shared.model.SizedTile import com.android.systemui.qs.panels.shared.model.SizedTileImpl +import com.android.systemui.qs.panels.ui.compose.infinitegrid.DefaultEditTileGrid import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel import com.android.systemui.qs.pipeline.shared.TileSpec import com.android.systemui.qs.shared.model.TileCategory @@ -57,7 +57,7 @@ class DragAndDropTest : SysuiTestCase() { @Composable private fun EditTileGridUnderTest( listState: EditTileListState, - onSetTiles: (List<TileSpec>) -> Unit + onSetTiles: (List<TileSpec>) -> Unit, ) { DefaultEditTileGrid( currentListState = listState, @@ -182,7 +182,7 @@ class DragAndDropTest : SysuiTestCase() { private fun ComposeContentTestRule.assertTileGridContainsExactly(specs: List<String>) { onNodeWithTag(CURRENT_TILES_GRID_TEST_TAG).onChildren().apply { fetchSemanticsNodes().forEachIndexed { index, _ -> - get(index).onChildAt(0).assert(hasContentDescription(specs[index])) + get(index).assert(hasContentDescription(specs[index])) } } } @@ -198,7 +198,7 @@ class DragAndDropTest : SysuiTestCase() { icon = Icon.Resource( android.R.drawable.star_on, - ContentDescription.Loaded(tileSpec) + ContentDescription.Loaded(tileSpec), ), label = AnnotatedString(tileSpec), appName = null, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index af043093b6f7..c710c56fd516 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -168,7 +168,7 @@ import com.android.systemui.statusbar.OperatorNameViewController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarStateControllerImpl; -import com.android.systemui.statusbar.core.StatusBarInitializer; +import com.android.systemui.statusbar.core.StatusBarInitializerImpl; import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepository; import com.android.systemui.statusbar.notification.NotifPipelineFlags; import com.android.systemui.statusbar.notification.NotificationActivityStarter; @@ -504,7 +504,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mock(FragmentService.class), mLightBarController, mAutoHideController, - new StatusBarInitializer( + new StatusBarInitializerImpl( mStatusBarWindowController, mCollapsedStatusBarFragmentProvider, emptySet()), diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java index 1e2648b228f3..ecc7909a857a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java @@ -20,7 +20,6 @@ import static android.media.AudioManager.RINGER_MODE_NORMAL; import static android.media.AudioManager.RINGER_MODE_SILENT; import static android.media.AudioManager.RINGER_MODE_VIBRATE; -import static com.android.systemui.Flags.FLAG_HAPTIC_VOLUME_SLIDER; import static com.android.systemui.volume.Events.DISMISS_REASON_UNKNOWN; import static com.android.systemui.volume.Events.SHOW_REASON_UNKNOWN; import static com.android.systemui.volume.VolumeDialogControllerImpl.DYNAMIC_STREAM_BROADCAST; @@ -51,7 +50,6 @@ import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.media.AudioSystem; import android.os.SystemClock; -import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.provider.Settings; import android.testing.TestableLooper; @@ -285,23 +283,8 @@ public class VolumeDialogImplTest extends SysuiTestCase { } @Test - @DisableFlags(FLAG_HAPTIC_VOLUME_SLIDER) - public void addSliderHaptics_withHapticsDisabled_doesNotDeliverOnProgressChangedHaptics() { - // GIVEN that the slider haptics flag is disabled and we try to add haptics to volume rows - mDialog.addSliderHapticsToRows(); - - // WHEN haptics try to be delivered to a volume stream - boolean canDeliverHaptics = - mDialog.canDeliverProgressHapticsToStream(AudioSystem.STREAM_MUSIC, true, 50); - - // THEN the result is that haptics are not successfully delivered - assertFalse(canDeliverHaptics); - } - - @Test - @EnableFlags(FLAG_HAPTIC_VOLUME_SLIDER) - public void addSliderHaptics_withHapticsEnabled_canDeliverOnProgressChangedHaptics() { - // GIVEN that the slider haptics flag is enabled and we try to add haptics to volume rows + public void addSliderHaptics_canDeliverOnProgressChangedHaptics() { + // GIVEN that the slider haptics are added to rows mDialog.addSliderHapticsToRows(); // WHEN haptics try to be delivered to a volume stream diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt index 649e4e8a6f7e..1b1d8c5d0f63 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt @@ -25,6 +25,8 @@ import com.android.systemui.authentication.shared.model.AuthenticationMethodMode import com.android.systemui.bouncer.domain.interactor.bouncerActionButtonInteractor import com.android.systemui.bouncer.domain.interactor.bouncerInteractor import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor +import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer +import com.android.systemui.haptics.msdl.bouncerHapticPlayer import com.android.systemui.inputmethod.domain.interactor.inputMethodInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture @@ -34,9 +36,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.StateFlow val Kosmos.bouncerUserActionsViewModel by Fixture { - BouncerUserActionsViewModel( - bouncerInteractor = bouncerInteractor, - ) + BouncerUserActionsViewModel(bouncerInteractor = bouncerInteractor) } val Kosmos.bouncerUserActionsViewModelFactory by Fixture { @@ -59,6 +59,7 @@ val Kosmos.bouncerSceneContentViewModel by Fixture { pinViewModelFactory = pinBouncerViewModelFactory, patternViewModelFactory = patternBouncerViewModelFactory, passwordViewModelFactory = passwordBouncerViewModelFactory, + bouncerHapticPlayer = bouncerHapticPlayer, ) } @@ -76,6 +77,7 @@ val Kosmos.pinBouncerViewModelFactory by Fixture { isInputEnabled: StateFlow<Boolean>, onIntentionalUserInput: () -> Unit, authenticationMethod: AuthenticationMethodModel, + bouncerHapticPlayer: BouncerHapticPlayer, ): PinBouncerViewModel { return PinBouncerViewModel( applicationContext = applicationContext, @@ -84,6 +86,7 @@ val Kosmos.pinBouncerViewModelFactory by Fixture { isInputEnabled = isInputEnabled, onIntentionalUserInput = onIntentionalUserInput, authenticationMethod = authenticationMethod, + bouncerHapticPlayer = bouncerHapticPlayer, ) } } @@ -92,6 +95,7 @@ val Kosmos.pinBouncerViewModelFactory by Fixture { val Kosmos.patternBouncerViewModelFactory by Fixture { object : PatternBouncerViewModel.Factory { override fun create( + bouncerHapticPlayer: BouncerHapticPlayer, isInputEnabled: StateFlow<Boolean>, onIntentionalUserInput: () -> Unit, ): PatternBouncerViewModel { @@ -100,6 +104,7 @@ val Kosmos.patternBouncerViewModelFactory by Fixture { interactor = bouncerInteractor, isInputEnabled = isInputEnabled, onIntentionalUserInput = onIntentionalUserInput, + bouncerHapticPlayer = bouncerHapticPlayer, ) } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorKosmos.kt index 1ed10fbe94c3..8922b2f5c5ef 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorKosmos.kt @@ -20,6 +20,7 @@ import com.android.systemui.authentication.domain.interactor.authenticationInter import com.android.systemui.deviceentry.data.repository.deviceEntryRepository import com.android.systemui.flags.fakeSystemPropertiesHelper import com.android.systemui.flags.systemPropertiesHelper +import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.keyguard.domain.interactor.trustInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture @@ -37,5 +38,6 @@ val Kosmos.deviceUnlockedInteractor by Fixture { powerInteractor = powerInteractor, biometricSettingsInteractor = deviceEntryBiometricSettingsInteractor, systemPropertiesHelper = fakeSystemPropertiesHelper, + keyguardTransitionInteractor = keyguardTransitionInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryKosmos.kt index 1d2bce2f9b99..1df3ef48d5a7 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryKosmos.kt @@ -19,7 +19,7 @@ package com.android.systemui.education.data.repository import com.android.systemui.kosmos.Kosmos import java.time.Instant -var Kosmos.contextualEducationRepository: ContextualEducationRepository by +var Kosmos.contextualEducationRepository: FakeContextualEducationRepository by Kosmos.Fixture { FakeContextualEducationRepository() } var Kosmos.fakeEduClock: FakeEduClock by Kosmos.Fixture { FakeEduClock(Instant.MIN) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/FakeContextualEducationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/FakeContextualEducationRepository.kt index fb4e2fb5fd14..4667bf5292fa 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/FakeContextualEducationRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/education/data/repository/FakeContextualEducationRepository.kt @@ -17,39 +17,77 @@ package com.android.systemui.education.data.repository import com.android.systemui.contextualeducation.GestureType +import com.android.systemui.contextualeducation.GestureType.ALL_APPS +import com.android.systemui.contextualeducation.GestureType.BACK +import com.android.systemui.contextualeducation.GestureType.HOME +import com.android.systemui.contextualeducation.GestureType.OVERVIEW import com.android.systemui.education.data.model.EduDeviceConnectionTime import com.android.systemui.education.data.model.GestureEduModel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.filterNotNull class FakeContextualEducationRepository : ContextualEducationRepository { - private val userGestureMap = mutableMapOf<Int, GestureEduModel>() - private val _gestureEduModels = MutableStateFlow(GestureEduModel(userId = 0)) - private val gestureEduModelsFlow = _gestureEduModels.asStateFlow() + private val userGestureMap = mutableMapOf<Int, MutableMap<GestureType, GestureEduModel>>() + + private val _backGestureEduModels = MutableStateFlow(GestureEduModel(BACK, userId = 0)) + private val backGestureEduModelsFlow = _backGestureEduModels.asStateFlow() + + private val _homeGestureEduModels = MutableStateFlow(GestureEduModel(HOME, userId = 0)) + private val homeEduModelsFlow = _homeGestureEduModels.asStateFlow() + + private val _allAppsGestureEduModels = MutableStateFlow(GestureEduModel(ALL_APPS, userId = 0)) + private val allAppsGestureEduModels = _allAppsGestureEduModels.asStateFlow() + + private val _overviewsGestureEduModels = MutableStateFlow(GestureEduModel(OVERVIEW, userId = 0)) + private val overviewsGestureEduModels = _overviewsGestureEduModels.asStateFlow() private val userEduDeviceConnectionTimeMap = mutableMapOf<Int, EduDeviceConnectionTime>() private val _eduDeviceConnectionTime = MutableStateFlow(EduDeviceConnectionTime()) private val eduDeviceConnectionTime = _eduDeviceConnectionTime.asStateFlow() + private val _keyboardShortcutTriggered = MutableStateFlow<GestureType?>(null) + private var currentUser: Int = 0 override fun setUser(userId: Int) { if (!userGestureMap.contains(userId)) { - userGestureMap[userId] = GestureEduModel(userId = userId) + userGestureMap[userId] = createGestureEduModelMap(userId = userId) userEduDeviceConnectionTimeMap[userId] = EduDeviceConnectionTime() } // save data of current user to the map - userGestureMap[currentUser] = _gestureEduModels.value - userEduDeviceConnectionTimeMap[currentUser] = _eduDeviceConnectionTime.value + val currentUserMap = userGestureMap[currentUser]!! + currentUserMap[BACK] = _backGestureEduModels.value + currentUserMap[HOME] = _homeGestureEduModels.value + currentUserMap[ALL_APPS] = _allAppsGestureEduModels.value + currentUserMap[OVERVIEW] = _overviewsGestureEduModels.value + // switch to data of new user - _gestureEduModels.value = userGestureMap[userId]!! + val newUserGestureMap = userGestureMap[userId]!! + newUserGestureMap[BACK]?.let { _backGestureEduModels.value = it } + newUserGestureMap[HOME]?.let { _homeGestureEduModels.value = it } + newUserGestureMap[ALL_APPS]?.let { _allAppsGestureEduModels.value = it } + newUserGestureMap[OVERVIEW]?.let { _overviewsGestureEduModels.value = it } + + userEduDeviceConnectionTimeMap[currentUser] = _eduDeviceConnectionTime.value _eduDeviceConnectionTime.value = userEduDeviceConnectionTimeMap[userId]!! } + private fun createGestureEduModelMap(userId: Int): MutableMap<GestureType, GestureEduModel> { + val gestureModelMap = mutableMapOf<GestureType, GestureEduModel>() + GestureType.values().forEach { gestureModelMap[it] = GestureEduModel(it, userId = userId) } + return gestureModelMap + } + override fun readGestureEduModelFlow(gestureType: GestureType): Flow<GestureEduModel> { - return gestureEduModelsFlow + return when (gestureType) { + BACK -> backGestureEduModelsFlow + HOME -> homeEduModelsFlow + ALL_APPS -> allAppsGestureEduModels + OVERVIEW -> overviewsGestureEduModels + } } override fun readEduDeviceConnectionTime(): Flow<EduDeviceConnectionTime> { @@ -60,8 +98,16 @@ class FakeContextualEducationRepository : ContextualEducationRepository { gestureType: GestureType, transform: (GestureEduModel) -> GestureEduModel ) { - val currentModel = _gestureEduModels.value - _gestureEduModels.value = transform(currentModel) + val gestureModels = + when (gestureType) { + BACK -> _backGestureEduModels + HOME -> _homeGestureEduModels + ALL_APPS -> _allAppsGestureEduModels + OVERVIEW -> _overviewsGestureEduModels + } + + val currentModel = gestureModels.value + gestureModels.value = transform(currentModel) } override suspend fun updateEduDeviceConnectionTime( @@ -70,4 +116,11 @@ class FakeContextualEducationRepository : ContextualEducationRepository { val currentModel = _eduDeviceConnectionTime.value _eduDeviceConnectionTime.value = transform(currentModel) } + + override val keyboardShortcutTriggered: Flow<GestureType> + get() = _keyboardShortcutTriggered.filterNotNull() + + fun setKeyboardShortcutTriggered(gestureType: GestureType) { + _keyboardShortcutTriggered.value = gestureType + } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt index 80f6fc24ef2c..2d275f9e9691 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorKosmos.kt @@ -40,8 +40,7 @@ var Kosmos.keyboardTouchpadEduInteractor by touchpadRepository, userRepository ), - clock = fakeEduClock, - inputManager = mockEduInputManager + clock = fakeEduClock ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt index c252924f4d2d..c0152b26d7a3 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt @@ -17,7 +17,6 @@ package com.android.systemui.flags import android.platform.test.annotations.EnableFlags -import com.android.systemui.Flags.FLAG_COMPOSE_LOCKSCREEN import com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR import com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR import com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR @@ -31,7 +30,6 @@ import com.android.systemui.Flags.FLAG_SCENE_CONTAINER * that feature. It is also picked up by [SceneContainerRule] to set non-aconfig prerequisites. */ @EnableFlags( - FLAG_COMPOSE_LOCKSCREEN, FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR, FLAG_KEYGUARD_WM_STATE_REFACTOR, FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt index 5ad973a54252..2b81da33b9bc 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt @@ -20,8 +20,10 @@ import com.google.android.msdl.data.model.FeedbackLevel import com.google.android.msdl.data.model.MSDLToken import com.google.android.msdl.domain.InteractionProperties import com.google.android.msdl.domain.MSDLPlayer +import com.google.android.msdl.logging.MSDLEvent class FakeMSDLPlayer : MSDLPlayer { + private val history = arrayListOf<MSDLEvent>() var currentFeedbackLevel = FeedbackLevel.DEFAULT var latestTokenPlayed: MSDLToken? = null private set @@ -34,5 +36,8 @@ class FakeMSDLPlayer : MSDLPlayer { override fun playToken(token: MSDLToken, properties: InteractionProperties?) { latestTokenPlayed = token latestPropertiesPlayed = properties + history.add(MSDLEvent(token, properties)) } + + override fun getHistory(): List<MSDLEvent> = history } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt index ca748b661d04..80db1e9b5e29 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/qs/QSLongPressEffectKosmos.kt @@ -16,6 +16,7 @@ package com.android.systemui.haptics.qs +import com.android.systemui.classifier.fakeFalsingManager import com.android.systemui.haptics.vibratorHelper import com.android.systemui.kosmos.Kosmos import com.android.systemui.log.core.FakeLogBuffer @@ -26,6 +27,7 @@ val Kosmos.qsLongPressEffect by QSLongPressEffect( vibratorHelper, keyguardStateController, + fakeFalsingManager, FakeLogBuffer.Factory.create(), ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridConsistencyInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridConsistencyInteractorKosmos.kt deleted file mode 100644 index edbc4c1cd65e..000000000000 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridConsistencyInteractorKosmos.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.qs.panels.domain.interactor - -import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.applicationCoroutineScope -import com.android.systemui.log.core.FakeLogBuffer -import com.android.systemui.qs.pipeline.domain.interactor.currentTilesInteractor - -val Kosmos.gridConsistencyInteractor by - Kosmos.Fixture { - GridConsistencyInteractor( - gridLayoutTypeInteractor, - currentTilesInteractor, - gridConsistencyInteractorsMap, - noopGridConsistencyInteractor, - FakeLogBuffer.Factory.create(), - applicationCoroutineScope, - ) - } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorKosmos.kt index 34e99d3a9a3c..c9516429553b 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/GridLayoutTypeInteractorKosmos.kt @@ -27,6 +27,3 @@ val Kosmos.gridLayoutTypeInteractor by val Kosmos.gridLayoutMap: Map<GridLayoutType, GridLayout> by Kosmos.Fixture { mapOf(Pair(InfiniteGridLayoutType, infiniteGridLayout)) } - -var Kosmos.gridConsistencyInteractorsMap: Map<GridLayoutType, GridTypeConsistencyInteractor> by - Kosmos.Fixture { mapOf(Pair(InfiniteGridLayoutType, infiniteGridConsistencyInteractor)) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridLayoutKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridLayoutKosmos.kt index be00152cb511..3f62b4d9f9cb 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridLayoutKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/domain/interactor/InfiniteGridLayoutKosmos.kt @@ -17,7 +17,7 @@ package com.android.systemui.qs.panels.domain.interactor import com.android.systemui.kosmos.Kosmos -import com.android.systemui.qs.panels.ui.compose.InfiniteGridLayout +import com.android.systemui.qs.panels.ui.compose.infinitegrid.InfiniteGridLayout import com.android.systemui.qs.panels.ui.viewmodel.fixedColumnsSizeViewModel import com.android.systemui.qs.panels.ui.viewmodel.iconTilesViewModel diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeRemoteInputRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeRemoteInputRepository.kt index c416ea1c1b39..91602c23ac17 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeRemoteInputRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeRemoteInputRepository.kt @@ -16,8 +16,13 @@ package com.android.systemui.statusbar.data.repository +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.flowOf class FakeRemoteInputRepository : RemoteInputRepository { override val isRemoteInputActive = MutableStateFlow(false) + override val remoteInputRowBottomBound: Flow<Float?> = flowOf(null) + + override fun setRemoteInputRowBottomBound(bottom: Float?) {} } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt index 6370a5d9c80b..7244d465ed7e 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt @@ -22,6 +22,7 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.shade.domain.interactor.shadeInteractor +import com.android.systemui.statusbar.domain.interactor.remoteInputInteractor import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationStackAppearanceInteractor val Kosmos.notificationScrollViewModel by Fixture { @@ -29,6 +30,7 @@ val Kosmos.notificationScrollViewModel by Fixture { dumpManager = dumpManager, stackAppearanceInteractor = notificationStackAppearanceInteractor, shadeInteractor = shadeInteractor, + remoteInputInteractor = remoteInputInteractor, sceneInteractor = sceneInteractor, keyguardInteractor = { keyguardInteractor }, ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt index 8bfc390ecfa3..e5cf0a90ebbd 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModelKosmos.kt @@ -22,6 +22,7 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.shade.domain.interactor.shadeInteractor +import com.android.systemui.statusbar.domain.interactor.remoteInputInteractor import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationStackAppearanceInteractor @@ -31,6 +32,7 @@ val Kosmos.notificationsPlaceholderViewModel by Fixture { sceneInteractor = sceneInteractor, shadeInteractor = shadeInteractor, headsUpNotificationInteractor = headsUpNotificationInteractor, + remoteInputInteractor = remoteInputInteractor, featureFlags = featureFlagsClassic, dumpManager = dumpManager, ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorKosmos.kt index 61b53c9a2067..99cd8309631e 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorKosmos.kt @@ -22,6 +22,8 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.testDispatcher import com.android.systemui.shared.notifications.data.repository.notificationSettingsRepository +import com.android.systemui.statusbar.policy.data.repository.deviceProvisioningRepository +import com.android.systemui.statusbar.policy.data.repository.userSetupRepository import com.android.systemui.statusbar.policy.data.repository.zenModeRepository val Kosmos.zenModeInteractor by Fixture { @@ -31,5 +33,7 @@ val Kosmos.zenModeInteractor by Fixture { notificationSettingsRepository = notificationSettingsRepository, bgDispatcher = testDispatcher, iconLoader = zenIconLoader, + deviceProvisioningRepository = deviceProvisioningRepository, + userSetupRepository = userSetupRepository, ) } diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt index a10097427ae5..57b58d8741da 100644 --- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt +++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt @@ -128,7 +128,11 @@ constructor( val currentDirection = if (angle < lastHingeAngle) FOLD_UPDATE_START_CLOSING else FOLD_UPDATE_START_OPENING - if (isTransitionInProgress && currentDirection != lastFoldUpdate) { + val changedDirectionWhileInTransition = + isTransitionInProgress && currentDirection != lastFoldUpdate + val unfoldedPastThresholdSinceLastTransition = + angle - lastHingeAngleBeforeTransition > HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES + if (changedDirectionWhileInTransition || unfoldedPastThresholdSinceLastTransition) { lastHingeAngleBeforeTransition = lastHingeAngle } @@ -153,7 +157,7 @@ constructor( isOnLargeScreen // Avoids sending closing event when on small screen. // Start event is sent regardless due to hall sensor. ) { - notifyFoldUpdate(transitionUpdate, lastHingeAngle) + notifyFoldUpdate(transitionUpdate, angle) } if (isTransitionInProgress) { diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java index c3d68cf04edd..93cdde0d9a20 100644 --- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java +++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java @@ -529,167 +529,6 @@ public class CameraExtensionsProxyService extends Service { */ public static Pair<PreviewExtenderImpl, ImageCaptureExtenderImpl> initializeExtension( int extensionType) { - if (Flags.concertModeApi()) { - if (extensionType == CameraExtensionCharacteristics.EXTENSION_EYES_FREE_VIDEOGRAPHY) { - // Basic extensions are deprecated starting with extension version 1.5 - return new Pair<>(new PreviewExtenderImpl() { - @Override - public boolean isExtensionAvailable(String cameraId, - CameraCharacteristics cameraCharacteristics) { - return false; - } - - @Override - public void init(String cameraId, CameraCharacteristics cameraCharacteristics) { - - } - - @Override - public androidx.camera.extensions.impl.CaptureStageImpl getCaptureStage() { - return null; - } - - @Override - public ProcessorType getProcessorType() { - return null; - } - - @Override - public ProcessorImpl getProcessor() { - return null; - } - - @Nullable - @Override - public List<Pair<Integer, Size[]>> getSupportedResolutions() { - return null; - } - - @Override - public void onInit(String cameraId, CameraCharacteristics cameraCharacteristics, - Context context) { } - - @Override - public void onDeInit() { } - - @Override - public androidx.camera.extensions.impl.CaptureStageImpl onPresetSession() { - return null; - } - - @Override - public androidx.camera.extensions.impl.CaptureStageImpl onEnableSession() { - return null; - } - - @Override - public androidx.camera.extensions.impl.CaptureStageImpl onDisableSession() { - return null; - } - - @Override - public int onSessionType() { - return 0; - } - }, new ImageCaptureExtenderImpl() { - @Override - public boolean isExtensionAvailable(String cameraId, - CameraCharacteristics cameraCharacteristics) { - return false; - } - - @Override - public void init(String cameraId, - CameraCharacteristics cameraCharacteristics) { } - - @Override - public CaptureProcessorImpl getCaptureProcessor() { - return null; - } - - @Override - public - List<androidx.camera.extensions.impl.CaptureStageImpl> getCaptureStages() { - return null; - } - - @Override - public int getMaxCaptureStage() { - return 0; - } - - @Override - public List<Pair<Integer, Size[]>> getSupportedResolutions() { - return null; - } - - @Override - public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions( - Size captureSize) { - return null; - } - - @Override - public Range<Long> getEstimatedCaptureLatencyRange( - Size captureOutputSize) { - return null; - } - - @Override - public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() { - return null; - } - - @Override - public List<CaptureResult.Key> getAvailableCaptureResultKeys() { - return null; - } - - @Override - public boolean isCaptureProcessProgressAvailable() { - return false; - } - - @Override - public Pair<Long, Long> getRealtimeCaptureLatency() { - return null; - } - - @Override - public boolean isPostviewAvailable() { - return false; - } - - @Override - public void onInit(String cameraId, - CameraCharacteristics cameraCharacteristics, Context context) { } - - @Override - public void onDeInit() { } - - @Override - public androidx.camera.extensions.impl.CaptureStageImpl onPresetSession() { - return null; - } - - @Override - public androidx.camera.extensions.impl.CaptureStageImpl onEnableSession() { - return null; - } - - @Override - public androidx.camera.extensions.impl.CaptureStageImpl onDisableSession() { - return null; - } - - @Override - public int onSessionType() { - return 0; - } - }); - } - } - switch (extensionType) { case CameraExtensionCharacteristics.EXTENSION_AUTOMATIC: return new Pair<>(new AutoPreviewExtenderImpl(), @@ -714,88 +553,6 @@ public class CameraExtensionsProxyService extends Service { * @hide */ public static AdvancedExtenderImpl initializeAdvancedExtensionImpl(int extensionType) { - if (Flags.concertModeApi()) { - if (extensionType == CameraExtensionCharacteristics.EXTENSION_EYES_FREE_VIDEOGRAPHY) { - if (EFV_SUPPORTED) { - return new EyesFreeVideographyAdvancedExtenderImpl(); - } else { - return new AdvancedExtenderImpl() { - @Override - public boolean isExtensionAvailable(String cameraId, - Map<String, CameraCharacteristics> characteristicsMap) { - return false; - } - - @Override - public void init(String cameraId, - Map<String, CameraCharacteristics> characteristicsMap) { - - } - - @Override - public Range<Long> getEstimatedCaptureLatencyRange(String cameraId, - Size captureOutputSize, int imageFormat) { - return null; - } - - @Override - public Map<Integer, List<Size>> getSupportedPreviewOutputResolutions( - String cameraId) { - return null; - } - - @Override - public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions( - String cameraId) { - return null; - } - - @Override - public Map<Integer, List<Size>> getSupportedPostviewResolutions( - Size captureSize) { - return null; - } - - @Override - public List<Size> getSupportedYuvAnalysisResolutions(String cameraId) { - return null; - } - - @Override - public SessionProcessorImpl createSessionProcessor() { - return null; - } - - @Override - public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() { - return null; - } - - @Override - public List<CaptureResult.Key> getAvailableCaptureResultKeys() { - return null; - } - - @Override - public boolean isCaptureProcessProgressAvailable() { - return false; - } - - @Override - public boolean isPostviewAvailable() { - return false; - } - - @Override - public List<Pair<CameraCharacteristics.Key, Object>> - getAvailableCharacteristicsKeyValues() { - return Collections.emptyList(); - } - }; - } - } - } - switch (extensionType) { case CameraExtensionCharacteristics.EXTENSION_AUTOMATIC: return new AutoAdvancedExtenderImpl(); diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp index d1a3bf9b529f..10e4f3820cd7 100644 --- a/ravenwood/Android.bp +++ b/ravenwood/Android.bp @@ -343,6 +343,8 @@ android_ravenwood_libgroup { data: [ ":framework-res", ":ravenwood-empty-res", + ":framework-platform-compat-config", + ":services-platform-compat-config", ], libs: [ "100-framework-minus-apex.ravenwood", diff --git a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRemove.java b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRemove.java index 6727327c99be..b69c63748d81 100644 --- a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRemove.java +++ b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRemove.java @@ -35,4 +35,18 @@ import java.lang.annotation.Target; @Target({TYPE, FIELD, METHOD, CONSTRUCTOR}) @Retention(RetentionPolicy.CLASS) public @interface RavenwoodRemove { + /** + * One or more classes that aren't yet supported by Ravenwood, which is why this method throws. + */ + Class<?>[] blockedBy() default {}; + + /** + * General free-form description of why this method throws. + */ + String reason() default ""; + + /** + * Tracking bug number, if any. + */ + long bug() default 0; } diff --git a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodReplace.java b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodReplace.java index 83a7b6e54389..57cdfd2240d0 100644 --- a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodReplace.java +++ b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodReplace.java @@ -42,4 +42,9 @@ public @interface RavenwoodReplace { * General free-form description of why this method is being replaced. */ String reason() default ""; + + /** + * Tracking bug number, if any. + */ + long bug() default 0; } diff --git a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodThrow.java b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodThrow.java index 0bb1f39cd453..19e6af1c478d 100644 --- a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodThrow.java +++ b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodThrow.java @@ -43,4 +43,9 @@ public @interface RavenwoodThrow { * General free-form description of why this method throws. */ String reason() default ""; + + /** + * Tracking bug number, if any. + */ + long bug() default 0; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridTypeConsistencyInteractor.kt b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNoConfigNoRuleTest.java index 4cdabaedc49e..d47330568828 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/GridTypeConsistencyInteractor.kt +++ b/ravenwood/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodNoConfigNoRuleTest.java @@ -13,15 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package com.android.ravenwoodtest.bivalenttest; -package com.android.systemui.qs.panels.domain.interactor +import static org.junit.Assert.assertNotNull; -import com.android.systemui.qs.pipeline.shared.TileSpec +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; -interface GridTypeConsistencyInteractor { - /** - * Given a list of tiles, return the best list of the same tiles (preserving as much order as - * possible, such that it's consistent with the current layout. - */ - fun reconcileTiles(tiles: List<TileSpec>): List<TileSpec> +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test to make sure the environment is still initialized when no config and no rules are set. + */ +@RunWith(AndroidJUnit4.class) +public class RavenwoodNoConfigNoRuleTest { + + @Test + public void testInitialization() { + assertNotNull(InstrumentationRegistry.getInstrumentation()); + } } diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java index 7a6f9e3669bb..478bead1354f 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java @@ -15,8 +15,6 @@ */ package android.platform.test.ravenwood; -import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERSION_JAVA_SYSPROP; - import static org.junit.Assert.fail; import android.os.Bundle; @@ -27,10 +25,6 @@ import android.util.Log; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.internal.os.RuntimeInit; -import com.android.platform.test.ravenwood.runtimehelper.ClassLoadHook; -import com.android.ravenwood.common.RavenwoodCommonUtils; - import org.junit.runner.Description; import org.junit.runners.model.TestClass; @@ -50,14 +44,16 @@ public class RavenwoodAwareTestRunnerHook { } /** + * Called before any code starts. Internally it will only initialize the environment once. + */ + public static void performGlobalInitialization() { + RavenwoodRuntimeEnvironmentController.globalInitOnce(); + } + + /** * Called when a runner starts, before the inner runner gets a chance to run. */ public static void onRunnerInitializing(RavenwoodAwareTestRunner runner, TestClass testClass) { - // TODO: Move the initialization code to a better place. - - initOnce(); - - // This log call also ensures the framework JNI is loaded. Log.i(TAG, "onRunnerInitializing: testClass=" + testClass.getJavaClass() + " runner=" + runner); @@ -65,33 +61,6 @@ public class RavenwoodAwareTestRunnerHook { InstrumentationRegistry.registerInstance(null, Bundle.EMPTY); } - private static boolean sInitialized = false; - - private static void initOnce() { - if (sInitialized) { - return; - } - sInitialized = true; - - // We haven't initialized liblog yet, so directly write to System.out here. - RavenwoodCommonUtils.log(TAG, "initOnce()"); - - // Make sure libandroid_runtime is loaded. - ClassLoadHook.onClassLoaded(Log.class); - - // Redirect stdout/stdin to liblog. - RuntimeInit.redirectLogStreams(); - - // This will let AndroidJUnit4 use the original runner. - System.setProperty("android.junit.runner", - "androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner"); - System.setProperty(RAVENWOOD_VERSION_JAVA_SYSPROP, "1"); - - // Do the basic set up for the android sysprops. - RavenwoodRuntimeEnvironmentController.setSystemProperties( - RavenwoodSystemProperties.DEFAULT_VALUES); - } - /** * Called when a whole test class is skipped. */ @@ -227,4 +196,4 @@ public class RavenwoodAwareTestRunnerHook { runner.mState.exitRavenwoodRule(rule); } -}
\ No newline at end of file +} diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodNativeLoader.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodNativeLoader.java new file mode 100644 index 000000000000..e5486117e7f2 --- /dev/null +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodNativeLoader.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.platform.test.ravenwood; + +import com.android.ravenwood.common.RavenwoodCommonUtils; + +import java.util.Arrays; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * We use this class to load libandroid_runtime. + * In the future, we may load other native libraries. + */ +public final class RavenwoodNativeLoader { + public static final String CORE_NATIVE_CLASSES = "core_native_classes"; + public static final String ICU_DATA_PATH = "icu.data.path"; + public static final String KEYBOARD_PATHS = "keyboard_paths"; + public static final String GRAPHICS_NATIVE_CLASSES = "graphics_native_classes"; + + public static final String LIBANDROID_RUNTIME_NAME = "android_runtime"; + + /** + * Classes with native methods that are backed by libandroid_runtime. + * + * See frameworks/base/core/jni/platform/host/HostRuntime.cpp + */ + private static final Class<?>[] sLibandroidClasses = { + android.util.Log.class, + android.os.Parcel.class, + android.os.Binder.class, + android.content.res.ApkAssets.class, + android.content.res.AssetManager.class, + android.content.res.StringBlock.class, + android.content.res.XmlBlock.class, + }; + + /** + * Classes with native methods that are backed by libhwui. + * + * See frameworks/base/libs/hwui/apex/LayoutlibLoader.cpp + */ + private static final Class<?>[] sLibhwuiClasses = { + android.graphics.Interpolator.class, + android.graphics.Matrix.class, + android.graphics.Path.class, + android.graphics.Color.class, + android.graphics.ColorSpace.class, + }; + + /** + * Extra strings needed to pass to register_android_graphics_classes(). + * + * `android.graphics.Graphics` is not actually a class, so we just hardcode it here. + */ + public final static String[] GRAPHICS_EXTRA_INIT_PARAMS = new String[] { + "android.graphics.Graphics" + }; + + private RavenwoodNativeLoader() { + } + + private static void log(String message) { + System.out.println("RavenwoodNativeLoader: " + message); + } + + private static void log(String fmt, Object... args) { + log(String.format(fmt, args)); + } + + private static void ensurePropertyNotSet(String key) { + if (System.getProperty(key) != null) { + throw new RuntimeException("System property \"" + key + "\" is set unexpectedly"); + } + } + + private static void setProperty(String key, String value) { + System.setProperty(key, value); + log("Property set: %s=\"%s\"", key, value); + } + + private static void dumpSystemProperties() { + for (var prop : System.getProperties().entrySet()) { + log(" %s=\"%s\"", prop.getKey(), prop.getValue()); + } + } + + /** + * libandroid_runtime uses Java's system properties to decide what JNI methods to set up. + * Set up these properties and load the native library + */ + public static void loadFrameworkNativeCode() { + if ("1".equals(System.getenv("RAVENWOOD_DUMP_PROPERTIES"))) { + log("Java system properties:"); + dumpSystemProperties(); + } + + // Make sure these properties are not set. + ensurePropertyNotSet(CORE_NATIVE_CLASSES); + ensurePropertyNotSet(ICU_DATA_PATH); + ensurePropertyNotSet(KEYBOARD_PATHS); + ensurePropertyNotSet(GRAPHICS_NATIVE_CLASSES); + + // Build the property values + final var joiner = Collectors.joining(","); + final var libandroidClasses = + Arrays.stream(sLibandroidClasses).map(Class::getName).collect(joiner); + final var libhwuiClasses = Stream.concat( + Arrays.stream(sLibhwuiClasses).map(Class::getName), + Arrays.stream(GRAPHICS_EXTRA_INIT_PARAMS) + ).collect(joiner); + + // Load the libraries + setProperty(CORE_NATIVE_CLASSES, libandroidClasses); + setProperty(GRAPHICS_NATIVE_CLASSES, libhwuiClasses); + log("Loading " + LIBANDROID_RUNTIME_NAME + " for '" + libandroidClasses + "' and '" + + libhwuiClasses + "'"); + RavenwoodCommonUtils.loadJniLibrary(LIBANDROID_RUNTIME_NAME); + } +} diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java index 04b67c45ad8e..03513ab0a2af 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java @@ -63,6 +63,7 @@ public final class RavenwoodRunnerState { private RavenwoodConfig mCurrentConfig; private RavenwoodRule mCurrentRule; + private boolean mHasRavenwoodRule; public Description getClassDescription() { return mClassDescription; @@ -71,6 +72,7 @@ public final class RavenwoodRunnerState { public void enterTestClass(Description classDescription) throws IOException { mClassDescription = classDescription; + mHasRavenwoodRule = hasRavenwoodRule(mRunner.getTestClass().getJavaClass()); mCurrentConfig = extractConfiguration(mRunner.getTestClass().getJavaClass()); if (mCurrentConfig != null) { @@ -97,9 +99,13 @@ public final class RavenwoodRunnerState { } public void enterRavenwoodRule(RavenwoodRule rule) throws IOException { + if (!mHasRavenwoodRule) { + fail("If you have a RavenwoodRule in your test, make sure the field type is" + + " RavenwoodRule so Ravenwood can detect it."); + } if (mCurrentConfig != null) { - fail("RavenwoodConfiguration and RavenwoodRule cannot be used in the same class." - + " Suggest migrating to RavenwoodConfiguration."); + fail("RavenwoodConfig and RavenwoodRule cannot be used in the same class." + + " Suggest migrating to RavenwoodConfig."); } if (mCurrentRule != null) { fail("Multiple nesting RavenwoodRule's are detected in the same class," @@ -125,16 +131,20 @@ public final class RavenwoodRunnerState { * @return a configuration from a test class, if any. */ @Nullable - private static RavenwoodConfig extractConfiguration(Class<?> testClass) { - final boolean hasRavenwoodRule = hasRavenwoodRule(testClass); - + private RavenwoodConfig extractConfiguration(Class<?> testClass) { var field = findConfigurationField(testClass); if (field == null) { - return null; + if (mHasRavenwoodRule) { + // Should be handled by RavenwoodRule + return null; + } + + // If no RavenwoodConfig and no RavenwoodRule, return a default config + return new RavenwoodConfig.Builder().build(); } - if (hasRavenwoodRule) { - fail("RavenwoodConfiguration and RavenwoodRule cannot be used in the same class." - + " Suggest migrating to RavenwoodConfiguration."); + if (mHasRavenwoodRule) { + fail("RavenwoodConfig and RavenwoodRule cannot be used in the same class." + + " Suggest migrating to RavenwoodConfig."); } try { @@ -155,7 +165,7 @@ public final class RavenwoodRunnerState { private static boolean hasRavenwoodRule(Class<?> testClass) { for (var field : testClass.getDeclaredFields()) { if (!field.isAnnotationPresent(Rule.class) - && field.isAnnotationPresent(ClassRule.class)) { + && !field.isAnnotationPresent(ClassRule.class)) { continue; } if (field.getType().equals(RavenwoodRule.class)) { @@ -165,7 +175,7 @@ public final class RavenwoodRunnerState { // JUnit supports rules as methods, so we need to check them too. for (var method : testClass.getDeclaredMethods()) { if (!method.isAnnotationPresent(Rule.class) - && method.isAnnotationPresent(ClassRule.class)) { + && !method.isAnnotationPresent(ClassRule.class)) { continue; } if (method.getReturnType().equals(RavenwoodRule.class)) { @@ -180,8 +190,8 @@ public final class RavenwoodRunnerState { } /** - * Find and return a field with @RavenwoodConfiguration.Config, which must be of type - * RavenwoodConfiguration. + * Find and return a field with @RavenwoodConfig.Config, which must be of type + * RavenwoodConfig. */ @Nullable private static Field findConfigurationField(Class<?> testClass) { @@ -198,7 +208,7 @@ public final class RavenwoodRunnerState { fail(String.format( "Class %s has multiple fields with %s", testClass.getCanonicalName(), - "@RavenwoodConfiguration.Config")); + "@RavenwoodConfig.Config")); } // Make sure it's static public ensureIsPublicMember(field, true); @@ -209,8 +219,8 @@ public final class RavenwoodRunnerState { "Field %s.%s has %s but type is not %s", testClass.getCanonicalName(), field.getName(), - "@RavenwoodConfiguration.Config", - "RavenwoodConfiguration")); + "@RavenwoodConfig.Config", + "RavenwoodConfig")); return null; // unreachable } } else { @@ -219,8 +229,8 @@ public final class RavenwoodRunnerState { "Field %s.%s does not have %s but type is %s", testClass.getCanonicalName(), field.getName(), - "@RavenwoodConfiguration.Config", - "RavenwoodConfiguration")); + "@RavenwoodConfig.Config", + "RavenwoodConfig")); return null; // unreachable } else { // Unrelated field, ignore. 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 f4756c5c58b3..241726283c52 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java @@ -18,6 +18,7 @@ package android.platform.test.ravenwood; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_RESOURCE_APK; 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.fail; @@ -31,10 +32,14 @@ import android.os.Bundle; import android.os.HandlerThread; import android.os.Looper; import android.os.ServiceManager; +import android.system.ErrnoException; +import android.system.Os; import android.util.Log; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.internal.os.RuntimeInit; +import com.android.ravenwood.common.RavenwoodCommonUtils; import com.android.ravenwood.common.RavenwoodRuntimeException; import com.android.ravenwood.common.SneakyThrow; import com.android.server.LocalServices; @@ -114,6 +119,43 @@ public class RavenwoodRuntimeEnvironmentController { } private static RavenwoodConfig sConfig; + private static boolean sInitialized = false; + + /** + * Initialize the global environment. + */ + public static void globalInitOnce() { + if (sInitialized) { + return; + } + sInitialized = true; + + // We haven't initialized liblog yet, so directly write to System.out here. + RavenwoodCommonUtils.log(TAG, "globalInit()"); + + // Do the basic set up for the android sysprops. + setSystemProperties(RavenwoodSystemProperties.DEFAULT_VALUES); + + // Make sure libandroid_runtime is loaded. + RavenwoodNativeLoader.loadFrameworkNativeCode(); + + // Redirect stdout/stdin to liblog. + RuntimeInit.redirectLogStreams(); + + if (RAVENWOOD_VERBOSE_LOGGING) { + RavenwoodCommonUtils.log(TAG, "Force enabling verbose logging"); + try { + Os.setenv("ANDROID_LOG_TAGS", "*:v", true); + } catch (ErrnoException e) { + // Shouldn't happen. + } + } + + System.setProperty(RAVENWOOD_VERSION_JAVA_SYSPROP, "1"); + // This will let AndroidJUnit4 use the original runner. + System.setProperty("android.junit.runner", + "androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner"); + } /** * Initialize the environment. diff --git a/ravenwood/junit-src/android/platform/test/annotations/DisabledOnRavenwood.java b/ravenwood/junit-src/android/platform/test/annotations/DisabledOnRavenwood.java index 1adb0f31da54..470165c6da43 100644 --- a/ravenwood/junit-src/android/platform/test/annotations/DisabledOnRavenwood.java +++ b/ravenwood/junit-src/android/platform/test/annotations/DisabledOnRavenwood.java @@ -51,4 +51,9 @@ public @interface DisabledOnRavenwood { * General free-form description of why this test is being ignored. */ String reason() default ""; + + /** + * Tracking bug number, if any. + */ + long bug() default 0; } diff --git a/ravenwood/junit-src/android/platform/test/annotations/IgnoreUnderRavenwood.java b/ravenwood/junit-src/android/platform/test/annotations/IgnoreUnderRavenwood.java index 7faa654b903c..1c06829dba06 100644 --- a/ravenwood/junit-src/android/platform/test/annotations/IgnoreUnderRavenwood.java +++ b/ravenwood/junit-src/android/platform/test/annotations/IgnoreUnderRavenwood.java @@ -51,4 +51,9 @@ public @interface IgnoreUnderRavenwood { * General free-form description of why this test is being ignored. */ String reason() default ""; + + /** + * Tracking bug number, if any. + */ + long bug() default 0; } diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java index cb8af0c01a1c..5d251bdafd44 100644 --- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java +++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java @@ -46,6 +46,7 @@ import org.junit.runner.notification.RunListener; import org.junit.runner.notification.RunNotifier; import org.junit.runner.notification.StoppedByUserException; import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.Suite; import org.junit.runners.model.MultipleFailureException; import org.junit.runners.model.RunnerBuilder; import org.junit.runners.model.Statement; @@ -170,6 +171,7 @@ public final class RavenwoodAwareTestRunner extends Runner implements Filterable private Runner mRealRunner = null; private Description mDescription = null; private Throwable mExceptionInConstructor = null; + private boolean mRealRunnerTakesRunnerBuilder = false; /** * Stores internal states / methods associated with this runner that's only needed in @@ -191,23 +193,27 @@ public final class RavenwoodAwareTestRunner extends Runner implements Filterable */ public RavenwoodAwareTestRunner(Class<?> testClass) { try { - mTestClass = new TestClass(testClass); - - Log.v(TAG, "RavenwoodAwareTestRunner starting for " + testClass.getCanonicalName()); - - onRunnerInitializing(); + performGlobalInitialization(); /* * If the class has @DisabledOnRavenwood, then we'll delegate to * ClassSkippingTestRunner, which simply skips it. + * + * We need to do it before instantiating TestClass for b/367694651. */ if (isOnRavenwood() && !RavenwoodAwareTestRunnerHook.shouldRunClassOnRavenwood( - mTestClass.getJavaClass())) { - mRealRunner = new ClassSkippingTestRunner(mTestClass); + testClass)) { + mRealRunner = new ClassSkippingTestRunner(testClass); mDescription = mRealRunner.getDescription(); return; } + mTestClass = new TestClass(testClass); + + Log.v(TAG, "RavenwoodAwareTestRunner starting for " + testClass.getCanonicalName()); + + onRunnerInitializing(); + // Find the real runner. final Class<? extends Runner> realRunnerClass; final InnerRunner innerRunnerAnnotation = mTestClass.getAnnotation(InnerRunner.class); @@ -243,7 +249,7 @@ public final class RavenwoodAwareTestRunner extends Runner implements Filterable } } - private static Runner instantiateRealRunner( + private Runner instantiateRealRunner( Class<? extends Runner> realRunnerClass, Class<?> testClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, @@ -251,12 +257,19 @@ public final class RavenwoodAwareTestRunner extends Runner implements Filterable try { return realRunnerClass.getConstructor(Class.class).newInstance(testClass); } catch (NoSuchMethodException e) { - var runnerBuilder = new AllDefaultPossibilitiesBuilder(); - return realRunnerClass.getConstructor(Class.class, - RunnerBuilder.class).newInstance(testClass, runnerBuilder); + var constructor = realRunnerClass.getConstructor(Class.class, RunnerBuilder.class); + mRealRunnerTakesRunnerBuilder = true; + return constructor.newInstance(testClass, new AllDefaultPossibilitiesBuilder()); } } + private void performGlobalInitialization() { + if (!isOnRavenwood()) { + return; + } + RavenwoodAwareTestRunnerHook.performGlobalInitialization(); + } + /** * Run the bare minimum setup to initialize the wrapped runner. */ @@ -265,7 +278,6 @@ public final class RavenwoodAwareTestRunner extends Runner implements Filterable if (!isOnRavenwood()) { return; } - // DO NOT USE android.util.Log before calling onRunnerInitializing(). RavenwoodAwareTestRunnerHook.onRunnerInitializing(this, mTestClass); @@ -317,14 +329,20 @@ public final class RavenwoodAwareTestRunner extends Runner implements Filterable return; } + // TODO(b/365976974): handle nested classes better + final boolean skipRunnerHook = + mRealRunnerTakesRunnerBuilder && mRealRunner instanceof Suite; + sCurrentRunner.set(this); try { - try { - RavenwoodAwareTestRunnerHook.onBeforeInnerRunnerStart( - this, getDescription()); - } catch (Throwable th) { - notifier.reportBeforeTestFailure(getDescription(), th); - return; + if (!skipRunnerHook) { + try { + RavenwoodAwareTestRunnerHook.onBeforeInnerRunnerStart( + this, getDescription()); + } catch (Throwable th) { + notifier.reportBeforeTestFailure(getDescription(), th); + return; + } } // Delegate to the inner runner. @@ -332,12 +350,13 @@ public final class RavenwoodAwareTestRunner extends Runner implements Filterable } finally { sCurrentRunner.remove(); - try { - RavenwoodAwareTestRunnerHook.onAfterInnerRunnerFinished( - this, getDescription()); - } catch (Throwable th) { - notifier.reportAfterTestFailure(th); - return; + if (!skipRunnerHook) { + try { + RavenwoodAwareTestRunnerHook.onAfterInnerRunnerFinished( + this, getDescription()); + } catch (Throwable th) { + notifier.reportAfterTestFailure(th); + } } } } @@ -427,14 +446,11 @@ public final class RavenwoodAwareTestRunner extends Runner implements Filterable * filter. */ private static class ClassSkippingTestRunner extends Runner implements Filterable { - private final TestClass mTestClass; private final Description mDescription; private boolean mFilteredOut; - ClassSkippingTestRunner(TestClass testClass) { - mTestClass = testClass; - mDescription = Description.createTestDescription( - testClass.getJavaClass(), testClass.getJavaClass().getSimpleName()); + ClassSkippingTestRunner(Class<?> testClass) { + mDescription = Description.createTestDescription(testClass, testClass.getSimpleName()); mFilteredOut = false; } diff --git a/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java b/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java index 0178b934a649..aa8c29936082 100644 --- a/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java +++ b/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java @@ -35,6 +35,12 @@ public class RavenwoodAwareTestRunnerHook { } /** + * Called before any code starts. Internally it will only initialize the environment once. + */ + public static void performGlobalInitialization() { + } + + /** * Called when a runner starts, before the inner runner gets a chance to run. */ public static void onRunnerInitializing(RavenwoodAwareTestRunner runner, TestClass testClass) { diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java index 790bb1c2373b..be8c44388435 100644 --- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java +++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java @@ -15,54 +15,10 @@ */ package com.android.platform.test.ravenwood.runtimehelper; -import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING; - -import android.system.ErrnoException; -import android.system.Os; - -import com.android.ravenwood.common.RavenwoodCommonUtils; - -import java.io.File; -import java.lang.reflect.Modifier; -import java.util.ArrayList; - /** * Standard class loader hook. - * - * Currently, we use this class to load libandroid_runtime (if needed). In the future, we may - * load other JNI or do other set up here. */ public class ClassLoadHook { - /** - * If true, we won't load `libandroid_runtime` - * - * <p>Looks like there's some complexity in running a host test with JNI with `atest`, - * so we need a way to remove the dependency. - */ - private static final boolean SKIP_LOADING_LIBANDROID = "1".equals(System.getenv( - "RAVENWOOD_SKIP_LOADING_LIBANDROID")); - - public static final String CORE_NATIVE_CLASSES = "core_native_classes"; - public static final String ICU_DATA_PATH = "icu.data.path"; - public static final String KEYBOARD_PATHS = "keyboard_paths"; - public static final String GRAPHICS_NATIVE_CLASSES = "graphics_native_classes"; - - public static final String LIBANDROID_RUNTIME_NAME = "android_runtime"; - - /** - * Extra strings needed to pass to register_android_graphics_classes(). - * - * `android.graphics.Graphics` is not actually a class, so we can't use the same initialization - * strategy than the "normal" classes. So we just hardcode it here. - */ - public static final String GRAPHICS_EXTRA_INIT_PARAMS = ",android.graphics.Graphics"; - - private static String sInitialDir = new File("").getAbsolutePath(); - - static { - log("Initialized. Current dir=" + sInitialDir); - } - private ClassLoadHook() { } @@ -75,144 +31,12 @@ public class ClassLoadHook { public static void onClassLoaded(Class<?> clazz) { System.out.println("Framework class loaded: " + clazz.getCanonicalName()); - loadFrameworkNativeCode(); - } - - private static void log(String message) { - System.out.println("ClassLoadHook: " + message); - } - - private static void log(String fmt, Object... args) { - log(String.format(fmt, args)); - } - - private static void ensurePropertyNotSet(String key) { - if (System.getProperty(key) != null) { - throw new RuntimeException("System property \"" + key + "\" is set unexpectedly"); + // Always try to initialize the environment in case classes are loaded before + // RavenwoodAwareTestRunner is initialized + try { + Class.forName("android.platform.test.ravenwood.RavenwoodRuntimeEnvironmentController") + .getMethod("globalInitOnce").invoke(null); + } catch (ReflectiveOperationException ignored) { } } - - private static void setProperty(String key, String value) { - System.setProperty(key, value); - log("Property set: %s=\"%s\"", key, value); - } - - private static void dumpSystemProperties() { - for (var prop : System.getProperties().entrySet()) { - log(" %s=\"%s\"", prop.getKey(), prop.getValue()); - } - } - - private static boolean sLoadFrameworkNativeCodeCalled = false; - - /** - * Load `libandroid_runtime` if needed. - */ - private static void loadFrameworkNativeCode() { - // This is called from class-initializers, so no synchronization is needed. - if (sLoadFrameworkNativeCodeCalled) { - return; - } - sLoadFrameworkNativeCodeCalled = true; - - // libandroid_runtime uses Java's system properties to decide what JNI methods to set up. - // Set up these properties for host-side tests. - - if ("1".equals(System.getenv("RAVENWOOD_DUMP_PROPERTIES"))) { - log("Java system properties:"); - dumpSystemProperties(); - } - - if (SKIP_LOADING_LIBANDROID) { - log("Skip loading native runtime."); - return; - } - - if (RAVENWOOD_VERBOSE_LOGGING) { - log("Force enabling verbose logging"); - try { - Os.setenv("ANDROID_LOG_TAGS", "*:v", true); - } catch (ErrnoException e) { - // Shouldn't happen. - } - } - - // Make sure these properties are not set. - ensurePropertyNotSet(CORE_NATIVE_CLASSES); - ensurePropertyNotSet(ICU_DATA_PATH); - ensurePropertyNotSet(KEYBOARD_PATHS); - ensurePropertyNotSet(GRAPHICS_NATIVE_CLASSES); - - // Load the libraries, if needed. - final var libanrdoidClasses = getClassesWithNativeMethods(sLibandroidClasses); - final var libhwuiClasses = getClassesWithNativeMethods(sLibhwuiClasses); - if (libanrdoidClasses.isEmpty() && libhwuiClasses.isEmpty()) { - log("No classes require JNI methods, skip loading native runtime."); - return; - } - setProperty(CORE_NATIVE_CLASSES, libanrdoidClasses); - setProperty(GRAPHICS_NATIVE_CLASSES, libhwuiClasses + GRAPHICS_EXTRA_INIT_PARAMS); - - log("Loading " + LIBANDROID_RUNTIME_NAME + " for '" + libanrdoidClasses + "' and '" - + libhwuiClasses + "'"); - RavenwoodCommonUtils.loadJniLibrary(LIBANDROID_RUNTIME_NAME); - } - - /** - * Classes with native methods that are backed by libandroid_runtime. - * - * See frameworks/base/core/jni/platform/host/HostRuntime.cpp - */ - private static final Class<?>[] sLibandroidClasses = { - android.util.Log.class, - android.os.Parcel.class, - android.os.Binder.class, - android.content.res.ApkAssets.class, - android.content.res.AssetManager.class, - android.content.res.StringBlock.class, - android.content.res.XmlBlock.class, - }; - - /** - * Classes with native methods that are backed by libhwui. - * - * See frameworks/base/libs/hwui/apex/LayoutlibLoader.cpp - */ - private static final Class<?>[] sLibhwuiClasses = { - android.graphics.Interpolator.class, - android.graphics.Matrix.class, - android.graphics.Path.class, - android.graphics.Color.class, - android.graphics.ColorSpace.class, - }; - - /** - * @return if a given class and its nested classes, if any, have any native method or not. - */ - private static boolean hasNativeMethod(Class<?> clazz) { - for (var nestedClass : clazz.getNestMembers()) { - for (var method : nestedClass.getDeclaredMethods()) { - if (Modifier.isNative(method.getModifiers())) { - return true; - } - } - } - return false; - } - /** - * Create a list of classes as comma-separated that require JNI methods to be set up from - * a given class list, ignoring classes with no native methods. - */ - private static String getClassesWithNativeMethods(Class<?>[] classes) { - final var coreNativeClassesToLoad = new ArrayList<String>(); - - for (var clazz : classes) { - if (hasNativeMethod(clazz)) { - log("Class %s has native methods", clazz.getCanonicalName()); - coreNativeClassesToLoad.add(clazz.getName()); - } - } - - return String.join(",", coreNativeClassesToLoad); - } } diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerCallbackTest.java b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerCallbackTest.java index 6d8fb983504b..09ed12d49cea 100644 --- a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerCallbackTest.java +++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerCallbackTest.java @@ -17,12 +17,14 @@ package com.android.ravenwoodtest.runnercallbacktests; import static org.junit.Assume.assumeTrue; +import android.platform.test.annotations.DisabledOnRavenwood; import android.platform.test.annotations.NoRavenizer; import android.platform.test.ravenwood.RavenwoodAwareTestRunner; import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.Assume; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -353,4 +355,34 @@ public class RavenwoodRunnerCallbackTest extends RavenwoodRunnerTestBase { public void test2() { } } + + /** + * The test class is unloadable, but has a @DisabledOnRavenwood. + */ + @RunWith(AndroidJUnit4.class) + @DisabledOnRavenwood + // CHECKSTYLE:OFF + @Expected(""" + testRunStarted: classes + testSuiteStarted: classes + testSuiteStarted: ClassUnloadbleTest(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerCallbackTest$ClassUnloadbleTest) + testIgnored: ClassUnloadbleTest(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerCallbackTest$ClassUnloadbleTest) + testSuiteFinished: ClassUnloadbleTest(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerCallbackTest$ClassUnloadbleTest) + testSuiteFinished: classes + testRunFinished: 0,0,0,1 + """) + // CHECKSTYLE:ON + public static class ClassUnloadbleTest { + static { + Assert.fail("Class unloadable!"); + } + + @Test + public void test1() { + } + + @Test + public void test2() { + } + } } diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java index 6ee443fac874..73ea64f57997 100644 --- a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java +++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java @@ -146,7 +146,7 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase testRunStarted: classes testSuiteStarted: classes testStarted: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$DuplicateConfigTest) - testFailure: Class com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest.DuplicateConfigTest has multiple fields with @RavenwoodConfiguration.Config + testFailure: Class com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest.DuplicateConfigTest has multiple fields with @RavenwoodConfig.Config testFinished: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$DuplicateConfigTest) testSuiteFinished: classes testRunFinished: 1,1,0,0 @@ -220,7 +220,7 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase } /** - * @Config's must be of type RavenwoodConfiguration. + * @Config's must be of type RavenwoodConfig. */ @RunWith(AndroidJUnit4.class) // CHECKSTYLE:OFF @@ -228,7 +228,7 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase testRunStarted: classes testSuiteStarted: classes testStarted: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WrongTypeConfigTest) - testFailure: Field com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest.WrongTypeConfigTest.sConfig has @RavenwoodConfiguration.Config but type is not RavenwoodConfiguration + testFailure: Field com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest.WrongTypeConfigTest.sConfig has @RavenwoodConfig.Config but type is not RavenwoodConfig testFinished: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WrongTypeConfigTest) testSuiteFinished: classes testRunFinished: 1,1,0,0 @@ -237,7 +237,7 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase public static class WrongTypeConfigTest { @RavenwoodConfig.Config - public Object sConfig = + public static Object sConfig = new RavenwoodConfig.Builder().build(); @Test @@ -247,6 +247,34 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase } /** + * @Rule must be of type RavenwoodRule. + */ + @RunWith(AndroidJUnit4.class) + // CHECKSTYLE:OFF + @Expected(""" + testRunStarted: classes + testSuiteStarted: classes + testSuiteStarted: com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WrongTypeRuleTest + testStarted: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WrongTypeRuleTest) + testFailure: If you have a RavenwoodRule in your test, make sure the field type is RavenwoodRule so Ravenwood can detect it. + testFinished: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WrongTypeRuleTest) + testSuiteFinished: com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WrongTypeRuleTest + testSuiteFinished: classes + testRunFinished: 1,1,0,0 + """) + // CHECKSTYLE:ON + public static class WrongTypeRuleTest { + + @Rule + public TestRule mRule = new RavenwoodRule.Builder().build(); + + @Test + public void testConfig() { + } + + } + + /** * Config can't be used with a (instance) Rule. */ @RunWith(AndroidJUnit4.class) @@ -255,7 +283,7 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase testRunStarted: classes testSuiteStarted: classes testStarted: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WithInstanceRuleTest) - testFailure: RavenwoodConfiguration and RavenwoodRule cannot be used in the same class. Suggest migrating to RavenwoodConfiguration. + testFailure: RavenwoodConfig and RavenwoodRule cannot be used in the same class. Suggest migrating to RavenwoodConfig. testFinished: testConfig(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$WithInstanceRuleTest) testSuiteFinished: classes testRunFinished: 1,1,0,0 @@ -373,7 +401,7 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase testRunStarted: classes testSuiteStarted: classes testStarted: test(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ConfigWithRuleInBaseClassTest) - testFailure: RavenwoodConfiguration and RavenwoodRule cannot be used in the same class. Suggest migrating to RavenwoodConfiguration. + testFailure: RavenwoodConfig and RavenwoodRule cannot be used in the same class. Suggest migrating to RavenwoodConfig. testFinished: test(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ConfigWithRuleInBaseClassTest) testSuiteFinished: classes testRunFinished: 1,1,0,0 @@ -408,10 +436,11 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase testSuiteStarted: classes testSuiteStarted: com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$RuleWithDifferentTypeInBaseClassSuccessTest testStarted: testRuleInBaseClass(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$RuleWithDifferentTypeInBaseClassSuccessTest) + testFailure: If you have a RavenwoodRule in your test, make sure the field type is RavenwoodRule so Ravenwood can detect it. testFinished: testRuleInBaseClass(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$RuleWithDifferentTypeInBaseClassSuccessTest) testSuiteFinished: com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$RuleWithDifferentTypeInBaseClassSuccessTest testSuiteFinished: classes - testRunFinished: 1,0,0,0 + testRunFinished: 1,1,0,0 """) // CHECKSTYLE:ON public static class RuleWithDifferentTypeInBaseClassSuccessTest extends RuleWithDifferentTypeInBaseClass { @@ -434,7 +463,7 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase testSuiteStarted: classes testSuiteStarted: com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ConfigWithRuleWithDifferentTypeInBaseClassTest testStarted: test(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ConfigWithRuleWithDifferentTypeInBaseClassTest) - testFailure: RavenwoodConfiguration and RavenwoodRule cannot be used in the same class. Suggest migrating to RavenwoodConfiguration. + testFailure: If you have a RavenwoodRule in your test, make sure the field type is RavenwoodRule so Ravenwood can detect it. testFinished: test(com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ConfigWithRuleWithDifferentTypeInBaseClassTest) testSuiteFinished: com.android.ravenwoodtest.runnercallbacktests.RavenwoodRunnerConfigValidationTest$ConfigWithRuleWithDifferentTypeInBaseClassTest testSuiteFinished: classes diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionExecutors.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionExecutors.java index c3b7087a44c3..1f98334bb8ce 100644 --- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionExecutors.java +++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionExecutors.java @@ -16,7 +16,15 @@ package com.android.server.appfunctions; +import android.annotation.NonNull; +import android.os.UserHandle; +import android.util.SparseArray; + +import com.android.internal.annotations.GuardedBy; + import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -33,5 +41,50 @@ public final class AppFunctionExecutors { /* unit= */ TimeUnit.SECONDS, /* workQueue= */ new LinkedBlockingQueue<>()); + /** A map of per-user executors for queued work. */ + @GuardedBy("sLock") + private static final SparseArray<ExecutorService> mPerUserExecutorsLocked = new SparseArray<>(); + + private static final Object sLock = new Object(); + + /** + * Returns a per-user executor for queued metadata sync request. + * + * <p>The work submitted to these executor (Sync request) needs to be synchronous per user hence + * the use of a single thread. + * + * <p>Note: Use a different executor if not calling {@code submitSyncRequest} on a {@code + * MetadataSyncAdapter}. + */ + // TODO(b/357551503): Restrict the scope of this executor to the MetadataSyncAdapter itself. + public static ExecutorService getPerUserSyncExecutor(@NonNull UserHandle user) { + synchronized (sLock) { + ExecutorService executor = mPerUserExecutorsLocked.get(user.getIdentifier(), null); + if (executor == null) { + executor = Executors.newSingleThreadExecutor(); + mPerUserExecutorsLocked.put(user.getIdentifier(), executor); + } + return executor; + } + } + + /** + * Shuts down and removes the per-user executor for queued work. + * + * <p>This should be called when the user is removed. + */ + public static void shutDownAndRemoveUserExecutor(@NonNull UserHandle user) + throws InterruptedException { + ExecutorService executor; + synchronized (sLock) { + executor = mPerUserExecutorsLocked.get(user.getIdentifier()); + mPerUserExecutorsLocked.remove(user.getIdentifier()); + } + if (executor != null) { + executor.shutdown(); + var unused = executor.awaitTermination(30, TimeUnit.SECONDS); + } + } + private AppFunctionExecutors() {} } diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerService.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerService.java index 02800cbf4f3d..c293087defb6 100644 --- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerService.java +++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerService.java @@ -16,6 +16,7 @@ package com.android.server.appfunctions; +import android.annotation.NonNull; import android.app.appfunctions.AppFunctionManagerConfiguration; import android.content.Context; @@ -36,4 +37,14 @@ public class AppFunctionManagerService extends SystemService { publishBinderService(Context.APP_FUNCTION_SERVICE, mServiceImpl); } } + + @Override + public void onUserUnlocked(@NonNull TargetUser user) { + mServiceImpl.onUserUnlocked(user); + } + + @Override + public void onUserStopping(@NonNull TargetUser user) { + mServiceImpl.onUserStopping(user); + } } diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java index 2362b91c826e..cf039df3bc96 100644 --- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java +++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java @@ -19,29 +19,35 @@ package com.android.server.appfunctions; import static com.android.server.appfunctions.AppFunctionExecutors.THREAD_POOL_EXECUTOR; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.appfunctions.AppFunctionStaticMetadataHelper; import android.app.appfunctions.ExecuteAppFunctionAidlRequest; import android.app.appfunctions.ExecuteAppFunctionResponse; import android.app.appfunctions.IAppFunctionManager; import android.app.appfunctions.IAppFunctionService; import android.app.appfunctions.IExecuteAppFunctionCallback; import android.app.appfunctions.SafeOneTimeExecuteAppFunctionCallback; +import android.app.appsearch.AppSearchManager; +import android.app.appsearch.AppSearchResult; +import android.app.appsearch.observer.DocumentChangeInfo; +import android.app.appsearch.observer.ObserverCallback; +import android.app.appsearch.observer.ObserverSpec; +import android.app.appsearch.observer.SchemaChangeInfo; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.UserHandle; import android.text.TextUtils; import android.util.Slog; -import android.app.appsearch.AppSearchResult; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.SystemService.TargetUser; import com.android.server.appfunctions.RemoteServiceCaller.RunServiceCallCallback; import com.android.server.appfunctions.RemoteServiceCaller.ServiceUsageCompleteListener; +import java.io.IOException; import java.util.Objects; import java.util.concurrent.CompletionException; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; /** Implementation of the AppFunctionManagerService. */ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { @@ -51,9 +57,11 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { private final CallerValidator mCallerValidator; private final ServiceHelper mInternalServiceHelper; private final ServiceConfig mServiceConfig; + private final Context mContext; public AppFunctionManagerServiceImpl(@NonNull Context context) { this( + context, new RemoteServiceCallerImpl<>( context, IAppFunctionService.Stub::asInterface, THREAD_POOL_EXECUTOR), new CallerValidatorImpl(context), @@ -63,10 +71,12 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { @VisibleForTesting AppFunctionManagerServiceImpl( + Context context, RemoteServiceCaller<IAppFunctionService> remoteServiceCaller, CallerValidator callerValidator, ServiceHelper appFunctionInternalServiceHelper, ServiceConfig serviceConfig) { + mContext = Objects.requireNonNull(context); mRemoteServiceCaller = Objects.requireNonNull(remoteServiceCaller); mCallerValidator = Objects.requireNonNull(callerValidator); mInternalServiceHelper = Objects.requireNonNull(appFunctionInternalServiceHelper); @@ -90,6 +100,26 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { } } + /** Called when the user is unlocked. */ + public void onUserUnlocked(TargetUser user) { + Objects.requireNonNull(user); + + registerAppSearchObserver(user); + trySyncRuntimeMetadata(user); + } + + /** Called when the user is stopping. */ + public void onUserStopping(@NonNull TargetUser user) { + Objects.requireNonNull(user); + + try { + AppFunctionExecutors.shutDownAndRemoveUserExecutor(user.getUserHandle()); + MetadataSyncPerUser.removeUserSyncAdapter(user.getUserHandle()); + } catch (InterruptedException e) { + Slog.e(TAG, "Unable to remove data for: " + user.getUserHandle(), e); + } + } + private void executeAppFunctionInternal( ExecuteAppFunctionAidlRequest requestInternal, SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback) { @@ -132,53 +162,55 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { return; } - var unused = mCallerValidator - .verifyCallerCanExecuteAppFunction( - validatedCallingPackage, - targetPackageName, - requestInternal.getClientRequest().getFunctionIdentifier()) - .thenAccept( - canExecute -> { - if (!canExecute) { - safeExecuteAppFunctionCallback.onResult( - ExecuteAppFunctionResponse.newFailure( - ExecuteAppFunctionResponse.RESULT_DENIED, - "Caller does not have permission to execute the" - + " appfunction", - /* extras= */ null)); - return; - } - Intent serviceIntent = - mInternalServiceHelper.resolveAppFunctionService( - targetPackageName, targetUser); - if (serviceIntent == null) { - safeExecuteAppFunctionCallback.onResult( - ExecuteAppFunctionResponse.newFailure( - ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR, - "Cannot find the target service.", - /* extras= */ null)); - return; - } - final long token = Binder.clearCallingIdentity(); - try { - bindAppFunctionServiceUnchecked( - requestInternal, - serviceIntent, - targetUser, - safeExecuteAppFunctionCallback, - /* bindFlags= */ Context.BIND_AUTO_CREATE, - /* timeoutInMillis= */ mServiceConfig - .getExecuteAppFunctionTimeoutMillis()); - } finally { - Binder.restoreCallingIdentity(token); - } - }) - .exceptionally( - ex -> { - safeExecuteAppFunctionCallback.onResult( - mapExceptionToExecuteAppFunctionResponse(ex)); - return null; - }); + var unused = + mCallerValidator + .verifyCallerCanExecuteAppFunction( + validatedCallingPackage, + targetPackageName, + requestInternal.getClientRequest().getFunctionIdentifier()) + .thenAccept( + canExecute -> { + if (!canExecute) { + safeExecuteAppFunctionCallback.onResult( + ExecuteAppFunctionResponse.newFailure( + ExecuteAppFunctionResponse.RESULT_DENIED, + "Caller does not have permission to execute" + + " the appfunction", + /* extras= */ null)); + return; + } + Intent serviceIntent = + mInternalServiceHelper.resolveAppFunctionService( + targetPackageName, targetUser); + if (serviceIntent == null) { + safeExecuteAppFunctionCallback.onResult( + ExecuteAppFunctionResponse.newFailure( + ExecuteAppFunctionResponse + .RESULT_INTERNAL_ERROR, + "Cannot find the target service.", + /* extras= */ null)); + return; + } + final long token = Binder.clearCallingIdentity(); + try { + bindAppFunctionServiceUnchecked( + requestInternal, + serviceIntent, + targetUser, + safeExecuteAppFunctionCallback, + /* bindFlags= */ Context.BIND_AUTO_CREATE, + /* timeoutInMillis= */ mServiceConfig + .getExecuteAppFunctionTimeoutMillis()); + } finally { + Binder.restoreCallingIdentity(token); + } + }) + .exceptionally( + ex -> { + safeExecuteAppFunctionCallback.onResult( + mapExceptionToExecuteAppFunctionResponse(ex)); + return null; + }); } private void bindAppFunctionServiceUnchecked( @@ -256,7 +288,7 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { } private ExecuteAppFunctionResponse mapExceptionToExecuteAppFunctionResponse(Throwable e) { - if(e instanceof CompletionException) { + if (e instanceof CompletionException) { e = e.getCause(); } @@ -291,4 +323,103 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { } return ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR; } + + private void registerAppSearchObserver(@NonNull TargetUser user) { + AppSearchManager perUserAppSearchManager = + mContext.createContextAsUser(user.getUserHandle(), /* flags= */ 0) + .getSystemService(AppSearchManager.class); + if (perUserAppSearchManager == null) { + Slog.d(TAG, "AppSearch Manager not found for user: " + user.getUserIdentifier()); + return; + } + try (FutureGlobalSearchSession futureGlobalSearchSession = + new FutureGlobalSearchSession( + perUserAppSearchManager, AppFunctionExecutors.THREAD_POOL_EXECUTOR)) { + AppFunctionMetadataObserver appFunctionMetadataObserver = + new AppFunctionMetadataObserver( + user.getUserHandle(), + mContext.createContextAsUser(user.getUserHandle(), /* flags= */ 0)); + var unused = + futureGlobalSearchSession + .registerObserverCallbackAsync( + "android", + new ObserverSpec.Builder().build(), + THREAD_POOL_EXECUTOR, + appFunctionMetadataObserver) + .whenComplete( + (voidResult, ex) -> { + if (ex != null) { + Slog.e(TAG, "Failed to register observer: ", ex); + } + }); + + } catch (IOException ex) { + Slog.e(TAG, "Failed to close observer session: ", ex); + } + } + + private void trySyncRuntimeMetadata(@NonNull TargetUser user) { + MetadataSyncAdapter metadataSyncAdapter = + MetadataSyncPerUser.getPerUserMetadataSyncAdapter( + user.getUserHandle(), + mContext.createContextAsUser(user.getUserHandle(), /* flags= */ 0)); + if (metadataSyncAdapter != null) { + var unused = + metadataSyncAdapter + .submitSyncRequest() + .whenComplete( + (isSuccess, ex) -> { + if (ex != null || !isSuccess) { + Slog.e(TAG, "Sync was not successful"); + } + }); + } + } + + private static class AppFunctionMetadataObserver implements ObserverCallback { + @Nullable private final MetadataSyncAdapter mPerUserMetadataSyncAdapter; + + AppFunctionMetadataObserver(@NonNull UserHandle userHandle, @NonNull Context userContext) { + mPerUserMetadataSyncAdapter = + MetadataSyncPerUser.getPerUserMetadataSyncAdapter(userHandle, userContext); + } + + @Override + public void onDocumentChanged(@NonNull DocumentChangeInfo documentChangeInfo) { + if (mPerUserMetadataSyncAdapter == null) { + return; + } + if (documentChangeInfo + .getDatabaseName() + .equals(AppFunctionStaticMetadataHelper.APP_FUNCTION_STATIC_METADATA_DB) + && documentChangeInfo + .getNamespace() + .equals( + AppFunctionStaticMetadataHelper + .APP_FUNCTION_STATIC_NAMESPACE)) { + var unused = mPerUserMetadataSyncAdapter.submitSyncRequest(); + } + } + + @Override + public void onSchemaChanged(@NonNull SchemaChangeInfo schemaChangeInfo) { + if (mPerUserMetadataSyncAdapter == null) { + return; + } + if (schemaChangeInfo + .getDatabaseName() + .equals(AppFunctionStaticMetadataHelper.APP_FUNCTION_STATIC_METADATA_DB)) { + boolean shouldInitiateSync = false; + for (String schemaName : schemaChangeInfo.getChangedSchemaNames()) { + if (schemaName.startsWith(AppFunctionStaticMetadataHelper.STATIC_SCHEMA_TYPE)) { + shouldInitiateSync = true; + break; + } + } + if (shouldInitiateSync) { + var unused = mPerUserMetadataSyncAdapter.submitSyncRequest(); + } + } + } + } } diff --git a/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncAdapter.java b/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncAdapter.java index e2573590bf5d..8c6f50e5c1bd 100644 --- a/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncAdapter.java +++ b/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncAdapter.java @@ -24,6 +24,8 @@ import android.annotation.WorkerThread; import android.app.appfunctions.AppFunctionRuntimeMetadata; import android.app.appfunctions.AppFunctionStaticMetadataHelper; import android.app.appsearch.AppSearchBatchResult; +import android.app.appsearch.AppSearchManager; +import android.app.appsearch.AppSearchManager.SearchContext; import android.app.appsearch.AppSearchResult; import android.app.appsearch.AppSearchSchema; import android.app.appsearch.PackageIdentifier; @@ -61,9 +63,8 @@ import java.util.concurrent.Executor; */ public class MetadataSyncAdapter { private static final String TAG = MetadataSyncAdapter.class.getSimpleName(); - private final FutureAppSearchSession mRuntimeMetadataSearchSession; - private final FutureAppSearchSession mStaticMetadataSearchSession; private final Executor mSyncExecutor; + private final AppSearchManager mAppSearchManager; private final PackageManager mPackageManager; // Hidden constants in {@link SetSchemaRequest} that restricts runtime metadata visibility @@ -73,13 +74,11 @@ public class MetadataSyncAdapter { public MetadataSyncAdapter( @NonNull Executor syncExecutor, - @NonNull FutureAppSearchSession runtimeMetadataSearchSession, - @NonNull FutureAppSearchSession staticMetadataSearchSession, - @NonNull PackageManager packageManager) { + @NonNull PackageManager packageManager, + @NonNull AppSearchManager appSearchManager) { mSyncExecutor = Objects.requireNonNull(syncExecutor); - mRuntimeMetadataSearchSession = Objects.requireNonNull(runtimeMetadataSearchSession); - mStaticMetadataSearchSession = Objects.requireNonNull(staticMetadataSearchSession); mPackageManager = Objects.requireNonNull(packageManager); + mAppSearchManager = Objects.requireNonNull(appSearchManager); } /** @@ -89,31 +88,54 @@ public class MetadataSyncAdapter { * synchronization was successful. */ public AndroidFuture<Boolean> submitSyncRequest() { + SearchContext staticMetadataSearchContext = + new SearchContext.Builder( + AppFunctionStaticMetadataHelper.APP_FUNCTION_STATIC_METADATA_DB) + .build(); + SearchContext runtimeMetadataSearchContext = + new SearchContext.Builder( + AppFunctionRuntimeMetadata.APP_FUNCTION_RUNTIME_METADATA_DB) + .build(); AndroidFuture<Boolean> settableSyncStatus = new AndroidFuture<>(); mSyncExecutor.execute( () -> { - try { - trySyncAppFunctionMetadataBlocking(); + try (FutureAppSearchSession staticMetadataSearchSession = + new FutureAppSearchSessionImpl( + mAppSearchManager, + AppFunctionExecutors.THREAD_POOL_EXECUTOR, + staticMetadataSearchContext); + FutureAppSearchSession runtimeMetadataSearchSession = + new FutureAppSearchSessionImpl( + mAppSearchManager, + AppFunctionExecutors.THREAD_POOL_EXECUTOR, + runtimeMetadataSearchContext)) { + + trySyncAppFunctionMetadataBlocking( + staticMetadataSearchSession, runtimeMetadataSearchSession); settableSyncStatus.complete(true); - } catch (Exception e) { - settableSyncStatus.completeExceptionally(e); + + } catch (Exception ex) { + settableSyncStatus.completeExceptionally(ex); } }); return settableSyncStatus; } @WorkerThread - private void trySyncAppFunctionMetadataBlocking() + @VisibleForTesting + void trySyncAppFunctionMetadataBlocking( + @NonNull FutureAppSearchSession staticMetadataSearchSession, + @NonNull FutureAppSearchSession runtimeMetadataSearchSession) throws ExecutionException, InterruptedException { ArrayMap<String, ArraySet<String>> staticPackageToFunctionMap = getPackageToFunctionIdMap( - mStaticMetadataSearchSession, + staticMetadataSearchSession, AppFunctionStaticMetadataHelper.STATIC_SCHEMA_TYPE, AppFunctionStaticMetadataHelper.PROPERTY_FUNCTION_ID, AppFunctionStaticMetadataHelper.PROPERTY_PACKAGE_NAME); ArrayMap<String, ArraySet<String>> runtimePackageToFunctionMap = getPackageToFunctionIdMap( - mRuntimeMetadataSearchSession, + runtimeMetadataSearchSession, RUNTIME_SCHEMA_TYPE, AppFunctionRuntimeMetadata.PROPERTY_FUNCTION_ID, AppFunctionRuntimeMetadata.PROPERTY_PACKAGE_NAME); @@ -134,7 +156,7 @@ public class MetadataSyncAdapter { RemoveByDocumentIdRequest removeByDocumentIdRequest = buildRemoveRuntimeMetadataRequest(removedFunctionsDiffMap); AppSearchBatchResult<String, Void> removeDocumentBatchResult = - mRuntimeMetadataSearchSession.remove(removeByDocumentIdRequest).get(); + runtimeMetadataSearchSession.remove(removeByDocumentIdRequest).get(); if (!removeDocumentBatchResult.isSuccess()) { throw convertFailedAppSearchResultToException( removeDocumentBatchResult.getFailures().values()); @@ -144,13 +166,14 @@ public class MetadataSyncAdapter { if (!addedFunctionsDiffMap.isEmpty()) { // TODO(b/357551503): only set schema on package diff SetSchemaRequest addSetSchemaRequest = - buildSetSchemaRequestForRuntimeMetadataSchemas(appRuntimeMetadataSchemas); + buildSetSchemaRequestForRuntimeMetadataSchemas( + mPackageManager, appRuntimeMetadataSchemas); Objects.requireNonNull( - mRuntimeMetadataSearchSession.setSchema(addSetSchemaRequest).get()); + runtimeMetadataSearchSession.setSchema(addSetSchemaRequest).get()); PutDocumentsRequest putDocumentsRequest = buildPutRuntimeMetadataRequest(addedFunctionsDiffMap); AppSearchBatchResult<String, Void> putDocumentBatchResult = - mRuntimeMetadataSearchSession.put(putDocumentsRequest).get(); + runtimeMetadataSearchSession.put(putDocumentsRequest).get(); if (!putDocumentBatchResult.isSuccess()) { throw convertFailedAppSearchResultToException( putDocumentBatchResult.getFailures().values()); @@ -211,6 +234,7 @@ public class MetadataSyncAdapter { @NonNull private SetSchemaRequest buildSetSchemaRequestForRuntimeMetadataSchemas( + @NonNull PackageManager packageManager, @NonNull Set<AppSearchSchema> metadataSchemaSet) { Objects.requireNonNull(metadataSchemaSet); SetSchemaRequest.Builder setSchemaRequestBuilder = @@ -220,7 +244,7 @@ public class MetadataSyncAdapter { String packageName = AppFunctionRuntimeMetadata.getPackageNameFromSchema( runtimeMetadataSchema.getSchemaType()); - byte[] packageCert = getCertificate(packageName); + byte[] packageCert = getCertificate(packageManager, packageName); if (packageCert == null) { continue; } @@ -399,13 +423,15 @@ public class MetadataSyncAdapter { /** Gets the SHA-256 certificate from a {@link PackageManager}, or null if it is not found. */ @Nullable - private byte[] getCertificate(@NonNull String packageName) { + private byte[] getCertificate( + @NonNull PackageManager packageManager, @NonNull String packageName) { + Objects.requireNonNull(packageManager); Objects.requireNonNull(packageName); PackageInfo packageInfo; try { packageInfo = Objects.requireNonNull( - mPackageManager.getPackageInfo( + packageManager.getPackageInfo( packageName, PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES)); diff --git a/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncPerUser.java b/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncPerUser.java new file mode 100644 index 000000000000..f421527e72d0 --- /dev/null +++ b/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncPerUser.java @@ -0,0 +1,80 @@ +/* + * 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.Nullable; +import android.app.appsearch.AppSearchManager; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.UserHandle; +import android.util.SparseArray; + +import com.android.internal.annotations.GuardedBy; + +/** A Singleton class that manages per-user metadata sync adapters. */ +public final class MetadataSyncPerUser { + private static final String TAG = MetadataSyncPerUser.class.getSimpleName(); + + /** A map of per-user adapter for synchronizing appFunction metadata. */ + @GuardedBy("sLock") + private static final SparseArray<MetadataSyncAdapter> sPerUserMetadataSyncAdapter = + new SparseArray<>(); + + private static final Object sLock = new Object(); + + /** + * Returns the per-user metadata sync adapter for the given user. + * + * @param user The user for which to get the metadata sync adapter. + * @param userContext The user context for the given user. + * @return The metadata sync adapter for the given user. + */ + @Nullable + public static MetadataSyncAdapter getPerUserMetadataSyncAdapter( + UserHandle user, Context userContext) { + synchronized (sLock) { + MetadataSyncAdapter metadataSyncAdapter = + sPerUserMetadataSyncAdapter.get(user.getIdentifier(), null); + if (metadataSyncAdapter == null) { + AppSearchManager perUserAppSearchManager = + userContext.getSystemService(AppSearchManager.class); + PackageManager perUserPackageManager = userContext.getPackageManager(); + if (perUserAppSearchManager != null) { + metadataSyncAdapter = + new MetadataSyncAdapter( + AppFunctionExecutors.getPerUserSyncExecutor(user), + perUserPackageManager, + perUserAppSearchManager); + sPerUserMetadataSyncAdapter.put(user.getIdentifier(), metadataSyncAdapter); + return metadataSyncAdapter; + } + } + return metadataSyncAdapter; + } + } + + /** + * Removes the per-user metadata sync adapter for the given user. + * + * @param user The user for which to remove the metadata sync adapter. + */ + public static void removeUserSyncAdapter(UserHandle user) { + synchronized (sLock) { + sPerUserMetadataSyncAdapter.remove(user.getIdentifier()); + } + } +} diff --git a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java index 2c261fe668fb..bd1b0ea99e17 100644 --- a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java +++ b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java @@ -732,6 +732,7 @@ public final class PresentationStatsEventLogger { // These autofill id's are being refilled, so they had failed previously. // Note that these autofillIds correspond to the new autofill ids after relayout. event.mFailedAutofillIds = new ArraySet<>(autofillIds); + setHasRelayoutLog(); }); } @@ -753,6 +754,7 @@ public final class PresentationStatsEventLogger { int failureCount = ids.size(); if (isRefill) { event.mViewFailedOnRefillCount = failureCount; + setHasRelayoutLog(); } else { event.mViewFillFailureCount = failureCount; event.mViewFailedPriorToRefillCount = failureCount; @@ -834,6 +836,19 @@ public final class PresentationStatsEventLogger { } /** + * Set the log contains relayout metrics. + * This is being added as a temporary measure to add logging. + * In future, when we map Session's old view states to the new autofill id's as part of fixing + * save for relayout cases, we no longer would need this. But till then, this is needed to set + * autofill logs for relayout cases. + */ + private void setHasRelayoutLog() { + mEventInternal.ifPresent(event -> { + event.mHasRelayoutLog = true; + }); + } + + /** * Finish and log the event. */ public void logAndEndEvent(String caller) { @@ -844,8 +859,10 @@ public final class PresentationStatsEventLogger { } PresentationStatsEventInternal event = mEventInternal.get(); - boolean ignoreLogging = !event.mIsDatasetAvailable; - + boolean ignoreLogging = !event.mIsDatasetAvailable + && !event.mHasRelayoutLog + && !(event.mFixExpireResponseDuringAuthCount > 0) + && !(event.mNotifyViewEnteredIgnoredDuringAuthCount > 0); if (sVerbose) { Slog.v(TAG, "(" + caller + ") " + (ignoreLogging ? "IGNORING - following event won't be logged: " : "") @@ -1032,8 +1049,9 @@ public final class PresentationStatsEventLogger { ArraySet<AutofillId> mFailedAutofillIds = new ArraySet<>(); ArraySet<AutofillId> mAlreadyFilledAutofillIds = new ArraySet<>(); - // Not logged - used for internal logic + // Following are not logged and used only for internal logic boolean shouldResetShownCount = false; + boolean mHasRelayoutLog = false; PresentationStatsEventInternal() {} } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index b109472a2a1e..2fa0e0d0d946 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -720,6 +720,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState void handleInlineSuggestionRequest(InlineSuggestionsRequest inlineSuggestionsRequest, ViewState viewState) { + if (sVerbose) { + Slog.v(TAG, "handleInlineSuggestionRequest(): inline suggestion request received"); + } synchronized (mLock) { if (!mWaitForInlineRequest || mPendingInlineSuggestionsRequest != null) { return; @@ -734,15 +737,27 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @GuardedBy("mLock") void maybeRequestFillLocked() { if (mPendingFillRequest == null) { + if (sVerbose) { + Slog.v(TAG, "maybeRequestFillLocked(): cancelling calling fill request " + + "due to empty pending fill request"); + } return; } mFieldClassificationIdSnapshot = sIdCounterForPcc.get(); if (mWaitForInlineRequest) { if (mPendingInlineSuggestionsRequest == null) { + if (sVerbose) { + Slog.v(TAG, "maybeRequestFillLocked(): cancelling calling fill request " + + "due to waiting for inline request and pending inline request is " + + "currently empty"); + } return; } - + if (sVerbose) { + Slog.v(TAG, "maybeRequestFillLocked(): adding inline request to pending " + + "fill request"); + } mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(), mPendingFillRequest.getFillContexts(), mPendingFillRequest.getHints(), @@ -750,8 +765,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mPendingFillRequest.getFlags(), mPendingInlineSuggestionsRequest, mPendingFillRequest.getDelayedFillIntentSender()); + } else { + if (sVerbose) { + Slog.v(TAG, "maybeRequestFillLocked(): not adding inline request to pending " + + "fill request"); + } } + mLastFillRequest = mPendingFillRequest; + if (sVerbose) { + Slog.v(TAG, "maybeRequestFillLocked(): sending fill request"); + } if (shouldRequestSecondaryProvider(mPendingFillRequest.getFlags()) && mSecondaryProviderHandler != null) { Slog.v(TAG, "Requesting fill response to secondary provider."); diff --git a/services/companion/java/com/android/server/companion/virtual/OWNERS b/services/companion/java/com/android/server/companion/virtual/OWNERS index 4fe0592f9075..4b732ac8e5a9 100644 --- a/services/companion/java/com/android/server/companion/virtual/OWNERS +++ b/services/companion/java/com/android/server/companion/virtual/OWNERS @@ -2,7 +2,9 @@ set noparent -marvinramin@google.com vladokom@google.com +marvinramin@google.com +caen@google.com +biswarupp@google.com ogunwale@google.com michaelwr@google.com
\ No newline at end of file diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING index 68d0ad265a46..a459ea944008 100644 --- a/services/core/java/com/android/server/TEST_MAPPING +++ b/services/core/java/com/android/server/TEST_MAPPING @@ -173,6 +173,15 @@ "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/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java index e2b6bd6ae360..d19899f03d71 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -489,7 +489,10 @@ public class VcnManagementService extends IVcnManagementService.Stub { // Check subscription is active first; much cheaper/faster check, and an app (currently) // cannot be carrier privileged for inactive subscriptions. - if (subMgr.isValidSlotIndex(info.getSimSlotIndex()) + final int simSlotIndex = info.getSimSlotIndex(); + final boolean isValidSlotIndex = + simSlotIndex >= 0 && simSlotIndex < telMgr.getActiveModemCount(); + if (isValidSlotIndex && telMgr.checkCarrierPrivilegesForPackage(pkgName) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { // TODO (b/173717728): Allow configuration for inactive, but manageable diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index f0cc09f7c232..22ec7904f972 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -73,6 +73,7 @@ import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE; import static android.media.audio.Flags.roForegroundAudioControl; import static android.os.Process.THREAD_GROUP_BACKGROUND; import static android.os.Process.THREAD_GROUP_DEFAULT; +import static android.os.Process.THREAD_GROUP_FOREGROUND_WINDOW; import static android.os.Process.THREAD_GROUP_RESTRICTED; import static android.os.Process.THREAD_GROUP_TOP_APP; import static android.os.Process.THREAD_PRIORITY_DISPLAY; @@ -116,6 +117,7 @@ import static com.android.server.am.ProcessList.PERSISTENT_SERVICE_ADJ; import static com.android.server.am.ProcessList.PREVIOUS_APP_ADJ; import static com.android.server.am.ProcessList.SCHED_GROUP_BACKGROUND; import static com.android.server.am.ProcessList.SCHED_GROUP_DEFAULT; +import static com.android.server.am.ProcessList.SCHED_GROUP_FOREGROUND_WINDOW; import static com.android.server.am.ProcessList.SCHED_GROUP_RESTRICTED; import static com.android.server.am.ProcessList.SCHED_GROUP_TOP_APP; import static com.android.server.am.ProcessList.SCHED_GROUP_TOP_APP_BOUND; @@ -1731,6 +1733,11 @@ public class OomAdjuster { // The recently used non-top visible freeform app. schedGroup = SCHED_GROUP_TOP_APP; mAdjType = "perceptible-freeform-activity"; + } else if ((flags + & WindowProcessController.ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE) != 0) { + // Currently the only case is from freeform apps which are not close to top. + schedGroup = SCHED_GROUP_FOREGROUND_WINDOW; + mAdjType = "vis-multi-window-activity"; } foregroundActivities = true; mHasVisibleActivities = true; @@ -3438,6 +3445,9 @@ public class OomAdjuster { case SCHED_GROUP_RESTRICTED: processGroup = THREAD_GROUP_RESTRICTED; break; + case SCHED_GROUP_FOREGROUND_WINDOW: + processGroup = THREAD_GROUP_FOREGROUND_WINDOW; + break; default: processGroup = THREAD_GROUP_DEFAULT; break; diff --git a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java index 21842db590b0..fb1c2e9a1f9d 100644 --- a/services/core/java/com/android/server/am/OomAdjusterModernImpl.java +++ b/services/core/java/com/android/server/am/OomAdjusterModernImpl.java @@ -331,7 +331,7 @@ public class OomAdjusterModernImpl extends OomAdjuster { void forEachNewNode(int slot, @NonNull Consumer<OomAdjusterArgs> callback) { ProcessRecordNode node = mLastNode[slot].mNext; final ProcessRecordNode tail = mProcessRecordNodes[slot].TAIL; - while (node != tail) { + while (node != null && node != tail) { mTmpOomAdjusterArgs.mApp = node.mApp; if (node.mApp == null) { // TODO(b/336178916) - Temporary logging for root causing b/336178916. @@ -365,7 +365,9 @@ public class OomAdjusterModernImpl extends OomAdjuster { } // Save the next before calling callback, since that may change the node.mNext. final ProcessRecordNode next = node.mNext; - callback.accept(mTmpOomAdjusterArgs); + if (mTmpOomAdjusterArgs.mApp != null) { + callback.accept(mTmpOomAdjusterArgs); + } // There are couple of cases: // a) The current node is moved to another slot // - for this case, we'd need to keep using the "next" node. diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index cb918a045ec6..00250b4ef463 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -303,6 +303,9 @@ public final class ProcessList { // Activity manager's version of Process.THREAD_GROUP_TOP_APP // Disambiguate between actual top app and processes bound to the top app static final int SCHED_GROUP_TOP_APP_BOUND = 4; + // Activity manager's version of Process.THREAD_GROUP_FOREGROUND_WINDOW + // The priority is like between default and top-app. + static final int SCHED_GROUP_FOREGROUND_WINDOW = 5; // The minimum number of cached apps we want to be able to keep around, // without empty apps being able to push them out of memory. diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index e145c90fb1c1..55d9c6eac87a 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -533,7 +533,8 @@ public class AudioDeviceBroker { AudioDeviceInfo.TYPE_BLE_SPEAKER, AudioDeviceInfo.TYPE_LINE_ANALOG, AudioDeviceInfo.TYPE_HDMI, - AudioDeviceInfo.TYPE_AUX_LINE + AudioDeviceInfo.TYPE_AUX_LINE, + AudioDeviceInfo.TYPE_BUS }; /*package */ static boolean isValidCommunicationDevice(@NonNull AudioDeviceInfo device) { diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index c3d09bb67452..9940442824ca 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -4006,6 +4006,7 @@ public class AudioService extends IAudioService.Stub && isFullVolumeDevice(device); boolean tvConditions = mHdmiTvClient != null && mHdmiSystemAudioSupported + && isFullVolumeDevice(device) && !isAbsoluteVolumeDevice(device) && !isA2dpAbsoluteVolumeDevice(device); diff --git a/services/core/java/com/android/server/cpu/CpuMonitorService.java b/services/core/java/com/android/server/cpu/CpuMonitorService.java index 88ff7e4103f9..2cadbc58d0f2 100644 --- a/services/core/java/com/android/server/cpu/CpuMonitorService.java +++ b/services/core/java/com/android/server/cpu/CpuMonitorService.java @@ -216,7 +216,7 @@ public final class CpuMonitorService extends SystemService { @Override public void onBootPhase(int phase) { - if (phase != PHASE_BOOT_COMPLETED) { + if (phase != PHASE_BOOT_COMPLETED || mHandler == null) { return; } Slogf.i(TAG, "Stopping periodic cpuset reading on boot complete"); diff --git a/services/core/java/com/android/server/display/DisplayControl.java b/services/core/java/com/android/server/display/DisplayControl.java index 38eb416ffdd8..ddea285d3564 100644 --- a/services/core/java/com/android/server/display/DisplayControl.java +++ b/services/core/java/com/android/server/display/DisplayControl.java @@ -109,7 +109,7 @@ public class DisplayControl { /** * Sets the HDR conversion mode for the device. * - * Returns the system preferred Hdr output type nn case when HDR conversion mode is + * Returns the system preferred HDR output type in case when HDR conversion mode is * {@link android.hardware.display.HdrConversionMode#HDR_CONVERSION_SYSTEM}. * Returns Hdr::INVALID in other cases. * @hide diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java index 93bd92614403..acf4db30ba93 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java @@ -318,13 +318,16 @@ final class DisplayDeviceInfo { */ public Display.HdrCapabilities hdrCapabilities; + /** When true, all HDR capabilities are hidden from public APIs */ + public boolean isForceSdr; + /** * Indicates whether this display supports Auto Low Latency Mode. */ public boolean allmSupported; /** - * Indicates whether this display suppors Game content type. + * Indicates whether this display supports Game content type. */ public boolean gameContentTypeSupported; @@ -516,6 +519,7 @@ final class DisplayDeviceInfo { || !Arrays.equals(supportedModes, other.supportedModes) || !Arrays.equals(supportedColorModes, other.supportedColorModes) || !Objects.equals(hdrCapabilities, other.hdrCapabilities) + || isForceSdr != other.isForceSdr || allmSupported != other.allmSupported || gameContentTypeSupported != other.gameContentTypeSupported || densityDpi != other.densityDpi @@ -560,6 +564,7 @@ final class DisplayDeviceInfo { colorMode = other.colorMode; supportedColorModes = other.supportedColorModes; hdrCapabilities = other.hdrCapabilities; + isForceSdr = other.isForceSdr; allmSupported = other.allmSupported; gameContentTypeSupported = other.gameContentTypeSupported; densityDpi = other.densityDpi; @@ -603,6 +608,7 @@ final class DisplayDeviceInfo { sb.append(", colorMode ").append(colorMode); sb.append(", supportedColorModes ").append(Arrays.toString(supportedColorModes)); sb.append(", hdrCapabilities ").append(hdrCapabilities); + sb.append(", isForceSdr ").append(isForceSdr); sb.append(", allmSupported ").append(allmSupported); sb.append(", gameContentTypeSupported ").append(gameContentTypeSupported); sb.append(", density ").append(densityDpi); diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 3c2167e7a4ef..e7fd8f7db182 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -48,6 +48,7 @@ import static android.os.Process.ROOT_UID; import static android.provider.Settings.Secure.RESOLUTION_MODE_FULL; import static android.provider.Settings.Secure.RESOLUTION_MODE_HIGH; import static android.provider.Settings.Secure.RESOLUTION_MODE_UNKNOWN; +import static android.view.Display.HdrCapabilities.HDR_TYPE_INVALID; import static com.android.server.display.layout.Layout.Display.POSITION_REAR; @@ -284,7 +285,7 @@ public final class DisplayManagerService extends SystemService { @GuardedBy("mSyncRoot") private int[] mUserDisabledHdrTypes = {}; @Display.HdrCapabilities.HdrType - private int[] mSupportedHdrOutputType; + private int[] mSupportedHdrOutputTypes; @GuardedBy("mSyncRoot") private boolean mAreUserDisabledHdrTypesAllowed = true; @@ -299,10 +300,10 @@ public final class DisplayManagerService extends SystemService { // HDR conversion mode chosen by user @GuardedBy("mSyncRoot") private HdrConversionMode mHdrConversionMode = null; - // Actual HDR conversion mode, which takes app overrides into account. - private HdrConversionMode mOverrideHdrConversionMode = null; + // Whether app has disabled HDR conversion + private boolean mShouldDisableHdrConversion = false; @GuardedBy("mSyncRoot") - private int mSystemPreferredHdrOutputType = Display.HdrCapabilities.HDR_TYPE_INVALID; + private int mSystemPreferredHdrOutputType = HDR_TYPE_INVALID; // The synchronization root for the display manager. @@ -1419,7 +1420,8 @@ public final class DisplayManagerService extends SystemService { } } - private void setUserDisabledHdrTypesInternal(int[] userDisabledHdrTypes) { + @VisibleForTesting + void setUserDisabledHdrTypesInternal(int[] userDisabledHdrTypes) { synchronized (mSyncRoot) { if (userDisabledHdrTypes == null) { Slog.e(TAG, "Null is not an expected argument to " @@ -1437,6 +1439,7 @@ public final class DisplayManagerService extends SystemService { if (Arrays.equals(mUserDisabledHdrTypes, userDisabledHdrTypes)) { return; } + String userDisabledFormatsString = ""; if (userDisabledHdrTypes.length != 0) { userDisabledFormatsString = TextUtils.join(",", @@ -1452,6 +1455,15 @@ public final class DisplayManagerService extends SystemService { handleLogicalDisplayChangedLocked(display); }); } + /* Note: it may be expected to reset the Conversion Mode when an HDR type is enabled + and the Conversion Mode is set to System Preferred. This is handled in the Settings + code because in the special case where HDR is indirectly disabled by Force SDR + Conversion, manually enabling HDR is not recognized as an action that reduces the + disabled HDR count. Thus, this case needs to be checked in the Settings code when we + know we're enabling an HDR mode. If we split checking for SystemConversion and + isForceSdr in two places, we may have duplicate calls to resetting to System Conversion + and get two black screens. + */ } } @@ -1464,19 +1476,20 @@ public final class DisplayManagerService extends SystemService { return true; } - private void setAreUserDisabledHdrTypesAllowedInternal( + @VisibleForTesting + void setAreUserDisabledHdrTypesAllowedInternal( boolean areUserDisabledHdrTypesAllowed) { synchronized (mSyncRoot) { if (mAreUserDisabledHdrTypesAllowed == areUserDisabledHdrTypesAllowed) { return; } mAreUserDisabledHdrTypesAllowed = areUserDisabledHdrTypesAllowed; - if (mUserDisabledHdrTypes.length == 0) { - return; - } Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED, areUserDisabledHdrTypesAllowed ? 1 : 0); + if (mUserDisabledHdrTypes.length == 0) { + return; + } int userDisabledHdrTypes[] = {}; if (!mAreUserDisabledHdrTypesAllowed) { userDisabledHdrTypes = mUserDisabledHdrTypes; @@ -1487,6 +1500,14 @@ public final class DisplayManagerService extends SystemService { display.setUserDisabledHdrTypes(finalUserDisabledHdrTypes); handleLogicalDisplayChangedLocked(display); }); + // When HDR conversion mode is set to SYSTEM, modification to + // areUserDisabledHdrTypesAllowed requires refreshing the HDR conversion mode to tell + // the system which HDR types it is not allowed to use. + if (getHdrConversionModeInternal().getConversionMode() + == HdrConversionMode.HDR_CONVERSION_SYSTEM) { + setHdrConversionModeInternal( + new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM)); + } } } @@ -2357,7 +2378,7 @@ public final class DisplayManagerService extends SystemService { final int preferredHdrOutputType = hdrConversionMode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_FORCE ? hdrConversionMode.getPreferredHdrOutputType() - : Display.HdrCapabilities.HDR_TYPE_INVALID; + : HDR_TYPE_INVALID; Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.HDR_FORCE_CONVERSION_TYPE, preferredHdrOutputType); } @@ -2370,7 +2391,7 @@ public final class DisplayManagerService extends SystemService { ? Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.HDR_FORCE_CONVERSION_TYPE, Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION) - : Display.HdrCapabilities.HDR_TYPE_INVALID; + : HDR_TYPE_INVALID; mHdrConversionMode = new HdrConversionMode(conversionMode, preferredHdrOutputType); setHdrConversionModeInternal(mHdrConversionMode); } @@ -2507,22 +2528,38 @@ public final class DisplayManagerService extends SystemService { }); } + /** + * Returns the HDR output types that are supported by the device's HDR conversion capabilities, + * stripping out any user-disabled HDR types if mAreUserDisabledHdrTypesAllowed is false. + */ @GuardedBy("mSyncRoot") - private int[] getEnabledAutoHdrTypesLocked() { - IntArray autoHdrOutputTypesArray = new IntArray(); + @VisibleForTesting + int[] getEnabledHdrOutputTypesLocked() { + if (mAreUserDisabledHdrTypesAllowed) { + return getSupportedHdrOutputTypesInternal(); + } + // Strip out all HDR formats that are currently user-disabled + IntArray enabledHdrOutputTypesArray = new IntArray(); for (int type : getSupportedHdrOutputTypesInternal()) { - boolean isDisabled = false; + boolean isEnabled = true; for (int disabledType : mUserDisabledHdrTypes) { if (type == disabledType) { - isDisabled = true; + isEnabled = false; break; } } - if (!isDisabled) { - autoHdrOutputTypesArray.add(type); + if (isEnabled) { + enabledHdrOutputTypesArray.add(type); } } - return autoHdrOutputTypesArray.toArray(); + return enabledHdrOutputTypesArray.toArray(); + } + + @VisibleForTesting + int[] getEnabledHdrOutputTypes() { + synchronized (mSyncRoot) { + return getEnabledHdrOutputTypesLocked(); + } } @GuardedBy("mSyncRoot") @@ -2531,7 +2568,7 @@ public final class DisplayManagerService extends SystemService { final int preferredHdrOutputType = mode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM ? mSystemPreferredHdrOutputType : mode.getPreferredHdrOutputType(); - if (preferredHdrOutputType != Display.HdrCapabilities.HDR_TYPE_INVALID) { + if (preferredHdrOutputType != HDR_TYPE_INVALID) { int[] hdrTypesWithLatency = mInjector.getHdrOutputTypesWithLatency(); return ArrayUtils.contains(hdrTypesWithLatency, preferredHdrOutputType); } @@ -2565,41 +2602,57 @@ public final class DisplayManagerService extends SystemService { if (!mInjector.getHdrOutputConversionSupport()) { return; } - int[] autoHdrOutputTypes = null; + synchronized (mSyncRoot) { if (hdrConversionMode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM && hdrConversionMode.getPreferredHdrOutputType() - != Display.HdrCapabilities.HDR_TYPE_INVALID) { + != HDR_TYPE_INVALID) { throw new IllegalArgumentException("preferredHdrOutputType must not be set if" + " the conversion mode is HDR_CONVERSION_SYSTEM"); } mHdrConversionMode = hdrConversionMode; storeHdrConversionModeLocked(mHdrConversionMode); - // For auto mode, all supported HDR types are allowed except the ones specifically - // disabled by the user. + // If the HDR conversion is HDR_CONVERSION_SYSTEM, all supported HDR types are allowed + // except the ones specifically disabled by the user. + int[] enabledHdrOutputTypes = null; if (hdrConversionMode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM) { - autoHdrOutputTypes = getEnabledAutoHdrTypesLocked(); + enabledHdrOutputTypes = getEnabledHdrOutputTypesLocked(); } int conversionMode = hdrConversionMode.getConversionMode(); int preferredHdrType = hdrConversionMode.getPreferredHdrOutputType(); + // If the HDR conversion is disabled by an app through WindowManager.LayoutParams, then // set HDR conversion mode to HDR_CONVERSION_PASSTHROUGH. - if (mOverrideHdrConversionMode == null) { + if (mShouldDisableHdrConversion) { + conversionMode = HdrConversionMode.HDR_CONVERSION_PASSTHROUGH; + preferredHdrType = -1; + enabledHdrOutputTypes = null; + } else { // HDR_CONVERSION_FORCE with HDR_TYPE_INVALID is used to represent forcing SDR type. - // But, internally SDR is selected by using passthrough mode. + // But, internally SDR is forced by using passthrough mode and not reporting any + // HDR capabilities to apps. if (conversionMode == HdrConversionMode.HDR_CONVERSION_FORCE - && preferredHdrType == Display.HdrCapabilities.HDR_TYPE_INVALID) { + && preferredHdrType == HDR_TYPE_INVALID) { conversionMode = HdrConversionMode.HDR_CONVERSION_PASSTHROUGH; + mLogicalDisplayMapper.forEachLocked( + logicalDisplay -> { + if (logicalDisplay.setIsForceSdr(true)) { + handleLogicalDisplayChangedLocked(logicalDisplay); + } + }); + } else { + mLogicalDisplayMapper.forEachLocked( + logicalDisplay -> { + if (logicalDisplay.setIsForceSdr(false)) { + handleLogicalDisplayChangedLocked(logicalDisplay); + } + }); } - } else { - conversionMode = mOverrideHdrConversionMode.getConversionMode(); - preferredHdrType = mOverrideHdrConversionMode.getPreferredHdrOutputType(); - autoHdrOutputTypes = null; } mSystemPreferredHdrOutputType = mInjector.setHdrConversionMode( - conversionMode, preferredHdrType, autoHdrOutputTypes); + conversionMode, preferredHdrType, enabledHdrOutputTypes); } } @@ -2621,8 +2674,8 @@ public final class DisplayManagerService extends SystemService { } HdrConversionMode mode; synchronized (mSyncRoot) { - mode = mOverrideHdrConversionMode != null - ? mOverrideHdrConversionMode + mode = mShouldDisableHdrConversion + ? new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH) : mHdrConversionMode; // Handle default: PASSTHROUGH. Don't include the system-preferred type. if (mode == null @@ -2630,8 +2683,6 @@ public final class DisplayManagerService extends SystemService { return new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH); } // Handle default or current mode: SYSTEM. Include the system preferred type. - // mOverrideHdrConversionMode and mHdrConversionMode do not include the system - // preferred type, it is kept separately in mSystemPreferredHdrOutputType. if (mode == null || mode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM) { return new HdrConversionMode( @@ -2642,10 +2693,10 @@ public final class DisplayManagerService extends SystemService { } private @Display.HdrCapabilities.HdrType int[] getSupportedHdrOutputTypesInternal() { - if (mSupportedHdrOutputType == null) { - mSupportedHdrOutputType = mInjector.getSupportedHdrOutputTypes(); + if (mSupportedHdrOutputTypes == null) { + mSupportedHdrOutputTypes = mInjector.getSupportedHdrOutputTypes(); } - return mSupportedHdrOutputType; + return mSupportedHdrOutputTypes; } void setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled) { @@ -2831,15 +2882,9 @@ public final class DisplayManagerService extends SystemService { // HDR conversion is disabled in two cases: // - HDR conversion introduces latency and minimal post-processing is requested // - app requests to disable HDR conversion - if (mOverrideHdrConversionMode == null && (disableHdrConversion - || disableHdrConversionForLatency)) { - mOverrideHdrConversionMode = - new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH); - setHdrConversionModeInternal(mHdrConversionMode); - handleLogicalDisplayChangedLocked(display); - } else if (mOverrideHdrConversionMode != null && !disableHdrConversion - && !disableHdrConversionForLatency) { - mOverrideHdrConversionMode = null; + boolean previousShouldDisableHdrConversion = mShouldDisableHdrConversion; + mShouldDisableHdrConversion = disableHdrConversion || disableHdrConversionForLatency; + if (previousShouldDisableHdrConversion != mShouldDisableHdrConversion) { setHdrConversionModeInternal(mHdrConversionMode); handleLogicalDisplayChangedLocked(display); } @@ -3530,9 +3575,9 @@ public final class DisplayManagerService extends SystemService { } int setHdrConversionMode(int conversionMode, int preferredHdrOutputType, - int[] autoHdrTypes) { + int[] allowedHdrOutputTypes) { return DisplayControl.setHdrConversionMode(conversionMode, preferredHdrOutputType, - autoHdrTypes); + allowedHdrOutputTypes); } @Display.HdrCapabilities.HdrType diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index e8be8a449652..007e3a8fde2f 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -518,6 +518,7 @@ final class LogicalDisplay { deviceInfo.supportedColorModes, deviceInfo.supportedColorModes.length); mBaseDisplayInfo.hdrCapabilities = deviceInfo.hdrCapabilities; + mBaseDisplayInfo.isForceSdr = deviceInfo.isForceSdr; mBaseDisplayInfo.userDisabledHdrTypes = mUserDisabledHdrTypes; mBaseDisplayInfo.minimalPostProcessingSupported = deviceInfo.allmSupported || deviceInfo.gameContentTypeSupported; @@ -899,6 +900,29 @@ final class LogicalDisplay { } /** + * Checks whether display is of the type where HDR settings are relevant, and then sets + * whether Force SDR conversion mode is active. isForceSdr is checked by the Display when + * returning HDR capabilities. + * + * @param isForceSdr Whether Force SDR conversion mode is active + * @return Whether Display Manager should call handleLogicalDisplayChangedLocked() + */ + public boolean setIsForceSdr(boolean isForceSdr) { + int displayType = getDisplayInfoLocked().type; + boolean isTargetDisplayType = displayType == Display.TYPE_INTERNAL + || displayType == Display.TYPE_EXTERNAL + || displayType == Display.TYPE_OVERLAY; + + boolean handleLogicalDisplayChangedLocked = false; + if (isTargetDisplayType && mBaseDisplayInfo.isForceSdr != isForceSdr) { + mBaseDisplayInfo.isForceSdr = isForceSdr; + mInfo.set(null); + handleLogicalDisplayChangedLocked = true; + } + return handleLogicalDisplayChangedLocked; + } + + /** * Swap the underlying {@link DisplayDevice} with the specified LogicalDisplay. * * @param targetDisplay The display with which to swap display-devices. diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java index ea240c75452d..9d04682f2374 100644 --- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java +++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java @@ -196,12 +196,7 @@ final class UpdatableFontDir { File signatureFile = new File(dir, FONT_SIGNATURE_FILE); if (!signatureFile.exists()) { Slog.i(TAG, "The signature file is missing."); - if (com.android.text.flags.Flags.fixFontUpdateFailure()) { - return; - } else { - FileUtils.deleteContentsAndDir(dir); - continue; - } + return; } byte[] signature; try { @@ -226,39 +221,33 @@ final class UpdatableFontDir { FontFileInfo fontFileInfo = validateFontFile(fontFile, signature); if (fontConfig == null) { - if (com.android.text.flags.Flags.fixFontUpdateFailure()) { - // Use preinstalled font config for checking revision number. - fontConfig = mConfigSupplier.apply(Collections.emptyMap()); - } else { - fontConfig = getSystemFontConfig(); - } + // Use preinstalled font config for checking revision number. + fontConfig = mConfigSupplier.apply(Collections.emptyMap()); } addFileToMapIfSameOrNewer(fontFileInfo, fontConfig, true /* deleteOldFile */); } - if (com.android.text.flags.Flags.fixFontUpdateFailure()) { - // Treat as error if post script name of font family was not installed. - for (int i = 0; i < config.fontFamilies.size(); ++i) { - FontUpdateRequest.Family family = config.fontFamilies.get(i); - for (int j = 0; j < family.getFonts().size(); ++j) { - FontUpdateRequest.Font font = family.getFonts().get(j); - if (mFontFileInfoMap.containsKey(font.getPostScriptName())) { - continue; - } - - if (fontConfig == null) { - fontConfig = mConfigSupplier.apply(Collections.emptyMap()); - } - - if (getFontByPostScriptName(font.getPostScriptName(), fontConfig) != null) { - continue; - } - - Slog.e(TAG, "Unknown font that has PostScript name " - + font.getPostScriptName() + " is requested in FontFamily " - + family.getName()); - return; + // Treat as error if post script name of font family was not installed. + for (int i = 0; i < config.fontFamilies.size(); ++i) { + FontUpdateRequest.Family family = config.fontFamilies.get(i); + for (int j = 0; j < family.getFonts().size(); ++j) { + FontUpdateRequest.Font font = family.getFonts().get(j); + if (mFontFileInfoMap.containsKey(font.getPostScriptName())) { + continue; } + + if (fontConfig == null) { + fontConfig = mConfigSupplier.apply(Collections.emptyMap()); + } + + if (getFontByPostScriptName(font.getPostScriptName(), fontConfig) != null) { + continue; + } + + Slog.e(TAG, "Unknown font that has PostScript name " + + font.getPostScriptName() + " is requested in FontFamily " + + family.getName()); + return; } } @@ -273,9 +262,7 @@ final class UpdatableFontDir { mFontFileInfoMap.clear(); mLastModifiedMillis = 0; FileUtils.deleteContents(mFilesDir); - if (com.android.text.flags.Flags.fixFontUpdateFailure()) { - mConfigFile.delete(); - } + mConfigFile.delete(); } } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 5db17bb90637..d0ad6fc0854f 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -171,6 +171,17 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { addAndStartAction( new HotplugDetectionAction(HdmiCecLocalDevicePlayback.this)); } + + if (mService.isHdmiControlEnhancedBehaviorFlagEnabled()) { + List<PowerStatusMonitorActionFromPlayback> + powerStatusMonitorActionsFromPlayback = + getActions(PowerStatusMonitorActionFromPlayback.class); + if (powerStatusMonitorActionsFromPlayback.isEmpty()) { + addAndStartAction( + new PowerStatusMonitorActionFromPlayback( + HdmiCecLocalDevicePlayback.this)); + } + } } }); addAndStartAction(action); @@ -686,6 +697,7 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { removeAction(DeviceDiscoveryAction.class); removeAction(HotplugDetectionAction.class); removeAction(NewDeviceAction.class); + removeAction(PowerStatusMonitorActionFromPlayback.class); super.disableDevice(initiatedByCec, callback); clearDeviceInfoList(); checkIfPendingActionsCleared(); diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 271836ac7d29..8e41d18f0953 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -16,6 +16,8 @@ package com.android.server.hdmi; +import static android.media.tv.flags.Flags.hdmiControlEnhancedBehavior; + 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; @@ -1378,7 +1380,8 @@ public class HdmiControlService extends SystemService { @ServiceThreadOnly private List<Integer> getCecLocalDeviceTypes() { ArrayList<Integer> allLocalDeviceTypes = new ArrayList<>(mCecLocalDevices); - if (isDsmEnabled() && !allLocalDeviceTypes.contains(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) + if (!isTvDevice() && isDsmEnabled() + && !allLocalDeviceTypes.contains(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) && isArcSupported() && mSoundbarModeFeatureFlagEnabled) { allLocalDeviceTypes.add(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); } @@ -1685,7 +1688,11 @@ public class HdmiControlService extends SystemService { private void sendCecCommandWithRetries(HdmiCecMessage command, @Nullable SendMessageCallback callback) { assertRunOnServiceThread(); - HdmiCecLocalDevice localDevice = getAllCecLocalDevices().get(0); + List<HdmiCecLocalDevice> devices = getAllCecLocalDevices(); + if (devices.isEmpty()) { + return; + } + HdmiCecLocalDevice localDevice = devices.get(0); if (localDevice != null) { sendCecCommandWithoutRetries(command, new SendMessageCallback() { @Override @@ -5137,4 +5144,8 @@ public class HdmiControlService extends SystemService { tv().startArcAction(enabled, callback); } } + + protected boolean isHdmiControlEnhancedBehaviorFlagEnabled() { + return hdmiControlEnhancedBehavior(); + } } diff --git a/services/core/java/com/android/server/hdmi/PowerStatusMonitorActionFromPlayback.java b/services/core/java/com/android/server/hdmi/PowerStatusMonitorActionFromPlayback.java new file mode 100644 index 000000000000..9a3cde156300 --- /dev/null +++ b/services/core/java/com/android/server/hdmi/PowerStatusMonitorActionFromPlayback.java @@ -0,0 +1,111 @@ +/* + * 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.hdmi; + +import static android.hardware.hdmi.HdmiControlManager.POWER_STATUS_STANDBY; + +import android.util.Slog; + +import com.android.internal.annotations.VisibleForTesting; + +/** + * This action is used by playback devices to query TV's power status such that they can go to + * standby when the TV reports power off. + */ +public class PowerStatusMonitorActionFromPlayback extends HdmiCecFeatureAction { + private static final String TAG = "PowerStatusMonitorActionFromPlayback"; + + // State that waits for <Report Power Status> once sending <Give Device Power Status> + // to all external devices. + private static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 1; + // State that waits for next monitoring. + private static final int STATE_WAIT_FOR_NEXT_MONITORING = 2; + // Monitoring interval (60s) + @VisibleForTesting + protected static final int MONITORING_INTERVAL_MS = 60000; + // Timeout once sending <Give Device Power Status> + private static final int REPORT_POWER_STATUS_TIMEOUT_MS = 5000; + // Maximum number of retries in case the <Give Device Power Status> failed being sent or times + // out. + private static final int GIVE_POWER_STATUS_FOR_SOURCE_RETRIES = 5; + private int mPowerStatusRetries = 0; + + PowerStatusMonitorActionFromPlayback(HdmiCecLocalDevice source) { + super(source); + } + + @Override + boolean start() { + // Start after timeout since the device just finished allocation. + mState = STATE_WAIT_FOR_NEXT_MONITORING; + addTimer(mState, MONITORING_INTERVAL_MS); + return true; + } + + @Override + boolean processCommand(HdmiCecMessage cmd) { + if (mState == STATE_WAIT_FOR_REPORT_POWER_STATUS + && cmd.getOpcode() == Constants.MESSAGE_REPORT_POWER_STATUS + && cmd.getSource() == Constants.ADDR_TV) { + return handleReportPowerStatusFromTv(cmd); + } + return false; + } + + private boolean handleReportPowerStatusFromTv(HdmiCecMessage cmd) { + int powerStatus = cmd.getParams()[0] & 0xFF; + if (powerStatus == POWER_STATUS_STANDBY) { + Slog.d(TAG, "TV reported it turned off, going to sleep."); + source().getService().standby(); + return true; + } + return false; + } + + @Override + void handleTimerEvent(int state) { + switch (mState) { + case STATE_WAIT_FOR_NEXT_MONITORING: + mPowerStatusRetries = 0; + queryPowerStatus(); + break; + case STATE_WAIT_FOR_REPORT_POWER_STATUS: + handleTimeout(); + break; + } + } + + private void queryPowerStatus() { + sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(), + Constants.ADDR_TV)); + + mState = STATE_WAIT_FOR_REPORT_POWER_STATUS; + addTimer(mState, REPORT_POWER_STATUS_TIMEOUT_MS); + } + + private void handleTimeout() { + if (mState == STATE_WAIT_FOR_REPORT_POWER_STATUS) { + if (mPowerStatusRetries++ < GIVE_POWER_STATUS_FOR_SOURCE_RETRIES) { + queryPowerStatus(); + } else { + mPowerStatusRetries = 0; + mState = STATE_WAIT_FOR_NEXT_MONITORING; + addTimer(mState, MONITORING_INTERVAL_MS); + } + } + } +} diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 44d675305ac0..65adaba62a4d 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -16,6 +16,9 @@ package com.android.server.input; +import static android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW; +import static android.content.PermissionChecker.PERMISSION_GRANTED; +import static android.content.PermissionChecker.PID_UNKNOWN; import static android.provider.DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT; import static android.view.KeyEvent.KEYCODE_UNKNOWN; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; @@ -37,6 +40,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.PermissionChecker; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.graphics.PixelFormat; @@ -121,6 +125,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.inputmethod.InputMethodSubtypeHandle; import com.android.internal.os.SomeArgs; +import com.android.internal.policy.KeyInterceptionInfo; import com.android.internal.util.DumpUtils; import com.android.internal.util.Preconditions; import com.android.server.DisplayThread; @@ -130,6 +135,7 @@ import com.android.server.input.InputManagerInternal.LidSwitchCallback; import com.android.server.input.debug.FocusEventDebugView; import com.android.server.input.debug.TouchpadDebugViewController; import com.android.server.policy.WindowManagerPolicy; +import com.android.server.wm.WindowManagerInternal; import libcore.io.IoUtils; @@ -177,6 +183,7 @@ public class InputManagerService extends IInputManager.Stub private final InputManagerHandler mHandler; private DisplayManagerInternal mDisplayManagerInternal; + private WindowManagerInternal mWindowManagerInternal; private PackageManagerInternal mPackageManagerInternal; private final File mDoubleTouchGestureEnableFile; @@ -449,6 +456,14 @@ public class InputManagerService extends IInputManager.Stub void registerLocalService(InputManagerInternal localService) { LocalServices.addService(InputManagerInternal.class, localService); } + + KeyboardBacklightControllerInterface getKeyboardBacklightController( + NativeInputManagerService nativeService, PersistentDataStore dataStore) { + return InputFeatureFlagProvider.isKeyboardBacklightControlEnabled() + ? new KeyboardBacklightController(mContext, nativeService, dataStore, + mLooper, mUEventManager) + : new KeyboardBacklightControllerInterface() {}; + } } public InputManagerService(Context context) { @@ -472,10 +487,7 @@ public class InputManagerService extends IInputManager.Stub injector.getLooper(), this) : null; mBatteryController = new BatteryController(mContext, mNative, injector.getLooper(), injector.getUEventManager()); - mKeyboardBacklightController = InputFeatureFlagProvider.isKeyboardBacklightControlEnabled() - ? new KeyboardBacklightController(mContext, mNative, mDataStore, - injector.getLooper(), injector.getUEventManager()) - : new KeyboardBacklightControllerInterface() {}; + mKeyboardBacklightController = injector.getKeyboardBacklightController(mNative, mDataStore); mStickyModifierStateController = new StickyModifierStateController(); mKeyGestureController = new KeyGestureController(mContext, injector.getLooper()); mKeyboardLedController = new KeyboardLedController(mContext, injector.getLooper(), @@ -548,6 +560,7 @@ public class InputManagerService extends IInputManager.Stub } mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); + mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); mSettingsObserver.registerAndUpdate(); @@ -598,6 +611,8 @@ public class InputManagerService extends IInputManager.Stub mKeyRemapper.systemRunning(); mPointerIconCache.systemRunning(); mKeyboardGlyphManager.systemRunning(); + + initKeyGestures(); } private void reloadDeviceAliases() { @@ -2471,6 +2486,11 @@ public class InputManagerService extends IInputManager.Stub long interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags) { final long keyNotConsumed = 0; long value = keyNotConsumed; + // TODO(b/358569822) Remove below once we have nicer API for listening to shortcuts + if ((event.isMetaPressed() || KeyEvent.isMetaKey(event.getKeyCode())) + && shouldInterceptShortcuts(focus)) { + return keyNotConsumed; + } if (useKeyGestureEventHandler()) { value = mKeyGestureController.interceptKeyBeforeDispatching(focus, event, policyFlags); } @@ -2481,6 +2501,69 @@ public class InputManagerService extends IInputManager.Stub return value; } + private boolean shouldInterceptShortcuts(IBinder focusedToken) { + KeyInterceptionInfo info = + mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken); + boolean hasInterceptWindowFlag = info != null && (info.layoutParamsPrivateFlags + & WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS) != 0; + return hasInterceptWindowFlag && PermissionChecker.checkPermissionForDataDelivery(mContext, + OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW, PID_UNKNOWN, info.windowOwnerUid, + null, null, null) == PERMISSION_GRANTED; + } + + private void initKeyGestures() { + if (!useKeyGestureEventHandler()) { + return; + } + InputManager im = Objects.requireNonNull(mContext.getSystemService(InputManager.class)); + im.registerKeyGestureEventHandler(new InputManager.KeyGestureEventHandler() { + @Override + public boolean handleKeyGestureEvent(@NonNull KeyGestureEvent event, + @Nullable IBinder focussedToken) { + int deviceId = event.getDeviceId(); + boolean complete = event.getAction() == KeyGestureEvent.ACTION_GESTURE_COMPLETE + && !event.isCancelled(); + switch (event.getKeyGestureType()) { + case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP: + if (complete) { + mKeyboardBacklightController.incrementKeyboardBacklight(deviceId); + } + return true; + case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN: + if (complete) { + mKeyboardBacklightController.decrementKeyboardBacklight(deviceId); + } + return true; + case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE: + // TODO(b/367748270): Add functionality to turn keyboard backlight on/off. + return true; + case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK: + if (complete) { + mNative.toggleCapsLock(deviceId); + } + return true; + default: + return false; + + } + } + + @Override + public boolean isKeyGestureSupported(int gestureType) { + switch (gestureType) { + case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP: + case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN: + case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE: + case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK: + return true; + default: + return false; + + } + } + }); + } + // Native callback. @SuppressWarnings("unused") private KeyEvent dispatchUnhandledKey(IBinder focus, KeyEvent event, int policyFlags) { @@ -3184,6 +3267,8 @@ public class InputManagerService extends IInputManager.Stub mKeyboardBacklightController.onInteractiveChanged(interactive); } + // TODO(b/358569822): Remove this method from InputManagerInternal after key gesture + // handler refactoring complete @Override public void toggleCapsLock(int deviceId) { mNative.toggleCapsLock(deviceId); @@ -3271,11 +3356,15 @@ public class InputManagerService extends IInputManager.Stub mKeyboardBacklightController.notifyUserActivity(); } + // TODO(b/358569822): Remove this method from InputManagerInternal after key gesture + // handler refactoring complete @Override public void incrementKeyboardBacklight(int deviceId) { mKeyboardBacklightController.incrementKeyboardBacklight(deviceId); } + // TODO(b/358569822): Remove this method from InputManagerInternal after key gesture + // handler refactoring complete @Override public void decrementKeyboardBacklight(int deviceId) { mKeyboardBacklightController.decrementKeyboardBacklight(deviceId); diff --git a/services/core/java/com/android/server/input/KeyGestureController.java b/services/core/java/com/android/server/input/KeyGestureController.java index 760566bad28a..7fe7891af80d 100644 --- a/services/core/java/com/android/server/input/KeyGestureController.java +++ b/services/core/java/com/android/server/input/KeyGestureController.java @@ -259,7 +259,11 @@ final class KeyGestureController { case KeyEvent.KEYCODE_N: if (firstDown && event.isMetaPressed()) { if (event.isCtrlPressed()) { - // TODO(b/358569822): Move open notes handling in System UI instead of PWM + return handleKeyGesture(deviceId, new int[]{keyCode}, + KeyEvent.META_META_ON | KeyEvent.META_CTRL_ON, + KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES, + KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId, + focusedToken, /* flags = */0); } else { return handleKeyGesture(deviceId, new int[]{keyCode}, KeyEvent.META_META_ON, diff --git a/services/core/java/com/android/server/input/debug/TouchpadDebugView.java b/services/core/java/com/android/server/input/debug/TouchpadDebugView.java index 3f11e7836609..0e940d281b09 100644 --- a/services/core/java/com/android/server/input/debug/TouchpadDebugView.java +++ b/services/core/java/com/android/server/input/debug/TouchpadDebugView.java @@ -29,7 +29,9 @@ import android.util.Slog; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; +import android.view.SurfaceControl; import android.view.ViewConfiguration; +import android.view.ViewRootImpl; import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.TextView; @@ -49,6 +51,7 @@ public class TouchpadDebugView extends LinearLayout { private static final float DEFAULT_RES_X = 47f; private static final float DEFAULT_RES_Y = 45f; private static final int TEXT_PADDING_DP = 12; + private static final int ROUNDED_CORNER_RADIUS_DP = 24; /** * Input device ID for the touchpad that this debug view is displaying. @@ -152,7 +155,35 @@ public class TouchpadDebugView extends LinearLayout { } @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + postDelayed(() -> { + final ViewRootImpl viewRootImpl = getRootView().getViewRootImpl(); + if (viewRootImpl == null) { + Slog.d("TouchpadDebugView", "ViewRootImpl is null."); + return; + } + + SurfaceControl surfaceControl = viewRootImpl.getSurfaceControl(); + if (surfaceControl != null && surfaceControl.isValid()) { + try (SurfaceControl.Transaction transaction = new SurfaceControl.Transaction()) { + transaction.setCornerRadius(surfaceControl, + TypedValue.applyDimension(COMPLEX_UNIT_DIP, + ROUNDED_CORNER_RADIUS_DP, + getResources().getDisplayMetrics())).apply(); + } + } else { + Slog.d("TouchpadDebugView", "SurfaceControl is invalid or has been released."); + } + }, 100); + } + + @Override public boolean onTouchEvent(MotionEvent event) { + if (event.getClassification() == MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE) { + return false; + } + float deltaX; float deltaY; switch (event.getAction()) { diff --git a/services/core/java/com/android/server/input/debug/TouchpadVisualizationView.java b/services/core/java/com/android/server/input/debug/TouchpadVisualizationView.java index 67c3621b7c8c..2eed9ba95413 100644 --- a/services/core/java/com/android/server/input/debug/TouchpadVisualizationView.java +++ b/services/core/java/com/android/server/input/debug/TouchpadVisualizationView.java @@ -27,20 +27,28 @@ import com.android.server.input.TouchpadFingerState; import com.android.server.input.TouchpadHardwareProperties; import com.android.server.input.TouchpadHardwareState; +import java.util.ArrayDeque; +import java.util.HashMap; +import java.util.Map; + public class TouchpadVisualizationView extends View { private static final String TAG = "TouchpadVizMain"; private static final boolean DEBUG = true; private static final float DEFAULT_RES_X = 47f; private static final float DEFAULT_RES_Y = 45f; + private static final float MAX_TRACE_HISTORY_DURATION_SECONDS = 1f; private final TouchpadHardwareProperties mTouchpadHardwareProperties; private float mScaleFactor; - TouchpadHardwareState mLatestHardwareState = new TouchpadHardwareState(0, 0, 0, 0, - new TouchpadFingerState[]{}); + private final ArrayDeque<TouchpadHardwareState> mHardwareStateHistory = + new ArrayDeque<TouchpadHardwareState>(); + private final Map<Integer, TouchpadFingerState> mTempFingerStatesByTrackingId = new HashMap<>(); private final Paint mOvalStrokePaint; private final Paint mOvalFillPaint; + private final Paint mTracePaint; + private final Paint mCenterPointPaint; private final RectF mTempOvalRect = new RectF(); public TouchpadVisualizationView(Context context, @@ -55,6 +63,29 @@ public class TouchpadVisualizationView extends View { mOvalFillPaint = new Paint(); mOvalFillPaint.setAntiAlias(true); mOvalFillPaint.setARGB(255, 0, 0, 0); + mTracePaint = new Paint(); + mTracePaint.setAntiAlias(false); + mTracePaint.setARGB(255, 0, 0, 255); + mTracePaint.setStyle(Paint.Style.STROKE); + mTracePaint.setStrokeWidth(2); + mCenterPointPaint = new Paint(); + mCenterPointPaint.setAntiAlias(true); + mCenterPointPaint.setARGB(255, 255, 0, 0); + mCenterPointPaint.setStrokeWidth(2); + } + + private void removeOldPoints() { + float latestTimestamp = mHardwareStateHistory.getLast().getTimestamp(); + + while (!mHardwareStateHistory.isEmpty()) { + TouchpadHardwareState oldestPoint = mHardwareStateHistory.getFirst(); + float onScreenTime = latestTimestamp - oldestPoint.getTimestamp(); + if (onScreenTime >= MAX_TRACE_HISTORY_DURATION_SECONDS) { + mHardwareStateHistory.removeFirst(); + } else { + break; + } + } } private void drawOval(Canvas canvas, float x, float y, float major, float minor, float angle) { @@ -71,19 +102,22 @@ public class TouchpadVisualizationView extends View { @Override protected void onDraw(Canvas canvas) { + if (mHardwareStateHistory.isEmpty()) { + return; + } + + TouchpadHardwareState latestHardwareState = mHardwareStateHistory.getLast(); + float maximumPressure = 0; - for (TouchpadFingerState touchpadFingerState : mLatestHardwareState.getFingerStates()) { + for (TouchpadFingerState touchpadFingerState : latestHardwareState.getFingerStates()) { maximumPressure = Math.max(maximumPressure, touchpadFingerState.getPressure()); } - for (TouchpadFingerState touchpadFingerState : mLatestHardwareState.getFingerStates()) { - float newX = translateRange(mTouchpadHardwareProperties.getLeft(), - mTouchpadHardwareProperties.getRight(), 0, getWidth(), - touchpadFingerState.getPositionX()); + // Visualizing fingers as ovals + for (TouchpadFingerState touchpadFingerState : latestHardwareState.getFingerStates()) { + float newX = translateX(touchpadFingerState.getPositionX()); - float newY = translateRange(mTouchpadHardwareProperties.getTop(), - mTouchpadHardwareProperties.getBottom(), 0, getHeight(), - touchpadFingerState.getPositionY()); + float newY = translateY(touchpadFingerState.getPositionY()); float newAngle = translateRange(0, mTouchpadHardwareProperties.getOrientationMaximum(), 0, 90, touchpadFingerState.getOrientation()); @@ -102,6 +136,28 @@ public class TouchpadVisualizationView extends View { drawOval(canvas, newX, newY, newTouchMajor, newTouchMinor, newAngle); } + + mTempFingerStatesByTrackingId.clear(); + + // Drawing the trace + for (TouchpadHardwareState currentHardwareState : mHardwareStateHistory) { + for (TouchpadFingerState currentFingerState : currentHardwareState.getFingerStates()) { + TouchpadFingerState prevFingerState = mTempFingerStatesByTrackingId.put( + currentFingerState.getTrackingId(), currentFingerState); + + if (prevFingerState == null) { + continue; + } + + float currentX = translateX(currentFingerState.getPositionX()); + float currentY = translateY(currentFingerState.getPositionY()); + float prevX = translateX(prevFingerState.getPositionX()); + float prevY = translateY(prevFingerState.getPositionY()); + + canvas.drawLine(prevX, prevY, currentX, currentY, mTracePaint); + canvas.drawPoint(currentX, currentY, mCenterPointPaint); + } + } } /** @@ -114,7 +170,18 @@ public class TouchpadVisualizationView extends View { logHardwareState(schs); } - mLatestHardwareState = schs; + if (!mHardwareStateHistory.isEmpty() + && mHardwareStateHistory.getLast().getFingerCount() == 0 + && schs.getFingerCount() > 0) { + mHardwareStateHistory.clear(); + } + + mHardwareStateHistory.addLast(schs); + removeOldPoints(); + + if (DEBUG) { + logFingerTrace(); + } invalidate(); } @@ -128,6 +195,16 @@ public class TouchpadVisualizationView extends View { mScaleFactor = scaleFactor; } + private float translateX(float x) { + return translateRange(mTouchpadHardwareProperties.getLeft(), + mTouchpadHardwareProperties.getRight(), 0, getWidth(), x); + } + + private float translateY(float y) { + return translateRange(mTouchpadHardwareProperties.getTop(), + mTouchpadHardwareProperties.getBottom(), 0, getHeight(), y); + } + private float translateRange(float rangeBeforeMin, float rangeBeforeMax, float rangeAfterMin, float rangeAfterMax, float value) { return rangeAfterMin + (value - rangeBeforeMin) / (rangeBeforeMax - rangeBeforeMin) * ( @@ -154,4 +231,10 @@ public class TouchpadVisualizationView extends View { } } -} + private void logFingerTrace() { + Slog.d(TAG, "Trace size= " + mHardwareStateHistory.size()); + for (TouchpadFingerState tfs : mHardwareStateHistory.getLast().getFingerStates()) { + Slog.d(TAG, "ID= " + tfs.getTrackingId()); + } + } +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index f7478799527c..2bb2b7b21cce 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -6107,7 +6107,22 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. final int argUserId = parseUserIdFromDumpArgs(args); final Printer p = new PrintWriterPrinter(pw); p.println("Current Input Method Manager state:"); - p.println(" concurrentMultiUserModeEnabled=" + mConcurrentMultiUserModeEnabled); + p.println(" mSystemReady=" + mSystemReady); + p.println(" mInteractive=" + mIsInteractive); + p.println(" mConcurrentMultiUserModeEnabled=" + mConcurrentMultiUserModeEnabled); + p.println(" ENABLE_HIDE_IME_CAPTION_BAR=" + + InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR); + synchronized (ImfLock.class) { + p.println(" mStylusIds=" + (mStylusIds != null + ? Arrays.toString(mStylusIds.toArray()) : "")); + } + if (Flags.imeSwitcherRevamp()) { + p.println(" mMenuControllerNew:"); + mMenuControllerNew.dump(p, " "); + } else { + p.println(" mMenuController:"); + mMenuController.dump(p, " "); + } if (mConcurrentMultiUserModeEnabled && argUserId == UserHandle.USER_NULL) { mUserDataRepository.forAllUserData( u -> dumpAsStringNoCheckForUser(u, fd, pw, args, isCritical)); @@ -6116,6 +6131,22 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. final var userData = getUserData(userId); dumpAsStringNoCheckForUser(userData, fd, pw, args, isCritical); } + + // TODO(b/365868861): Make StartInputHistory, SoftInputShowHideHistory and ImeTracker per + // user. + synchronized (ImfLock.class) { + p.println(" mStartInputHistory:"); + mStartInputHistory.dump(pw, " "); + + p.println(" mSoftInputShowHideHistory:"); + mSoftInputShowHideHistory.dump(pw, " "); + } + + p.println(" mImeTrackerService#History:"); + mImeTrackerService.dump(pw, " "); + + dumpUserRepository(p); + dumpClientStates(p); } @UserIdInt @@ -6140,104 +6171,33 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. userData.mUserId); final List<InputMethodInfo> methodList = settings.getMethodList(); int numImes = methodList.size(); - p.println(" Input Methods:"); + p.println(" Input Methods:"); for (int i = 0; i < numImes; i++) { InputMethodInfo info = methodList.get(i); - p.println(" InputMethod #" + i + ":"); - info.dump(p, " "); + p.println(" InputMethod #" + i + ":"); + info.dump(p, " "); } - // Dump ClientController#mClients - p.println(" ClientStates:"); - // TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed. - @SuppressWarnings("GuardedBy") Consumer<ClientState> clientControllerDump = c -> { - p.println(" " + c + ":"); - p.println(" client=" + c.mClient); - p.println(" fallbackInputConnection=" - + c.mFallbackInputConnection); - p.println(" sessionRequested=" - + c.mSessionRequested); - p.println(" sessionRequestedForAccessibility=" - + c.mSessionRequestedForAccessibility); - p.println(" curSession=" + c.mCurSession); - p.println(" selfReportedDisplayId=" + c.mSelfReportedDisplayId); - p.println(" uid=" + c.mUid); - p.println(" pid=" + c.mPid); - }; - mClientController.forAllClients(clientControllerDump); final var bindingController = userData.mBindingController; - p.println(" mCurMethodId=" + bindingController.getSelectedMethodId()); + p.println(" mCurMethodId=" + bindingController.getSelectedMethodId()); client = userData.mCurClient; - p.println(" mCurClient=" + client + " mCurSeq=" + p.println(" mCurClient=" + client + " mCurSeq=" + bindingController.getSequenceNumber()); - p.println(" mFocusedWindowPerceptible=" + mFocusedWindowPerceptible); + p.println(" mFocusedWindowPerceptible=" + mFocusedWindowPerceptible); userData.mImeBindingState.dump(/* prefix= */ " ", p); - - p.println(" mCurId=" + bindingController.getCurId() - + " mHaveConnection=" + bindingController.hasMainConnection() - + " mBoundToMethod=" + userData.mBoundToMethod + " mVisibleBound=" - + bindingController.isVisibleBound()); - - p.println(" mUserDataRepository="); - // TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed. - @SuppressWarnings("GuardedBy") Consumer<UserData> userDataDump = - u -> { - p.println(" mUserId=" + u.mUserId); - p.println(" unlocked=" + u.mIsUnlockingOrUnlocked.get()); - p.println(" hasMainConnection=" - + u.mBindingController.hasMainConnection()); - p.println(" isVisibleBound=" + u.mBindingController.isVisibleBound()); - p.println(" boundToMethod=" + u.mBoundToMethod); - p.println(" curClient=" + u.mCurClient); - if (u.mCurEditorInfo != null) { - p.println(" curEditorInfo:"); - u.mCurEditorInfo.dump(p, " ", false /* dumpExtras */); - } else { - p.println(" curEditorInfo: null"); - } - p.println(" imeBindingState:"); - u.mImeBindingState.dump(" ", p); - p.println(" enabledSession=" + u.mEnabledSession); - p.println(" inFullscreenMode=" + u.mInFullscreenMode); - p.println(" imeDrawsNavBar=" + u.mImeDrawsNavBar.get()); - p.println(" switchingController:"); - u.mSwitchingController.dump(p, " "); - p.println(" mLastEnabledInputMethodsStr=" - + u.mLastEnabledInputMethodsStr); - }; - mUserDataRepository.forAllUserData(userDataDump); - - if (Flags.imeSwitcherRevamp()) { - p.println(" menuControllerNew:"); - mMenuControllerNew.dump(p, " "); - } else { - p.println(" menuController:"); - mMenuController.dump(p, " "); - } - p.println(" mCurToken=" + bindingController.getCurToken()); - p.println(" mCurTokenDisplayId=" + bindingController.getCurTokenDisplayId()); - p.println(" mCurHostInputToken=" + bindingController.getCurHostInputToken()); - p.println(" mCurIntent=" + bindingController.getCurIntent()); + p.println(" mCurId=" + bindingController.getCurId()); + p.println(" mHaveConnection=" + bindingController.hasMainConnection()); + p.println(" mBoundToMethod=" + userData.mBoundToMethod); + p.println(" mVisibleBound=" + bindingController.isVisibleBound()); + p.println(" mCurToken=" + bindingController.getCurToken()); + p.println(" mCurTokenDisplayId=" + bindingController.getCurTokenDisplayId()); + p.println(" mCurHostInputToken=" + bindingController.getCurHostInputToken()); + p.println(" mCurIntent=" + bindingController.getCurIntent()); method = bindingController.getCurMethod(); - p.println(" mCurMethod=" + method); - p.println(" mEnabledSession=" + userData.mEnabledSession); + p.println(" mCurMethod=" + method); + p.println(" mEnabledSession=" + userData.mEnabledSession); final var visibilityStateComputer = userData.mVisibilityStateComputer; visibilityStateComputer.dump(pw, " "); - p.println(" mInFullscreenMode=" + userData.mInFullscreenMode); - p.println(" mSystemReady=" + mSystemReady + " mInteractive=" + mIsInteractive); - p.println(" mConcurrentMultiUserModeEnabled=" + mConcurrentMultiUserModeEnabled); - p.println(" ENABLE_HIDE_IME_CAPTION_BAR=" - + InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR); - p.println(" mStylusIds=" + (mStylusIds != null - ? Arrays.toString(mStylusIds.toArray()) : "")); - - p.println(" mStartInputHistory:"); - mStartInputHistory.dump(pw, " "); - - p.println(" mSoftInputShowHideHistory:"); - mSoftInputShowHideHistory.dump(pw, " "); - - p.println(" mImeTrackerService#History:"); - mImeTrackerService.dump(pw, " "); + p.println(" mInFullscreenMode=" + userData.mInFullscreenMode); } // Exit here for critical dump, as remaining sections require IPCs to other processes. @@ -6288,6 +6248,61 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. } } + private void dumpClientStates(Printer p) { + p.println(" ClientStates:"); + // TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed. + @SuppressWarnings("GuardedBy") Consumer<ClientState> clientControllerDump = c -> { + p.println(" " + c + ":"); + p.println(" client=" + c.mClient); + p.println(" fallbackInputConnection=" + + c.mFallbackInputConnection); + p.println(" sessionRequested=" + + c.mSessionRequested); + p.println(" sessionRequestedForAccessibility=" + + c.mSessionRequestedForAccessibility); + p.println(" curSession=" + c.mCurSession); + p.println(" selfReportedDisplayId=" + c.mSelfReportedDisplayId); + p.println(" uid=" + c.mUid); + p.println(" pid=" + c.mPid); + }; + synchronized (ImfLock.class) { + mClientController.forAllClients(clientControllerDump); + } + } + + private void dumpUserRepository(Printer p) { + p.println(" mUserDataRepository="); + // TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed. + @SuppressWarnings("GuardedBy") Consumer<UserData> userDataDump = + u -> { + p.println(" mUserId=" + u.mUserId); + p.println(" unlocked=" + u.mIsUnlockingOrUnlocked.get()); + p.println(" hasMainConnection=" + + u.mBindingController.hasMainConnection()); + p.println(" isVisibleBound=" + u.mBindingController.isVisibleBound()); + p.println(" boundToMethod=" + u.mBoundToMethod); + p.println(" curClient=" + u.mCurClient); + if (u.mCurEditorInfo != null) { + p.println(" curEditorInfo:"); + u.mCurEditorInfo.dump(p, " ", false /* dumpExtras */); + } else { + p.println(" curEditorInfo: null"); + } + p.println(" imeBindingState:"); + u.mImeBindingState.dump(" ", p); + p.println(" enabledSession=" + u.mEnabledSession); + p.println(" inFullscreenMode=" + u.mInFullscreenMode); + p.println(" imeDrawsNavBar=" + u.mImeDrawsNavBar.get()); + p.println(" switchingController:"); + u.mSwitchingController.dump(p, " "); + p.println(" mLastEnabledInputMethodsStr=" + + u.mLastEnabledInputMethodsStr); + }; + synchronized (ImfLock.class) { + mUserDataRepository.forAllUserData(userDataDump); + } + } + @BinderThread @Override public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out, diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java index 4b2c12abe5bb..63bd9ab815b2 100644 --- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java @@ -389,7 +389,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // Reload gnss config for no SIM case mGnssConfiguration.reloadGpsProperties(); } - if (Flags.enableNiSuplMessageInjectionByCarrierConfig()) { + if (Flags.enableNiSuplMessageInjectionByCarrierConfigBugfix()) { updateNiSuplMessageListenerRegistration( mGnssConfiguration.isNiSuplMessageInjectionEnabled()); } @@ -538,7 +538,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements intentFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); mContext.registerReceiver(mIntentReceiver, intentFilter, null, mHandler); - if (!Flags.enableNiSuplMessageInjectionByCarrierConfig()) { + if (!Flags.enableNiSuplMessageInjectionByCarrierConfigBugfix()) { updateNiSuplMessageListenerRegistration( mGnssConfiguration.isNiSuplMessageInjectionEnabled()); } @@ -1672,7 +1672,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements if (dumpAll) { mNetworkTimeHelper.dump(pw); pw.println("mSupportsPsds=" + mSupportsPsds); - if (Flags.enableNiSuplMessageInjectionByCarrierConfig()) { + if (Flags.enableNiSuplMessageInjectionByCarrierConfigBugfix()) { pw.println("mNiSuplMessageListenerRegistered=" + mNiSuplMessageListenerRegistered); } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java index 158d444bcff2..1e25f1cf1d5e 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java @@ -140,7 +140,7 @@ class LockSettingsStorage { try { db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?", new String[] {key, Integer.toString(userId)}); - db.insert(TABLE, null, cv); + db.insertOrThrow(TABLE, null, cv); db.setTransactionSuccessful(); mCache.putKeyValue(key, value, userId); } finally { 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 621c090d37b8..48d24f2e14dd 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java @@ -179,7 +179,8 @@ public final class MediaProjectionManagerService extends SystemService /** * In order to record the keyguard, the MediaProjection package must be either: * - a holder of RECORD_SENSITIVE_CONTENT permission, or - * - be one of the bugreport whitelisted packages + * - be one of the bugreport allowlisted packages, or + * - hold the OP_PROJECT_MEDIA AppOp. */ private boolean canCaptureKeyguard() { if (!android.companion.virtualdevice.flags.Flags.mediaProjectionKeyguardRestrictions()) { @@ -194,6 +195,14 @@ public final class MediaProjectionManagerService extends SystemService == PackageManager.PERMISSION_GRANTED) { return true; } + boolean operationActive = mAppOps.isOperationActive(AppOpsManager.OP_PROJECT_MEDIA, + mProjectionGrant.uid, + mProjectionGrant.packageName); + if (operationActive) { + // Some tools use media projection by granting the OP_PROJECT_MEDIA app + // op via a shell command. Those tools can be granted keyguard capture + return true; + } return SystemConfig.getInstance().getBugreportWhitelistedPackages() .contains(mProjectionGrant.packageName); } diff --git a/services/core/java/com/android/server/notification/VibratorHelper.java b/services/core/java/com/android/server/notification/VibratorHelper.java index fbe77720b9fc..f54c1f7654dc 100644 --- a/services/core/java/com/android/server/notification/VibratorHelper.java +++ b/services/core/java/com/android/server/notification/VibratorHelper.java @@ -218,10 +218,16 @@ public final class VibratorHelper { * @param uri {@code Uri} an uri including query parameter "vibraiton_uri" */ public @Nullable VibrationEffect createVibrationEffectFromSoundUri(Uri uri) { - if (uri == null) { + if (uri == null || uri.isOpaque()) { return null; } - return Utils.parseVibrationEffect(mVibrator, Utils.getVibrationUri(uri)); + + try { + return Utils.parseVibrationEffect(mVibrator, Utils.getVibrationUri(uri)); + } catch (Exception e) { + Slog.e(TAG, "Failed to get vibration effect: ", e); + } + return null; } /** Returns if a given vibration can be played by the vibrator that does notification buzz. */ diff --git a/services/core/java/com/android/server/notification/ZenModeConditions.java b/services/core/java/com/android/server/notification/ZenModeConditions.java index d495ef5ce108..50bfbc3530a9 100644 --- a/services/core/java/com/android/server/notification/ZenModeConditions.java +++ b/services/core/java/com/android/server/notification/ZenModeConditions.java @@ -157,7 +157,7 @@ public class ZenModeConditions implements ConditionProviders.Callback { } // empty rule? disable and bail early if (rule.component == null && rule.enabler == null) { - if (!android.app.Flags.modesUi() || (android.app.Flags.modesUi() && !isManual)) { + if (!isManual) { Log.w(TAG, "No component found for automatic rule: " + rule.conditionId); rule.enabled = false; } diff --git a/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java b/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java index 41351613331d..5aea356a4173 100644 --- a/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java +++ b/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java @@ -18,6 +18,7 @@ package com.android.server.pm; import static android.media.AudioAttributes.USAGE_ALARM; +import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.Notification; @@ -42,6 +43,8 @@ import android.util.Log; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; +import java.util.List; + public class BackgroundUserSoundNotifier { private static final boolean DEBUG = false; @@ -49,11 +52,21 @@ public class BackgroundUserSoundNotifier { private static final String BUSN_CHANNEL_ID = "bg_user_sound_channel"; private static final String BUSN_CHANNEL_NAME = "BackgroundUserSound"; public static final String ACTION_MUTE_SOUND = "com.android.server.ACTION_MUTE_BG_USER"; - private static final String EXTRA_NOTIFICATION_ID = "com.android.server.EXTRA_CLIENT_UID"; - private static final String EXTRA_CURRENT_USER_ID = "com.android.server.EXTRA_CURRENT_USER_ID"; private static final String ACTION_SWITCH_USER = "com.android.server.ACTION_SWITCH_TO_USER"; - /** ID of user with notification displayed, -1 if notification is not showing*/ - private int mUserWithNotification = -1; + private static final String ACTION_DISMISS_NOTIFICATION = + "com.android.server.ACTION_DISMISS_NOTIFICATION"; + /** + * The clientUid from the AudioFocusInfo of the background user, + * for which an active notification is currently displayed. + * Set to -1 if no notification is being shown. + * TODO: b/367615180 - add support for multiple simultaneous alarms + */ + @VisibleForTesting + int mNotificationClientUid = -1; + @VisibleForTesting + AudioPolicy mFocusControlAudioPolicy; + @VisibleForTesting + BackgroundUserListener mBgUserListener; private final Context mSystemUserContext; @VisibleForTesting final NotificationManager mNotificationManager; @@ -67,11 +80,18 @@ public class BackgroundUserSoundNotifier { mSystemUserContext = context; mNotificationManager = mSystemUserContext.getSystemService(NotificationManager.class); mUserManager = mSystemUserContext.getSystemService(UserManager.class); + createNotificationChannel(); + setupFocusControlAudioPolicy(); + } + + /** + * Creates a dedicated channel for background user related notifications. + */ + private void createNotificationChannel() { NotificationChannel channel = new NotificationChannel(BUSN_CHANNEL_ID, BUSN_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH); channel.setSound(null, null); mNotificationManager.createNotificationChannel(channel); - setupFocusControlAudioPolicy(); } private void setupFocusControlAudioPolicy() { @@ -81,15 +101,16 @@ public class BackgroundUserSoundNotifier { ActivityManager am = mSystemUserContext.getSystemService(ActivityManager.class); registerReceiver(am); - BackgroundUserListener bgUserListener = new BackgroundUserListener(mSystemUserContext); + mBgUserListener = new BackgroundUserListener(mSystemUserContext); AudioPolicy.Builder focusControlPolicyBuilder = new AudioPolicy.Builder(mSystemUserContext); focusControlPolicyBuilder.setLooper(Looper.getMainLooper()); - focusControlPolicyBuilder.setAudioPolicyFocusListener(bgUserListener); + focusControlPolicyBuilder.setAudioPolicyFocusListener(mBgUserListener); - AudioPolicy mFocusControlAudioPolicy = focusControlPolicyBuilder.build(); + mFocusControlAudioPolicy = focusControlPolicyBuilder.build(); int status = mSystemUserContext.getSystemService(AudioManager.class) .registerAudioPolicy(mFocusControlAudioPolicy); + if (status != AudioManager.SUCCESS) { Log.w(LOG_TAG , "Could not register the service's focus" + " control audio policy, error: " + status); @@ -117,123 +138,170 @@ public class BackgroundUserSoundNotifier { @SuppressLint("MissingPermission") public void onAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) { - BackgroundUserSoundNotifier.this.dismissNotificationIfNecessary(afi); + BackgroundUserSoundNotifier.this.dismissNotificationIfNecessary(); } } + @VisibleForTesting + BackgroundUserListener getAudioPolicyFocusListener() { + return mBgUserListener; + } + /** * Registers a BroadcastReceiver for actions related to background user sound notifications. * When ACTION_MUTE_SOUND is received, it mutes a background user's alarm sound. * When ACTION_SWITCH_USER is received, a switch to the background user with alarm is started. */ - private void registerReceiver(ActivityManager service) { + private void registerReceiver(ActivityManager activityManager) { BroadcastReceiver backgroundUserNotificationBroadcastReceiver = new BroadcastReceiver() { @SuppressLint("MissingPermission") @Override public void onReceive(Context context, Intent intent) { - if (!(intent.hasExtra(EXTRA_NOTIFICATION_ID) - && intent.hasExtra(EXTRA_CURRENT_USER_ID) - && intent.hasExtra(Intent.EXTRA_USER_ID))) { + if (mNotificationClientUid == -1) { return; } - final int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1); + dismissNotification(); if (DEBUG) { - Log.d(LOG_TAG, - "User with alarm id " + intent.getIntExtra(Intent.EXTRA_USER_ID, - -1) + " current user id " + intent.getIntExtra( - EXTRA_CURRENT_USER_ID, -1)); + final int actionIndex = intent.getAction().lastIndexOf(".") + 1; + final String action = intent.getAction().substring(actionIndex); + Log.d(LOG_TAG, "Action requested: " + action + ", by userId " + + ActivityManager.getCurrentUser() + " for alarm on user " + + UserHandle.getUserHandleForUid(mNotificationClientUid)); } - mUserWithNotification = -1; - mNotificationManager.cancelAsUser(LOG_TAG, notificationId, - UserHandle.of(intent.getIntExtra(EXTRA_CURRENT_USER_ID, -1))); + if (ACTION_MUTE_SOUND.equals(intent.getAction())) { - final AudioManager audioManager = - mSystemUserContext.getSystemService(AudioManager.class); - if (audioManager != null) { - for (AudioPlaybackConfiguration apc : - audioManager.getActivePlaybackConfigurations()) { - if (apc.getAudioAttributes().getUsage() == USAGE_ALARM) { - if (apc.getPlayerProxy() != null) { - apc.getPlayerProxy().stop(); - } - } - } - } + muteAlarmSounds(mSystemUserContext); } else if (ACTION_SWITCH_USER.equals(intent.getAction())) { - service.switchUser(intent.getIntExtra(Intent.EXTRA_USER_ID, -1)); + activityManager.switchUser(UserHandle.getUserId(mNotificationClientUid)); } + + mNotificationClientUid = -1; } }; IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_MUTE_SOUND); filter.addAction(ACTION_SWITCH_USER); + filter.addAction(ACTION_DISMISS_NOTIFICATION); mSystemUserContext.registerReceiver(backgroundUserNotificationBroadcastReceiver, filter, Context.RECEIVER_NOT_EXPORTED); } /** + * Stop player proxy for the ongoing alarm and drop focus for its AudioFocusInfo. + */ + @VisibleForTesting + void muteAlarmSounds(Context context) { + AudioManager audioManager = context.getSystemService(AudioManager.class); + if (audioManager != null) { + for (AudioPlaybackConfiguration apc : audioManager.getActivePlaybackConfigurations()) { + if (apc.getClientUid() == mNotificationClientUid && apc.getPlayerProxy() != null) { + apc.getPlayerProxy().stop(); + } + } + } + } + + /** * Check if sound is coming from background user and show notification is required. */ @VisibleForTesting - void notifyForegroundUserAboutSoundIfNecessary(AudioFocusInfo afi, Context - foregroundContext) throws RemoteException { + void notifyForegroundUserAboutSoundIfNecessary(AudioFocusInfo afi, Context foregroundContext) + throws RemoteException { final int userId = UserHandle.getUserId(afi.getClientUid()); final int usage = afi.getAttributes().getUsage(); UserInfo userInfo = mUserManager.getUserInfo(userId); - if (userInfo != null && userId != foregroundContext.getUserId()) { + // Only show notification if the sound is coming from background user and the notification + // is not already shown. + if (userInfo != null && userId != foregroundContext.getUserId() + && mNotificationClientUid == -1) { //TODO: b/349138482 - Add handling of cases when usage == USAGE_NOTIFICATION_RINGTONE if (usage == USAGE_ALARM) { - Intent muteIntent = createIntent(ACTION_MUTE_SOUND, afi, foregroundContext, userId); - PendingIntent mutePI = PendingIntent.getBroadcast(mSystemUserContext, 0, - muteIntent, PendingIntent.FLAG_UPDATE_CURRENT - | PendingIntent.FLAG_IMMUTABLE); - Intent switchIntent = createIntent(ACTION_SWITCH_USER, afi, foregroundContext, - userId); - PendingIntent switchPI = PendingIntent.getBroadcast(mSystemUserContext, 0, - switchIntent, PendingIntent.FLAG_UPDATE_CURRENT - | PendingIntent.FLAG_IMMUTABLE); - - mUserWithNotification = foregroundContext.getUserId(); - mNotificationManager.notifyAsUser(LOG_TAG, afi.getClientUid(), - createNotification(userInfo.name, mutePI, switchPI, foregroundContext), + if (DEBUG) { + Log.d(LOG_TAG, "Alarm ringing on background user " + userId + + ", displaying notification for current user " + + foregroundContext.getUserId()); + } + + mNotificationClientUid = afi.getClientUid(); + + mNotificationManager.notifyAsUser(LOG_TAG, mNotificationClientUid, + createNotification(userInfo.name, foregroundContext), foregroundContext.getUser()); } } } /** - * If notification is present, dismisses it. To be called when the relevant sound loses focus. + * Dismisses notification if the associated focus has been removed from the focus stack. + * Notification remains if the focus is temporarily lost due to another client taking over the + * focus ownership. */ - private void dismissNotificationIfNecessary(AudioFocusInfo afi) { - if (mUserWithNotification >= 0) { - mNotificationManager.cancelAsUser(LOG_TAG, afi.getClientUid(), - UserHandle.of(mUserWithNotification)); + @VisibleForTesting + void dismissNotificationIfNecessary() { + if (getAudioFocusInfoForNotification() == null && mNotificationClientUid >= 0) { + if (DEBUG) { + Log.d(LOG_TAG, "Alarm ringing on background user " + + UserHandle.getUserHandleForUid(mNotificationClientUid).getIdentifier() + + " left focus stack, dismissing notification"); + } + dismissNotification(); + mNotificationClientUid = -1; } - mUserWithNotification = -1; } - private Intent createIntent(String intentAction, AudioFocusInfo afi, Context fgUserContext, - int userId) { + /** + * Dismisses notification for all users in case user switch occurred after notification was + * shown. + */ + @SuppressLint("MissingPermission") + private void dismissNotification() { + mNotificationManager.cancelAsUser(LOG_TAG, mNotificationClientUid, UserHandle.ALL); + } + + /** + * Returns AudioFocusInfo associated with the current notification. + */ + @SuppressLint("MissingPermission") + @VisibleForTesting + @Nullable + AudioFocusInfo getAudioFocusInfoForNotification() { + if (mNotificationClientUid >= 0) { + List<AudioFocusInfo> stack = mFocusControlAudioPolicy.getFocusStack(); + for (int i = stack.size() - 1; i >= 0; i--) { + if (stack.get(i).getClientUid() == mNotificationClientUid) { + return stack.get(i); + } + } + } + return null; + } + + private PendingIntent createPendingIntent(String intentAction) { final Intent intent = new Intent(intentAction); - intent.putExtra(EXTRA_CURRENT_USER_ID, fgUserContext.getUserId()); - intent.putExtra(EXTRA_NOTIFICATION_ID, afi.getClientUid()); - intent.putExtra(Intent.EXTRA_USER_ID, userId); - return intent; + PendingIntent resultPI = PendingIntent.getBroadcast(mSystemUserContext, 0, intent, + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); + return resultPI; } - private Notification createNotification(String userName, PendingIntent muteIntent, - PendingIntent switchIntent, Context fgContext) { + @VisibleForTesting + Notification createNotification(String userName, Context fgContext) { final String title = fgContext.getString(R.string.bg_user_sound_notification_title_alarm, userName); final int icon = R.drawable.ic_audio_alarm; + + PendingIntent mutePI = createPendingIntent(ACTION_MUTE_SOUND); + PendingIntent switchPI = createPendingIntent(ACTION_SWITCH_USER); + PendingIntent dismissNotificationPI = createPendingIntent(ACTION_DISMISS_NOTIFICATION); + final Notification.Action mute = new Notification.Action.Builder(null, fgContext.getString(R.string.bg_user_sound_notification_button_mute), - muteIntent).build(); + mutePI).build(); final Notification.Action switchUser = new Notification.Action.Builder(null, fgContext.getString(R.string.bg_user_sound_notification_button_switch_user), - switchIntent).build(); + switchPI).build(); + Notification.Builder notificationBuilder = new Notification.Builder(mSystemUserContext, BUSN_CHANNEL_ID) .setSmallIcon(icon) @@ -243,16 +311,18 @@ public class BackgroundUserSoundNotifier { .setOngoing(true) .setColor(fgContext.getColor(R.color.system_notification_accent_color)) .setContentTitle(title) - .setContentIntent(muteIntent) + .setContentIntent(mutePI) .setAutoCancel(true) + .setDeleteIntent(dismissNotificationPI) .setVisibility(Notification.VISIBILITY_PUBLIC); + if (mUserManager.isUserSwitcherEnabled() && (mUserManager.getUserSwitchability( - UserHandle.of(fgContext.getUserId())) == UserManager.SWITCHABILITY_STATUS_OK)) { + fgContext.getUser()) == UserManager.SWITCHABILITY_STATUS_OK)) { notificationBuilder.setActions(mute, switchUser); } else { notificationBuilder.setActions(mute); } + return notificationBuilder.build(); } } - diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index ee15bec0d62b..efd58ed6edcc 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -92,7 +92,6 @@ import android.graphics.Rect; import android.multiuser.Flags; import android.net.Uri; import android.os.Binder; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IInterface; @@ -215,7 +214,7 @@ public class LauncherAppsService extends SystemService { @VisibleForTesting static class LauncherAppsImpl extends ILauncherApps.Stub { - private static final boolean DEBUG = Build.IS_DEBUGGABLE; + private static final boolean DEBUG = false; private static final String TAG = "LauncherAppsService"; private static final String NAMESPACE_MULTIUSER = "multiuser"; private static final String FLAG_NON_SYSTEM_ACCESS_TO_HIDDEN_PROFILES = @@ -496,28 +495,8 @@ public class LauncherAppsService extends SystemService { private boolean canAccessProfile(int callingUid, int callingUserId, int callingPid, int targetUserId, String message) { - if (DEBUG) { - final AndroidPackage callingPackage = - mPackageManagerInternal.getPackage(callingUid); - final String callingPackageName = callingPackage == null - ? null : callingPackage.getPackageName(); - Slog.v(TAG, "canAccessProfile called by " + callingPackageName - + " for user " + callingUserId - + " requesting to access user " - + targetUserId + " when invoking " + message); - } - if (targetUserId == callingUserId) { - if (DEBUG) { - Slog.v(TAG, message + " passed canAccessProfile for targetuser" - + targetUserId + " because it is the same as the calling user"); - } - return true; - } + if (targetUserId == callingUserId) return true; if (injectHasInteractAcrossUsersFullPermission(callingPid, callingUid)) { - if (DEBUG) { - Slog.v(TAG, message + " passed because calling process" - + "has permission to interact across users"); - } return true; } @@ -535,25 +514,11 @@ public class LauncherAppsService extends SystemService { if (isHiddenProfile(UserHandle.of(targetUserId)) && !canAccessHiddenProfile(callingUid, callingPid)) { - Slog.w(TAG, message + " for hidden profile user " + targetUserId - + " from " + callingUserId + " not allowed"); - return false; } - final boolean ret = mUserManagerInternal.isProfileAccessible( - callingUserId, targetUserId, message, true); - if (DEBUG) { - final AndroidPackage callingPackage = - mPackageManagerInternal.getPackage(callingUid); - final String callingPackageName = callingPackage == null - ? null : callingPackage.getPackageName(); - Slog.v(TAG, "canAccessProfile returned " + ret + " for " + callingPackageName - + " for user " + callingUserId - + " requesting to access user " - + targetUserId + " when invoking " + message); - } - return ret; + return mUserManagerInternal.isProfileAccessible(callingUserId, targetUserId, + message, true); } private boolean isHiddenProfile(UserHandle targetUser) { @@ -1376,10 +1341,6 @@ public class LauncherAppsService extends SystemService { @Override public void pinShortcuts(String callingPackage, String packageName, List<String> ids, UserHandle targetUser) { - if (DEBUG) { - Slog.v(TAG, "pinShortcuts: " + callingPackage + " is pinning shortcuts from " - + packageName + " for user " + targetUser); - } if (!mShortcutServiceInternal .areShortcutsSupportedOnHomeScreen(targetUser.getIdentifier())) { // Requires strict ACCESS_SHORTCUTS permission for user-profiles with items @@ -1390,11 +1351,6 @@ public class LauncherAppsService extends SystemService { } ensureShortcutPermission(callingPackage); if (!canAccessProfile(targetUser.getIdentifier(), "Cannot pin shortcuts")) { - if (DEBUG) { - Slog.v(TAG, "pinShortcuts: " + callingPackage - + " is pinning shortcuts from " + packageName - + " for user " + targetUser + " but cannot access profile"); - } return; } @@ -2451,7 +2407,7 @@ public class LauncherAppsService extends SystemService { final int callbackUserId = callbackUser.getIdentifier(); final int shortcutUserId = shortcutUser.getIdentifier(); - if (shortcutUser == callbackUser) return true; + if ((shortcutUser.equals(callbackUser))) return true; return mUserManagerInternal.isProfileAccessible(callbackUserId, shortcutUserId, null, false); } @@ -2485,16 +2441,28 @@ public class LauncherAppsService extends SystemService { final BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); if (!isEnabledProfileOf(cookie, user, "onPackageRemoved")) { + // b/350144057 + Slog.d(TAG, "onPackageRemoved: Skipping - profile not enabled" + + " or not accessible for user=" + user + + ", packageName=" + packageName); continue; } if (!isCallingAppIdAllowed(appIdAllowList, UserHandle.getAppId( cookie.callingUid))) { + // b/350144057 + Slog.d(TAG, "onPackageRemoved: Skipping - appId not allowed" + + " for user=" + user + + ", packageName=" + packageName); continue; } try { + // b/350144057 + Slog.d(TAG, "onPackageRemoved: triggering onPackageRemoved" + + " for user=" + user + + ", packageName=" + packageName); listener.onPackageRemoved(user, packageName); } catch (RemoteException re) { - Slog.d(TAG, "Callback failed ", re); + Slog.d(TAG, "onPackageRemoved: Callback failed ", re); } } } finally { @@ -2524,15 +2492,27 @@ public class LauncherAppsService extends SystemService { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); if (!isEnabledProfileOf(cookie, user, "onPackageAdded")) { + // b/350144057 + Slog.d(TAG, "onPackageAdded: Skipping - profile not enabled" + + " or not accessible for user=" + user + + ", packageName=" + packageName); continue; } if (!isPackageVisibleToListener(packageName, cookie, user)) { + // b/350144057 + Slog.d(TAG, "onPackageAdded: Skipping - package filtered" + + " for user=" + user + + ", packageName=" + packageName); continue; } try { + // b/350144057 + Slog.d(TAG, "onPackageAdded: triggering onPackageAdded" + + " for user=" + user + + ", packageName=" + packageName); listener.onPackageAdded(user, packageName); } catch (RemoteException re) { - Slog.d(TAG, "Callback failed ", re); + Slog.d(TAG, "onPackageAdded: Callback failed ", re); } } } finally { @@ -2566,7 +2546,7 @@ public class LauncherAppsService extends SystemService { try { listener.onPackageChanged(user, packageName); } catch (RemoteException re) { - Slog.d(TAG, "Callback failed ", re); + Slog.d(TAG, "onPackageChanged: Callback failed ", re); } } } finally { diff --git a/services/core/java/com/android/server/pm/ShortcutLauncher.java b/services/core/java/com/android/server/pm/ShortcutLauncher.java index d65e30be9edb..045d4db0a1f1 100644 --- a/services/core/java/com/android/server/pm/ShortcutLauncher.java +++ b/services/core/java/com/android/server/pm/ShortcutLauncher.java @@ -42,7 +42,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; /** * Launcher information used by {@link ShortcutService}. @@ -129,15 +128,9 @@ class ShortcutLauncher extends ShortcutPackageItem { */ public void pinShortcuts(@UserIdInt int packageUserId, @NonNull String packageName, @NonNull List<String> ids, boolean forPinRequest) { - if (ShortcutService.DEBUG) { - Slog.v(TAG, "ShortcutLauncher#pinShortcuts: pin shortcuts from " + packageName - + " with userId=" + packageUserId + " shortcutIds=" - + ids.stream().collect(Collectors.joining(", ", "[", "]"))); - } final ShortcutPackage packageShortcuts = mShortcutUser.getPackageShortcutsIfExists(packageName); if (packageShortcuts == null) { - Slog.w(TAG, "ShortcutLauncher#pinShortcuts packageShortcuts is null"); return; // No need to instantiate. } @@ -162,10 +155,6 @@ class ShortcutLauncher extends ShortcutPackageItem { final String id = ids.get(i); final ShortcutInfo si = packageShortcuts.findShortcutById(id); if (si == null) { - if (ShortcutService.DEBUG) { - Slog.w(TAG, "ShortcutLauncher#pinShortcuts: cannot pin " - + id + " because it does not exist"); - } continue; } if (si.isDynamic() || si.isLongLived() @@ -185,13 +174,6 @@ class ShortcutLauncher extends ShortcutPackageItem { } } } - if (ShortcutService.DEBUG) { - Slog.v(TAG, "ShortcutLauncher#pinShortcuts: " - + " newSet: " + newSet.stream().collect( - Collectors.joining(", ", "[", "]")) - + " floatingSet: " + floatingSet.stream().collect( - Collectors.joining(", ", "[", "]"))); - } mPinnedShortcuts.put(up, newSet); } } diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index c9ad4988f8ca..60056eb471d1 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -729,11 +729,6 @@ class ShortcutPackage extends ShortcutPackageItem { } pinnedShortcuts.addAll(pinned); }); - if (ShortcutService.DEBUG) { - Slog.v(TAG, "ShortcutPackage#refreshPinnedFlags: " - + " pinnedShortcuts: " + pinnedShortcuts.stream().collect( - Collectors.joining(", ", "[", "]"))); - } // Secondly, update the pinned state if necessary. final List<ShortcutInfo> pinned = findAll(pinnedShortcuts); if (pinned != null) { diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index ea495c9bee9c..a3ff1952205f 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -169,7 +169,7 @@ import java.util.stream.Collectors; public class ShortcutService extends IShortcutService.Stub { static final String TAG = "ShortcutService"; - static final boolean DEBUG = Build.IS_DEBUGGABLE; // STOPSHIP if true + static final boolean DEBUG = false; // STOPSHIP if true static final boolean DEBUG_LOAD = false; // STOPSHIP if true static final boolean DEBUG_PROCSTATE = false; // STOPSHIP if true static final boolean DEBUG_REBOOT = Build.IS_DEBUGGABLE; @@ -3206,11 +3206,6 @@ public class ShortcutService extends IShortcutService.Stub { public void pinShortcuts(int launcherUserId, @NonNull String callingPackage, @NonNull String packageName, @NonNull List<String> shortcutIds, int userId) { - if (DEBUG) { - Slog.v(TAG, "pinShortcuts: " + callingPackage + ", with userId=" + launcherUserId - + ", is trying to pin shortcuts from " + packageName - + " with userId=" + userId); - } // Calling permission must be checked by LauncherAppsImpl. Preconditions.checkStringNotEmpty(packageName, "packageName"); Objects.requireNonNull(shortcutIds, "shortcutIds"); @@ -3235,11 +3230,6 @@ public class ShortcutService extends IShortcutService.Stub { && !si.isDeclaredInManifest(), ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO, callingPackage, launcherUserId, false); - } else { - if (DEBUG) { - Slog.w(TAG, "specified package " + packageName + ", with userId=" + userId - + ", doesn't exist."); - } } // Get list of shortcuts that will get unpinned. ArraySet<String> oldPinnedIds = launcher.getPinnedShortcutIds(packageName, userId); @@ -5458,17 +5448,6 @@ public class ShortcutService extends IShortcutService.Stub { */ private List<ShortcutInfo> prepareChangedShortcuts(ArraySet<String> changedIds, ArraySet<String> newIds, List<ShortcutInfo> deletedList, final ShortcutPackage ps) { - if (DEBUG) { - Slog.v(TAG, "prepareChangedShortcuts: " - + " changedIds=" + (changedIds == null - ? "n/a" : changedIds.stream().collect(Collectors.joining(", ", "[", "]"))) - + " newIds=" + (newIds == null - ? "n/a" : newIds.stream().collect(Collectors.joining(", ", "[", "]"))) - + " deletedList=" + (deletedList == null - ? "n/a" : deletedList.stream().map(ShortcutInfo::getId).collect( - Collectors.joining(", ", "[", "]"))) - + " ps=" + (ps == null ? "n/a" : ps.getPackageName())); - } if (ps == null) { // This can happen when package restore is not finished yet. return null; diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index a683a8c54849..89417f3765ff 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1090,6 +1090,21 @@ public class UserManagerService extends IUserManager.Stub { mUser0Allocations = DBG_ALLOCATION ? new AtomicInteger() : null; mPrivateSpaceAutoLockSettingsObserver = new SettingsObserver(mHandler); emulateSystemUserModeIfNeeded(); + initPropertyInvalidatedCaches(); + } + + /** + * This method is used to invalidate the caches at server statup, + * so that caches can start working. + */ + private static final void initPropertyInvalidatedCaches() { + if (android.multiuser.Flags.cachesNotInvalidatedAtStartReadOnly()) { + UserManager.invalidateIsUserUnlockedCache(); + UserManager.invalidateQuietModeEnabledCache(); + UserManager.invalidateStaticUserProperties(); + UserManager.invalidateUserPropertiesCache(); + UserManager.invalidateUserSerialNumberCache(); + } } private boolean doesDeviceHardwareSupportPrivateSpace() { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 98091b1e617f..02c02b04c5de 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -3350,12 +3350,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - // TODO(b/358569822) Remove below once we have nicer API for listening to shortcuts - if ((event.isMetaPressed() || KeyEvent.isMetaKey(keyCode)) - && shouldInterceptShortcuts(focusedToken)) { - return keyNotConsumed; - } - Set<Integer> consumedKeys = mConsumedKeysForDevice.get(deviceId); if (consumedKeys == null) { consumedKeys = new HashSet<>(); @@ -3855,10 +3849,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS: case KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SEARCH: case KeyGestureEvent.KEY_GESTURE_TYPE_LANGUAGE_SWITCH: - case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP: - case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN: - case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE: - case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK: return true; default: return false; @@ -4016,25 +4006,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { sendSwitchKeyboardLayout(displayId, focusedToken, direction); } return true; - // TODO (b/358569822): Move these input specific gesture handling to IMS since we - // are calling into InputManager through internal API anyways - case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP: - if (complete) { - mInputManagerInternal.incrementKeyboardBacklight(deviceId); - } - return true; - case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN: - if (complete) { - mInputManagerInternal.decrementKeyboardBacklight(deviceId); - } - return true; - case KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE: - return true; - case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK: - if (complete) { - mInputManagerInternal.toggleCapsLock(deviceId); - } - return true; } return false; } @@ -4064,15 +4035,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); } - private boolean shouldInterceptShortcuts(IBinder focusedToken) { - KeyInterceptionInfo info = - mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken); - boolean hasInterceptWindowFlag = (info.layoutParamsPrivateFlags - & WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS) != 0; - return hasInterceptWindowFlag && mButtonOverridePermissionChecker.canAppOverrideSystemKey( - mContext, info.windowOwnerUid); - } - /** * In this function, we check whether a system key should be sent to the application. We also * detect the key gesture on this key, even if the key will be sent to the app. The gesture diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java index 68026ea9094a..e3d71e4998be 100644 --- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java +++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java @@ -24,8 +24,11 @@ import android.annotation.AnyThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.WorkerThread; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -78,6 +81,8 @@ import java.util.function.Consumer; public final class RollbackPackageHealthObserver implements PackageHealthObserver { private static final String TAG = "RollbackPackageHealthObserver"; private static final String NAME = "rollback-observer"; + private static final String ACTION_NAME = RollbackPackageHealthObserver.class.getName(); + private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_PERSISTENT | ApplicationInfo.FLAG_SYSTEM; @@ -596,12 +601,40 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve } }; - final LocalIntentReceiver rollbackReceiver = new LocalIntentReceiver(result -> { - mHandler.post(() -> onResult.accept(result)); - }); + if (Flags.refactorCrashrecovery()) { + // Define a BroadcastReceiver to handle the result + BroadcastReceiver rollbackReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent result) { + mHandler.post(() -> onResult.accept(result)); + } + }; + + // Register the BroadcastReceiver + mContext.registerReceiver(rollbackReceiver, + new IntentFilter(ACTION_NAME), + Context.RECEIVER_NOT_EXPORTED); + + Intent intentReceiver = new Intent(ACTION_NAME); + intentReceiver.putExtra("rollbackId", rollback.getRollbackId()); + intentReceiver.setPackage(mContext.getPackageName()); - rollbackManager.commitRollback(rollback.getRollbackId(), - Collections.singletonList(failedPackage), rollbackReceiver.getIntentSender()); + PendingIntent rollbackPendingIntent = PendingIntent.getBroadcast(mContext, + rollback.getRollbackId(), + intentReceiver, + PendingIntent.FLAG_MUTABLE); + + rollbackManager.commitRollback(rollback.getRollbackId(), + Collections.singletonList(failedPackage), + rollbackPendingIntent.getIntentSender()); + } else { + final LocalIntentReceiver rollbackReceiver = new LocalIntentReceiver(result -> { + mHandler.post(() -> onResult.accept(result)); + }); + + rollbackManager.commitRollback(rollback.getRollbackId(), + Collections.singletonList(failedPackage), rollbackReceiver.getIntentSender()); + } } /** diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 953aae9588dd..457196b74d2e 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -89,6 +89,7 @@ import com.android.internal.widget.LockSettingsInternal; import com.android.internal.widget.LockSettingsStateListener; import com.android.server.LocalServices; import com.android.server.SystemService; +import com.android.server.pm.UserManagerInternal; import com.android.server.servicewatcher.CurrentUserServiceSupplier; import com.android.server.servicewatcher.ServiceWatcher; import com.android.server.utils.Slogf; @@ -170,6 +171,7 @@ public class TrustManagerService extends SystemService { private final ActivityManager mActivityManager; private FingerprintManager mFingerprintManager; private FaceManager mFaceManager; + private UserManagerInternal mUserManagerInternal; private enum TrustState { // UNTRUSTED means that TrustManagerService is currently *not* giving permission for the @@ -1064,6 +1066,8 @@ public class TrustManagerService extends SystemService { Log.w(TAG, "Unable to check keyguard lock state", e); } currentUserIsUnlocked = unlockedUser == id; + } else if (isVisibleBackgroundUser(id)) { + showingKeyguard = !mUserManager.isUserUnlocked(id); } final boolean deviceLocked = secure && showingKeyguard && !trusted && !biometricAuthenticated; @@ -1095,6 +1099,16 @@ public class TrustManagerService extends SystemService { } } + private boolean isVisibleBackgroundUser(int userId) { + if (!mUserManager.isVisibleBackgroundUsersSupported()) { + return false; + } + if (mUserManagerInternal == null) { + mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); + } + return mUserManagerInternal.isVisibleBackgroundFullUser(userId); + } + private void notifyTrustAgentsOfDeviceLockState(int userId, boolean isLocked) { for (int i = 0; i < mActiveAgents.size(); i++) { AgentInfo agent = mActiveAgents.valueAt(i); diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java index 96a25dac21e3..1e82b8999834 100644 --- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java +++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java @@ -322,9 +322,16 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { if (SubscriptionManager.isValidSubscriptionId(subId)) { // Get only configs as needed to save memory. - final PersistableBundle carrierConfig = - CarrierConfigManager.getCarrierConfigSubset(mContext, subId, - VcnManager.VCN_RELATED_CARRIER_CONFIG_KEYS); + PersistableBundle carrierConfig = new PersistableBundle(); + try { + carrierConfig = + mCarrierConfigManager.getConfigForSubId( + subId, VcnManager.VCN_RELATED_CARRIER_CONFIG_KEYS); + + } catch (RuntimeException exception) { + Slog.w(TAG, "CarrierConfigLoader is not available."); + } + if (mDeps.isConfigForIdentifiedCarrier(carrierConfig)) { mReadySubIdsBySlotId.put(slotId, subId); diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index 8d378a021f17..b5747828349e 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -177,6 +177,10 @@ public class VcnGatewayConnection extends StateMachine { /** Default number of parallel SAs requested */ static final int TUNNEL_AGGREGATION_SA_COUNT_MAX_DEFAULT = 1; + // The returned string of + // TelephonyManager#getNetworkTypeName(TelephonyManager.NETWORK_TYPE_UNKNOWN) + private static final String NETWORK_TYPE_STRING_UNKNOWN = "UNKNOWN"; + // Matches DataConnection.NETWORK_TYPE private constant, and magic string from // ConnectivityManager#getNetworkTypeName() @VisibleForTesting(visibility = Visibility.PRIVATE) @@ -1815,9 +1819,7 @@ public class VcnGatewayConnection extends StateMachine { .setLegacyType(ConnectivityManager.TYPE_MOBILE) .setLegacyTypeName(NETWORK_INFO_NETWORK_TYPE_STRING) .setLegacySubType(TelephonyManager.NETWORK_TYPE_UNKNOWN) - .setLegacySubTypeName( - TelephonyManager.getNetworkTypeName( - TelephonyManager.NETWORK_TYPE_UNKNOWN)) + .setLegacySubTypeName(NETWORK_TYPE_STRING_UNKNOWN) .setLegacyExtraInfo(NETWORK_INFO_EXTRA_INFO) .build(); diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java index 3f8d39e72e89..2b0ca0802359 100644 --- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java +++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java @@ -360,7 +360,10 @@ public class UnderlyingNetworkController { final NetworkRequest.Builder nrBuilder = getBaseNetworkRequestBuilder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .setNetworkSpecifier(new TelephonyNetworkSpecifier(subId)); + .setNetworkSpecifier( + new TelephonyNetworkSpecifier.Builder() + .setSubscriptionId(subId) + .build()); for (CapabilityMatchCriteria capMatchCriteria : capsMatchCriteria) { final int cap = capMatchCriteria.capability; diff --git a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java index cae6b34d4c73..006a5bb1d1d0 100644 --- a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java +++ b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java @@ -16,6 +16,8 @@ package com.android.server.vibrator; +import static android.os.vibrator.Flags.hapticFeedbackInputSourceCustomizationEnabled; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.Resources; @@ -121,7 +123,6 @@ public final class HapticFeedbackVibrationProvider { return getVibrationForHapticFeedback(effectId); } - // TODO(b/354049335): handle input source customized VibrationAttributes. /** * Provides the {@link VibrationAttributes} that should be used for a haptic feedback. * @@ -131,7 +132,7 @@ public final class HapticFeedbackVibrationProvider { * @param privFlags Additional private flags as per {@link HapticFeedbackConstants}. * @return the {@link VibrationAttributes} that should be used for the provided haptic feedback. */ - public VibrationAttributes getVibrationAttributesForHapticFeedback(int effectId, + public VibrationAttributes getVibrationAttributes(int effectId, @HapticFeedbackConstants.Flags int flags, @HapticFeedbackConstants.PrivateFlags int privFlags) { VibrationAttributes attrs; @@ -142,10 +143,13 @@ public final class HapticFeedbackVibrationProvider { break; case HapticFeedbackConstants.ASSISTANT_BUTTON: case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON: + attrs = HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES; + break; case HapticFeedbackConstants.SCROLL_TICK: case HapticFeedbackConstants.SCROLL_ITEM_FOCUS: case HapticFeedbackConstants.SCROLL_LIMIT: - attrs = HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES; + attrs = hapticFeedbackInputSourceCustomizationEnabled() ? TOUCH_VIBRATION_ATTRIBUTES + : HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES; break; case HapticFeedbackConstants.KEYBOARD_TAP: case HapticFeedbackConstants.KEYBOARD_RELEASE: @@ -158,19 +162,32 @@ public final class HapticFeedbackVibrationProvider { default: attrs = TOUCH_VIBRATION_ATTRIBUTES; } + return getVibrationAttributesWithFlags(attrs, effectId, flags); + } - int vibFlags = 0; - boolean bypassVibrationIntensitySetting = - (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0; - if (bypassVibrationIntensitySetting) { - vibFlags |= VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF; - } - if (shouldBypassInterruptionPolicy(effectId)) { - vibFlags |= VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY; + /** + * Similar to {@link #getVibrationAttributes(int, int, int)} but also handles + * input source customization. + * + * @param inputSource the {@link InputDevice.Source} that customizes the + * {@link VibrationAttributes}. + */ + public VibrationAttributes getVibrationAttributes(int effectId, + int inputSource, + @HapticFeedbackConstants.Flags int flags, + @HapticFeedbackConstants.PrivateFlags int privFlags) { + if (hapticFeedbackInputSourceCustomizationEnabled() + && inputSource == InputDevice.SOURCE_ROTARY_ENCODER) { + switch (effectId) { + case HapticFeedbackConstants.SCROLL_TICK, + HapticFeedbackConstants.SCROLL_ITEM_FOCUS, + HapticFeedbackConstants.SCROLL_LIMIT -> { + return getVibrationAttributesWithFlags(HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES, + effectId, flags); + } + } } - - return vibFlags == 0 ? attrs : new VibrationAttributes.Builder(attrs) - .setFlags(vibFlags).build(); + return getVibrationAttributes(effectId, flags, privFlags); } /** @@ -344,6 +361,20 @@ public final class HapticFeedbackVibrationProvider { return IME_FEEDBACK_VIBRATION_ATTRIBUTES; } + private VibrationAttributes getVibrationAttributesWithFlags(VibrationAttributes attrs, + int effectId, int flags) { + int vibFlags = 0; + if ((flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0) { + vibFlags |= VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF; + } + if (shouldBypassInterruptionPolicy(effectId)) { + vibFlags |= VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY; + } + + return vibFlags == 0 ? attrs : new VibrationAttributes.Builder(attrs) + .setFlags(vibFlags).build(); + } + private static boolean shouldBypassInterruptionPolicy(int effectId) { switch (effectId) { case HapticFeedbackConstants.SCROLL_TICK: diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index 899f0b121a8d..a76d8d6bded0 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -509,7 +509,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } return performHapticFeedbackWithEffect(uid, deviceId, opPkg, constant, reason, token, hapticVibrationProvider.getVibration(constant), - hapticVibrationProvider.getVibrationAttributesForHapticFeedback( + hapticVibrationProvider.getVibrationAttributes( constant, flags, privFlags)); } @@ -534,8 +534,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } return performHapticFeedbackWithEffect(uid, deviceId, opPkg, constant, reason, token, hapticVibrationProvider.getVibration(constant, inputSource), - hapticVibrationProvider.getVibrationAttributesForHapticFeedback( - constant, flags, privFlags)); + hapticVibrationProvider.getVibrationAttributes(constant, inputSource, flags, + privFlags)); } private HalVibration performHapticFeedbackWithEffect(int uid, int deviceId, String opPkg, diff --git a/services/core/java/com/android/server/wallpaper/WallpaperData.java b/services/core/java/com/android/server/wallpaper/WallpaperData.java index a698429ff09e..15f86e9c08ff 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperData.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperData.java @@ -78,7 +78,7 @@ class WallpaperData { /** * The component name of the currently set live wallpaper. */ - ComponentName wallpaperComponent; + private ComponentName mWallpaperComponent; // TODO(b/347235611) Remove this field /** @@ -195,7 +195,7 @@ class WallpaperData { */ WallpaperData(WallpaperData source) { this.userId = source.userId; - this.wallpaperComponent = source.wallpaperComponent; + this.mWallpaperComponent = source.mWallpaperComponent; this.mWhich = source.mWhich; this.wallpaperId = source.wallpaperId; this.cropHint.set(source.cropHint); @@ -230,6 +230,14 @@ class WallpaperData { return result; } + ComponentName getComponent() { + return mWallpaperComponent; + } + + void setComponent(ComponentName componentName) { + this.mWallpaperComponent = componentName; + } + @Override public String toString() { StringBuilder out = new StringBuilder(defaultString(this)); diff --git a/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java b/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java index b15facb2945c..e3e83b3e1fd7 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java @@ -189,13 +189,13 @@ public class WallpaperDataParser { String comp = parser.getAttributeValue(null, "component"); if (removeNextWallpaperComponent()) { - wallpaperToParse.wallpaperComponent = comp != null + wallpaperToParse.setComponent(comp != null ? ComponentName.unflattenFromString(comp) - : null; - if (wallpaperToParse.wallpaperComponent == null - || "android".equals(wallpaperToParse.wallpaperComponent + : null); + if (wallpaperToParse.getComponent() == null + || "android".equals(wallpaperToParse.getComponent() .getPackageName())) { - wallpaperToParse.wallpaperComponent = mImageWallpaper; + wallpaperToParse.setComponent(mImageWallpaper); } } else { wallpaperToParse.nextWallpaperComponent = comp != null @@ -219,7 +219,7 @@ public class WallpaperDataParser { Slog.v(TAG, "primaryColors:" + wallpaper.primaryColors); Slog.v(TAG, "mName:" + wallpaper.name); if (removeNextWallpaperComponent()) { - Slog.v(TAG, "mWallpaperComponent:" + wallpaper.wallpaperComponent); + Slog.v(TAG, "mWallpaperComponent:" + wallpaper.getComponent()); } else { Slog.v(TAG, "mNextWallpaperComponent:" + wallpaper.nextWallpaperComponent); @@ -340,7 +340,7 @@ public class WallpaperDataParser { getAttributeInt(parser, "totalCropTop", 0), getAttributeInt(parser, "totalCropRight", 0), getAttributeInt(parser, "totalCropBottom", 0)); - ComponentName componentName = removeNextWallpaperComponent() ? wallpaper.wallpaperComponent + ComponentName componentName = removeNextWallpaperComponent() ? wallpaper.getComponent() : wallpaper.nextWallpaperComponent; if (multiCrop() && mImageWallpaper.equals(componentName)) { wallpaper.mCropHints = new SparseArray<>(); @@ -480,7 +480,7 @@ public class WallpaperDataParser { out.startTag(null, tag); out.attributeInt(null, "id", wallpaper.wallpaperId); - if (multiCrop() && mImageWallpaper.equals(wallpaper.wallpaperComponent)) { + if (multiCrop() && mImageWallpaper.equals(wallpaper.getComponent())) { if (wallpaper.mCropHints == null) { Slog.e(TAG, "cropHints should not be null when saved"); wallpaper.mCropHints = new SparseArray<>(); @@ -580,10 +580,10 @@ public class WallpaperDataParser { } out.attribute(null, "name", wallpaper.name); - if (wallpaper.wallpaperComponent != null - && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) { + if (wallpaper.getComponent() != null + && !wallpaper.getComponent().equals(mImageWallpaper)) { out.attribute(null, "component", - wallpaper.wallpaperComponent.flattenToShortString()); + wallpaper.getComponent().flattenToShortString()); } if (wallpaper.allowBackup) { diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 6cc37ddda9bc..4754ffb5cf6e 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -276,7 +276,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub final boolean isMigration = moved && lockWallpaperChanged; final boolean isRestore = moved && !isMigration; final boolean isAppliedToLock = (wallpaper.mWhich & FLAG_LOCK) != 0; - final boolean needsUpdate = wallpaper.wallpaperComponent == null + final boolean needsUpdate = wallpaper.getComponent() == null || event != CLOSE_WRITE // includes the MOVED_TO case || wallpaper.imageWallpaperPending; @@ -527,7 +527,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub * @return true unless the wallpaper changed during the color computation */ private boolean extractColors(WallpaperData wallpaper) { - if (offloadColorExtraction()) return !mImageWallpaper.equals(wallpaper.wallpaperComponent); + if (offloadColorExtraction()) return !mImageWallpaper.equals(wallpaper.getComponent()); String cropFile = null; boolean defaultImageWallpaper = false; int wallpaperId; @@ -550,8 +550,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub synchronized (mLock) { // Not having a wallpaperComponent means it's a lock screen wallpaper. - final boolean imageWallpaper = mImageWallpaper.equals(wallpaper.wallpaperComponent) - || wallpaper.wallpaperComponent == null; + final boolean imageWallpaper = mImageWallpaper.equals(wallpaper.getComponent()) + || wallpaper.getComponent() == null; if (imageWallpaper && wallpaper.getCropFile().exists()) { cropFile = wallpaper.getCropFile().getAbsolutePath(); } else if (imageWallpaper && !wallpaper.cropExists() && !wallpaper.sourceExists()) { @@ -824,13 +824,13 @@ public class WallpaperManagerService extends IWallpaperManager.Stub return; } TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG); - t.traceBegin("WPMS.connectLocked-" + wallpaper.wallpaperComponent); + t.traceBegin("WPMS.connectLocked-" + wallpaper.getComponent()); if (DEBUG) Slog.v(TAG, "Adding window token: " + mToken); mWindowManagerInternal.addWindowToken(mToken, TYPE_WALLPAPER, mDisplayId, null /* options */); mWindowManagerInternal.setWallpaperShowWhenLocked( mToken, (wallpaper.mWhich & FLAG_LOCK) != 0); - if (multiCrop() && mImageWallpaper.equals(wallpaper.wallpaperComponent)) { + if (multiCrop() && mImageWallpaper.equals(wallpaper.getComponent())) { mWindowManagerInternal.setWallpaperCropHints(mToken, mWallpaperCropper.getRelativeCropHints(wallpaper)); } else { @@ -906,7 +906,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } if (!mWallpaper.wallpaperUpdating && mWallpaper.userId == mCurrentUserId) { - Slog.w(TAG, "Wallpaper reconnect timed out for " + mWallpaper.wallpaperComponent + Slog.w(TAG, "Wallpaper reconnect timed out for " + mWallpaper.getComponent() + ", reverting to built-in wallpaper!"); clearWallpaperLocked(mWallpaper.mWhich, mWallpaper.userId, false, null); } @@ -1035,9 +1035,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub public void onServiceDisconnected(ComponentName name) { synchronized (mLock) { Slog.w(TAG, "Wallpaper service gone: " + name); - if (!Objects.equals(name, mWallpaper.wallpaperComponent)) { + if (!Objects.equals(name, mWallpaper.getComponent())) { Slog.e(TAG, "Does not match expected wallpaper component " - + mWallpaper.wallpaperComponent); + + mWallpaper.getComponent()); } mService = null; forEachDisplayConnector(connector -> connector.mEngine = null); @@ -1065,7 +1065,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub fgHandler.postDelayed(mResetRunnable, WALLPAPER_RECONNECT_TIMEOUT_MS); if (DEBUG_LIVE) { Slog.i(TAG, - "Started wallpaper reconnect timeout for " + mWallpaper.wallpaperComponent); + "Started wallpaper reconnect timeout for " + mWallpaper.getComponent()); } } @@ -1081,7 +1081,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub return; } - final ComponentName wpService = mWallpaper.wallpaperComponent; + final ComponentName wpService = mWallpaper.getComponent(); // The broadcast of package update could be delayed after service disconnected. Try // to re-bind the service for 10 seconds. mWallpaper.mBindSource = BindSource.CONNECTION_TRY_TO_REBIND; @@ -1110,7 +1110,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub // The wallpaper disappeared. If this isn't a system-default one, track // crashes and fall back to default if it continues to misbehave. if (this == mWallpaper.connection) { - final ComponentName wpService = mWallpaper.wallpaperComponent; + final ComponentName wpService = mWallpaper.getComponent(); if (!mWallpaper.wallpaperUpdating && mWallpaper.userId == mCurrentUserId && !Objects.equals(mDefaultWallpaperComponent, wpService) @@ -1188,7 +1188,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub synchronized (mLock) { // Do not broadcast changes on ImageWallpaper since it's handled // internally by this class. - boolean isImageWallpaper = mImageWallpaper.equals(mWallpaper.wallpaperComponent); + boolean isImageWallpaper = mImageWallpaper.equals(mWallpaper.getComponent()); if (isImageWallpaper && (!offloadColorExtraction() || primaryColors == null)) { return; } @@ -1303,7 +1303,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub if (mNewWallpaper.mWhich == FLAG_SYSTEM) { // New wp is system only, so old system+lock is now lock only final boolean originalIsStatic = mImageWallpaper.equals( - mOriginalSystem.wallpaperComponent); + mOriginalSystem.getComponent()); if (originalIsStatic) { // Static wp: image file rename has already been tried via // migrateStaticSystemToLockWallpaperLocked() and added to the lock wp map @@ -1314,8 +1314,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub if (DEBUG) { Slog.v(TAG, "static system+lock to system success"); } - lockWp.wallpaperComponent = - mOriginalSystem.wallpaperComponent; + lockWp.setComponent(mOriginalSystem.getComponent()); lockWp.connection = mOriginalSystem.connection; lockWp.connection.mWallpaper = lockWp; mOriginalSystem.mWhich = FLAG_LOCK; @@ -1376,7 +1375,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub return; } for (WallpaperData wallpaper: getWallpapers()) { - final ComponentName wpService = wallpaper.wallpaperComponent; + final ComponentName wpService = wallpaper.getComponent(); if (wpService != null && wpService.getPackageName().equals(packageName)) { if (DEBUG_LIVE) { Slog.i(TAG, "Wallpaper " + wpService + " update has finished"); @@ -1402,8 +1401,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub return; } for (WallpaperData wallpaper: getWallpapers()) { - if (wallpaper.wallpaperComponent != null - && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) { + if (wallpaper.getComponent() != null + && wallpaper.getComponent().getPackageName().equals(packageName)) { doPackagesChangedLocked(true, wallpaper); } } @@ -1417,10 +1416,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub return; } for (WallpaperData wallpaper: getWallpapers()) { - if (wallpaper.wallpaperComponent != null - && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) { + if (wallpaper.getComponent() != null + && wallpaper.getComponent().getPackageName().equals(packageName)) { if (DEBUG_LIVE) { - Slog.i(TAG, "Wallpaper service " + wallpaper.wallpaperComponent + Slog.i(TAG, "Wallpaper service " + wallpaper.getComponent() + " is updating"); } wallpaper.wallpaperUpdating = true; @@ -1462,15 +1461,15 @@ public class WallpaperManagerService extends IWallpaperManager.Stub boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) { boolean changed = false; - if (wallpaper.wallpaperComponent != null) { - int change = isPackageDisappearing(wallpaper.wallpaperComponent + if (wallpaper.getComponent() != null) { + int change = isPackageDisappearing(wallpaper.getComponent() .getPackageName()); if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) { changed = true; if (doit) { Slog.w(TAG, "Wallpaper uninstalled, removing: " - + wallpaper.wallpaperComponent); + + wallpaper.getComponent()); clearWallpaperLocked(wallpaper.mWhich, wallpaper.userId, false, null); } } @@ -1485,15 +1484,15 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } } - if (wallpaper.wallpaperComponent != null - && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) { + if (wallpaper.getComponent() != null + && isPackageModified(wallpaper.getComponent().getPackageName())) { try { - mContext.getPackageManager().getServiceInfo(wallpaper.wallpaperComponent, + mContext.getPackageManager().getServiceInfo(wallpaper.getComponent(), PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); } catch (NameNotFoundException e) { Slog.w(TAG, "Wallpaper component gone, removing: " - + wallpaper.wallpaperComponent); + + wallpaper.getComponent()); clearWallpaperLocked(wallpaper.mWhich, wallpaper.userId, false, null); } } @@ -1636,8 +1635,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub // sure we have something to render boolean isImageComponent; if (removeNextWallpaperComponent()) { - isImageComponent = wallpaper.wallpaperComponent == null - || mImageWallpaper.equals(wallpaper.wallpaperComponent); + isImageComponent = wallpaper.getComponent() == null + || mImageWallpaper.equals(wallpaper.getComponent()); } else { isImageComponent = mImageWallpaper.equals(wallpaper.nextWallpaperComponent); } @@ -1892,10 +1891,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub final ComponentName cname; if (removeNextWallpaperComponent()) { - cname = wallpaper.wallpaperComponent; + cname = wallpaper.getComponent(); } else { - cname = (wallpaper.wallpaperComponent != null) - ? wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent; + cname = (wallpaper.getComponent() != null) + ? wallpaper.getComponent() : wallpaper.nextWallpaperComponent; } if (!bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) { // We failed to bind the desired wallpaper, but that might @@ -1927,7 +1926,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub // We might end up persisting the current wallpaper data // while locked, so pretend like the component was actually // bound into place - wallpaper.wallpaperComponent = wallpaper.nextWallpaperComponent; + wallpaper.setComponent(wallpaper.nextWallpaperComponent); } final WallpaperData fallback = new WallpaperData(wallpaper.userId, wallpaper.mWhich); @@ -2004,7 +2003,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub // lock only case: set the system wallpaper component to both screens if (which == FLAG_LOCK) { - component = wallpaper.wallpaperComponent; + component = wallpaper.getComponent(); finalWhich = FLAG_LOCK | FLAG_SYSTEM; } else { component = null; @@ -2310,7 +2309,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub checkPermission(READ_WALLPAPER_INTERNAL); WallpaperData wallpaper = (which == FLAG_LOCK) ? mLockWallpaperMap.get(userId) : mWallpaperMap.get(userId); - if (wallpaper == null || !mImageWallpaper.equals(wallpaper.wallpaperComponent)) { + if (wallpaper == null || !mImageWallpaper.equals(wallpaper.getComponent())) { return null; } SparseArray<Rect> relativeSuggestedCrops = @@ -2760,7 +2759,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub WallpaperData wallpaperData = (which == FLAG_LOCK ? mLockWallpaperMap : mWallpaperMap) .get(mCurrentUserId); if (wallpaperData == null) return false; - return mImageWallpaper.equals(wallpaperData.wallpaperComponent); + return mImageWallpaper.equals(wallpaperData.getComponent()); } } @@ -2996,7 +2995,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub final WallpaperData originalSystemWallpaper = mWallpaperMap.get(userId); final boolean systemIsStatic = originalSystemWallpaper != null && mImageWallpaper.equals( - originalSystemWallpaper.wallpaperComponent); + originalSystemWallpaper.getComponent()); final boolean systemIsBoth = mLockWallpaperMap.get(userId) == null; /* If we're setting system but not lock, and lock is currently sharing the system @@ -3190,7 +3189,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub throw new IllegalStateException("Wallpaper not yet initialized for user " + userId); } final boolean systemIsStatic = mImageWallpaper.equals( - originalSystemWallpaper.wallpaperComponent); + originalSystemWallpaper.getComponent()); final boolean systemIsBoth = mLockWallpaperMap.get(userId) == null; if (which == FLAG_SYSTEM && systemIsBoth && systemIsStatic) { @@ -3212,7 +3211,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub liveSync = new WallpaperDestinationChangeHandler( newWallpaper); boolean same = changingToSame(name, newWallpaper.connection, - newWallpaper.wallpaperComponent); + newWallpaper.getComponent()); /* * If we have a shared system+lock wallpaper, and we reapply the same wallpaper @@ -3243,7 +3242,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } boolean lockBitmapCleared = false; - if (!mImageWallpaper.equals(newWallpaper.wallpaperComponent)) { + if (!mImageWallpaper.equals(newWallpaper.getComponent())) { clearWallpaperBitmaps(newWallpaper); lockBitmapCleared = newWallpaper.mWhich == FLAG_LOCK; } @@ -3324,7 +3323,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } // Has the component changed? if (!force && changingToSame(componentName, wallpaper.connection, - wallpaper.wallpaperComponent)) { + wallpaper.getComponent())) { try { if (DEBUG_LIVE) { Slog.v(TAG, "Changing to the same component, ignoring"); @@ -3461,7 +3460,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub return false; } maybeDetachLastWallpapers(wallpaper); - wallpaper.wallpaperComponent = componentName; + wallpaper.setComponent(componentName); wallpaper.connection = newConn; newConn.mReply = reply; updateCurrentWallpapers(wallpaper); @@ -3586,7 +3585,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } private void clearWallpaperComponentLocked(WallpaperData wallpaper) { - wallpaper.wallpaperComponent = null; + wallpaper.setComponent(null); detachWallpaperLocked(wallpaper); } @@ -3831,7 +3830,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub wallpaper.wallpaperId = makeWallpaperIdLocked(); // always bump id at restore wallpaper.allowBackup = true; // by definition if it was restored ComponentName componentName = - removeNextWallpaperComponent() ? wallpaper.wallpaperComponent + removeNextWallpaperComponent() ? wallpaper.getComponent() : wallpaper.nextWallpaperComponent; if (componentName != null && !componentName.equals(mImageWallpaper)) { wallpaper.mBindSource = BindSource.RESTORE_SETTINGS_LIVE_SUCCESS; @@ -3907,7 +3906,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub if (multiCrop()) pw.print(" mCropHints="); pw.println(wallpaper.mCropHints); pw.print(" mName="); pw.println(wallpaper.name); pw.print(" mAllowBackup="); pw.println(wallpaper.allowBackup); - pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent); + pw.print(" mWallpaperComponent="); pw.println(wallpaper.getComponent()); pw.print(" mWallpaperDimAmount="); pw.println(wallpaper.mWallpaperDimAmount); pw.print(" isColorExtracted="); pw.println(wallpaper.mIsColorExtractedFromDim); pw.println(" mUidToDimAmount:"); diff --git a/services/core/java/com/android/server/wm/AppCompatSizeCompatModePolicy.java b/services/core/java/com/android/server/wm/AppCompatSizeCompatModePolicy.java index 3be266e2951b..f069dcdbc86b 100644 --- a/services/core/java/com/android/server/wm/AppCompatSizeCompatModePolicy.java +++ b/services/core/java/com/android/server/wm/AppCompatSizeCompatModePolicy.java @@ -145,11 +145,13 @@ class AppCompatSizeCompatModePolicy { } } - void updateSizeCompatScale(@NonNull Rect resolvedAppBounds, @NonNull Rect containerAppBounds) { + void updateSizeCompatScale(@NonNull Rect resolvedAppBounds, @NonNull Rect containerAppBounds, + @NonNull Configuration newParentConfig) { mSizeCompatScale = mActivityRecord.mAppCompatController.getTransparentPolicy() .findOpaqueNotFinishingActivityBelow() .map(activityRecord -> mSizeCompatScale) - .orElseGet(() -> calculateSizeCompatScale(resolvedAppBounds, containerAppBounds)); + .orElseGet(() -> calculateSizeCompatScale( + resolvedAppBounds, containerAppBounds, newParentConfig)); } void clearSizeCompatModeAttributes() { @@ -290,7 +292,7 @@ class AppCompatSizeCompatModePolicy { // Calculates the scale the size compatibility bounds into the region which is available // to application. final float lastSizeCompatScale = mSizeCompatScale; - updateSizeCompatScale(resolvedAppBounds, containerAppBounds); + updateSizeCompatScale(resolvedAppBounds, containerAppBounds, newParentConfiguration); final int containerTopInset = containerAppBounds.top - containerBounds.top; final boolean topNotAligned = @@ -423,7 +425,7 @@ class AppCompatSizeCompatModePolicy { } private float calculateSizeCompatScale(@NonNull Rect resolvedAppBounds, - @NonNull Rect containerAppBounds) { + @NonNull Rect containerAppBounds, @NonNull Configuration newParentConfig) { final int contentW = resolvedAppBounds.width(); final int contentH = resolvedAppBounds.height(); final int viewportW = containerAppBounds.width(); @@ -432,7 +434,8 @@ class AppCompatSizeCompatModePolicy { // original container or if it's a freeform window in desktop mode. boolean shouldAllowUpscaling = !(contentW <= viewportW && contentH <= viewportH) || (canEnterDesktopMode(mActivityRecord.mAtmService.mContext) - && mActivityRecord.getWindowingMode() == WINDOWING_MODE_FREEFORM); + && newParentConfig.windowConfiguration.getWindowingMode() + == WINDOWING_MODE_FREEFORM); return shouldAllowUpscaling ? Math.min( (float) viewportW / contentW, (float) viewportH / contentH) : 1f; } diff --git a/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java b/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java index 19941741ed19..3a2cffbe1d85 100644 --- a/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java +++ b/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java @@ -422,6 +422,7 @@ class DeferredDisplayUpdater { || first.brightnessMaximum != second.brightnessMaximum || first.brightnessDefault != second.brightnessDefault || first.installOrientation != second.installOrientation + || first.isForceSdr != second.isForceSdr || !Objects.equals(first.layoutLimitedRefreshRate, second.layoutLimitedRefreshRate) || !BrightnessSynchronizer.floatEquals(first.hdrSdrRatio, second.hdrSdrRatio) || !first.thermalRefreshRateThrottling.contentEquals( diff --git a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java index cc6904f9b3af..156d8a065b67 100644 --- a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java +++ b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java @@ -103,7 +103,7 @@ public final class DesktopModeBoundsCalculator { final TaskDisplayArea displayArea = task.getDisplayArea(); final Rect screenBounds = displayArea.getBounds(); final Size idealSize = calculateIdealSize(screenBounds, DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - if (!DesktopModeFlags.DYNAMIC_INITIAL_BOUNDS.isEnabled(activity.mWmService.mContext)) { + if (!DesktopModeFlags.ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS.isEnabled()) { return centerInScreen(idealSize, screenBounds); } if (activity.mAppCompatController.getAppCompatAspectRatioOverrides() diff --git a/services/core/java/com/android/server/wm/DesktopModeHelper.java b/services/core/java/com/android/server/wm/DesktopModeHelper.java index 61fbb96882ec..da7631723185 100644 --- a/services/core/java/com/android/server/wm/DesktopModeHelper.java +++ b/services/core/java/com/android/server/wm/DesktopModeHelper.java @@ -35,8 +35,8 @@ public final class DesktopModeHelper { "persist.wm.debug.desktop_mode_enforce_device_restrictions", true); /** Whether desktop mode is enabled. */ - static boolean isDesktopModeEnabled(@NonNull Context context) { - return DesktopModeFlags.DESKTOP_WINDOWING_MODE.isEnabled(context); + static boolean isDesktopModeEnabled() { + return DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODE.isEnabled(); } /** @@ -60,7 +60,7 @@ public final class DesktopModeHelper { * Return {@code true} if desktop mode can be entered on the current device. */ static boolean canEnterDesktopMode(@NonNull Context context) { - return isDesktopModeEnabled(context) + return isDesktopModeEnabled() && (!shouldEnforceDeviceRestrictions() || isDesktopModeSupported(context)); } } diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java index 5514294ed477..e007b1d07b34 100644 --- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java +++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java @@ -181,22 +181,30 @@ class EmbeddedWindowController { return true; } - boolean transferToHost(@NonNull InputTransferToken embeddedWindowToken, + boolean transferToHost(int callingUid, @NonNull InputTransferToken embeddedWindowToken, @NonNull WindowState transferToHostWindowState) { EmbeddedWindow ew = getByInputTransferToken(embeddedWindowToken); if (!isValidTouchGestureParams(transferToHostWindowState, ew)) { return false; } + if (callingUid != ew.mOwnerUid) { + throw new SecurityException( + "Transfer request must originate from owner of transferFromToken"); + } return mInputManagerService.transferTouchGesture(ew.getInputChannelToken(), transferToHostWindowState.mInputChannelToken); } - boolean transferToEmbedded(WindowState hostWindowState, + boolean transferToEmbedded(int callingUid, WindowState hostWindowState, @NonNull InputTransferToken transferToToken) { final EmbeddedWindowController.EmbeddedWindow ew = getByInputTransferToken(transferToToken); if (!isValidTouchGestureParams(hostWindowState, ew)) { return false; } + if (callingUid != hostWindowState.mOwnerUid) { + throw new SecurityException( + "Transfer request must originate from owner of transferFromToken"); + } return mInputManagerService.transferTouchGesture(hostWindowState.mInputChannelToken, ew.getInputChannelToken()); } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 3490b3e12b2a..a2fda0afb9c6 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2789,11 +2789,15 @@ class Task extends TaskFragment { @Override void onDisplayChanged(DisplayContent dc) { + final int lastDisplayId = getDisplayId(); super.onDisplayChanged(dc); if (isLeafTask()) { final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY; - mWmService.mAtmService.getTaskChangeNotificationController().notifyTaskDisplayChanged( - mTaskId, displayId); + //Send the callback when the task reparented to another display. + if (lastDisplayId != displayId) { + mWmService.mAtmService.getTaskChangeNotificationController() + .notifyTaskDisplayChanged(mTaskId, displayId); + } } if (isRootTask()) { updateSurfaceBounds(); diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 638e92f112c7..42ea5a88a09b 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -28,6 +28,7 @@ import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; +import static android.view.Display.INVALID_DISPLAY; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.ActivityRecord.State.RESUMED; @@ -57,6 +58,7 @@ import com.android.internal.protolog.ProtoLog; import com.android.internal.util.ArrayUtils; import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.util.function.pooled.PooledPredicate; +import com.android.server.pm.UserManagerInternal; import com.android.server.wm.LaunchParamsController.LaunchParams; import java.io.PrintWriter; @@ -1761,10 +1763,10 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { * @return last reparented root task, or {@code null} if the root tasks had to be destroyed. */ Task remove() { + final TaskDisplayArea toDisplayArea = getReparentToTaskDisplayArea(getFocusedRootTask()); mPreferredTopFocusableRootTask = null; // TODO(b/153090332): Allow setting content removal mode per task display area final boolean destroyContentOnRemoval = mDisplayContent.shouldDestroyContentOnRemove(); - final TaskDisplayArea toDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea(); Task lastReparentedRootTask = null; // Root tasks could be reparented from the removed display area to other display area. After @@ -1830,6 +1832,41 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { return lastReparentedRootTask; } + /** + * Returns the {@link TaskDisplayArea} to which root tasks should be reparented. + * + * <p>In the automotive multi-user multi-display environment where background users have + * UI access on their assigned displays (a.k.a. visible background users), it's not allowed to + * launch an activity on an unassigned display. If an activity is attempted to launch on an + * unassigned display, it throws an exception. + * <p>This method determines the appropriate {@link TaskDisplayArea} for reparenting root tasks + * when a display is removed, in order to avoid the exception. If the root task is null, + * the visible background user is not supported or the user associated with the root task is + * not a visible background user, it returns the default {@link TaskDisplayArea} of the default + * display. Otherwise, it returns the default {@link TaskDisplayArea} of the main display + * assigned to the user. + * + * @param rootTask The root task whose {@link TaskDisplayArea} needs to be determined. + * @return The {@link TaskDisplayArea} where the root tasks should be reparented to. + */ + private TaskDisplayArea getReparentToTaskDisplayArea(Task rootTask) { + final TaskDisplayArea defaultTaskDisplayArea = + mRootWindowContainer.getDefaultTaskDisplayArea(); + if (rootTask == null) { + return defaultTaskDisplayArea; + } + UserManagerInternal userManagerInternal = mAtmService.mWindowManager.mUmInternal; + if (!userManagerInternal.isVisibleBackgroundFullUser(rootTask.mUserId)) { + return defaultTaskDisplayArea; + } + int toDisplayId = userManagerInternal.getMainDisplayAssignedToUser(rootTask.mUserId); + if (toDisplayId == INVALID_DISPLAY) { + return defaultTaskDisplayArea; + } + DisplayContent dc = mRootWindowContainer.getDisplayContent(toDisplayId); + return dc != null ? dc.getDefaultTaskDisplayArea() : defaultTaskDisplayArea; + } + /** Whether this task display area can request orientation. */ boolean canSpecifyOrientation(@ScreenOrientation int orientation) { // Only allow to specify orientation if this TDA is the last focused one on this logical diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 9d4652957487..7c3f0f22608e 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -35,6 +35,7 @@ import static android.view.SurfaceControl.Transaction; 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; +import static android.window.flags.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ANIM; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; @@ -115,7 +116,6 @@ import com.android.server.wm.SurfaceAnimator.Animatable; import com.android.server.wm.SurfaceAnimator.AnimationType; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; import com.android.server.wm.utils.AlwaysTruePredicate; -import com.android.window.flags.Flags; import java.io.PrintWriter; import java.lang.ref.WeakReference; @@ -457,7 +457,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< source.setFrame(provider.getArbitraryRectangle()) .updateSideHint(getBounds()) .setBoundingRects(provider.getBoundingRects()); - if (Flags.enableCaptionCompatInsetForceConsumption()) { + if (ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isEnabled()) { source.setFlags(provider.getFlags()); } mLocalInsetsSources.put(id, source); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 33f2dd103c2e..b8f47cce6005 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -9212,6 +9212,8 @@ public class WindowManagerService extends IWindowManager.Stub final InputApplicationHandle applicationHandle; final String name; Objects.requireNonNull(outInputChannel); + Objects.requireNonNull(inputTransferToken); + synchronized (mGlobalLock) { WindowState hostWindowState = hostInputTransferToken != null ? mInputToWindowMap.get(hostInputTransferToken.getToken()) : null; @@ -9236,6 +9238,7 @@ public class WindowManagerService extends IWindowManager.Stub Objects.requireNonNull(transferFromToken); Objects.requireNonNull(transferToToken); + final int callingUid = Binder.getCallingUid(); final long identity = Binder.clearCallingIdentity(); boolean didTransfer; try { @@ -9245,12 +9248,14 @@ public class WindowManagerService extends IWindowManager.Stub // represents an embedded window so transfer from host to embedded. WindowState windowStateTo = mInputToWindowMap.get(transferToToken.getToken()); if (windowStateTo != null) { - didTransfer = mEmbeddedWindowController.transferToHost(transferFromToken, + didTransfer = mEmbeddedWindowController.transferToHost(callingUid, + transferFromToken, windowStateTo); } else { WindowState windowStateFrom = mInputToWindowMap.get( transferFromToken.getToken()); - didTransfer = mEmbeddedWindowController.transferToEmbedded(windowStateFrom, + didTransfer = mEmbeddedWindowController.transferToEmbedded(callingUid, + windowStateFrom, transferToToken); } } diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 976be4aa3bd4..30d6f0a46bae 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -326,6 +326,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio public static final int ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK = 1 << 22; public static final int ACTIVITY_STATE_FLAG_RESUMED_SPLIT_SCREEN = 1 << 23; public static final int ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM = 1 << 24; + public static final int ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE = 1 << 25; public static final int ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER = 0x0000ffff; /** @@ -1293,8 +1294,12 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio if (hasResumedFreeform && com.android.window.flags.Flags.processPriorityPolicyForMultiWindowMode() // Exclude task layer 1 because it is already the top most. - && minTaskLayer > 1 && minTaskLayer <= 1 + MAX_NUM_PERCEPTIBLE_FREEFORM) { - stateFlags |= ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM; + && minTaskLayer > 1) { + if (minTaskLayer <= 1 + MAX_NUM_PERCEPTIBLE_FREEFORM) { + stateFlags |= ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM; + } else { + stateFlags |= ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE; + } } stateFlags |= minTaskLayer & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER; if (visible) { diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 8c4448e7915f..155e73c53819 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -1808,9 +1808,30 @@ void NativeInputManager::loadAdditionalMouseResources( ATRACE_CALL(); JNIEnv* env = jniEnv(); - for (int32_t iconId = static_cast<int32_t>(PointerIconStyle::TYPE_CONTEXT_MENU); - iconId <= static_cast<int32_t>(PointerIconStyle::TYPE_HANDWRITING); ++iconId) { - const PointerIconStyle pointerIconStyle = static_cast<PointerIconStyle>(iconId); + constexpr static std::array ADDITIONAL_STYLES{PointerIconStyle::TYPE_CONTEXT_MENU, + PointerIconStyle::TYPE_HAND, + PointerIconStyle::TYPE_HELP, + PointerIconStyle::TYPE_WAIT, + PointerIconStyle::TYPE_CELL, + PointerIconStyle::TYPE_CROSSHAIR, + PointerIconStyle::TYPE_TEXT, + PointerIconStyle::TYPE_VERTICAL_TEXT, + PointerIconStyle::TYPE_ALIAS, + PointerIconStyle::TYPE_COPY, + PointerIconStyle::TYPE_NO_DROP, + PointerIconStyle::TYPE_ALL_SCROLL, + PointerIconStyle::TYPE_HORIZONTAL_DOUBLE_ARROW, + PointerIconStyle::TYPE_VERTICAL_DOUBLE_ARROW, + PointerIconStyle::TYPE_TOP_RIGHT_DOUBLE_ARROW, + PointerIconStyle::TYPE_TOP_LEFT_DOUBLE_ARROW, + PointerIconStyle::TYPE_ZOOM_IN, + PointerIconStyle::TYPE_ZOOM_OUT, + PointerIconStyle::TYPE_GRAB, + PointerIconStyle::TYPE_GRABBING, + PointerIconStyle::TYPE_HANDWRITING, + PointerIconStyle::TYPE_SPOT_HOVER}; + + for (const auto pointerIconStyle : ADDITIONAL_STYLES) { PointerIcon pointerIcon = loadPointerIcon(env, displayId, pointerIconStyle); (*outResources)[pointerIconStyle] = toSpriteIcon(pointerIcon); if (!pointerIcon.bitmapFrames.empty()) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java index 24ee46fbcd6f..f271162bbfa4 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java @@ -102,9 +102,6 @@ final class PolicyDefinition<V> { PolicyEnforcerCallbacks.setAutoTimezoneEnabled(value, context), new BooleanPolicySerializer()); - // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the - // actual policy with the correct arguments (packageName and permission name) - // when reading the policies from xml. static final PolicyDefinition<Integer> GENERIC_PERMISSION_GRANT = new PolicyDefinition<>( new PackagePermissionPolicyKey(DevicePolicyIdentifiers.PERMISSION_GRANT_POLICY), @@ -123,10 +120,6 @@ final class PolicyDefinition<V> { PolicyEnforcerCallbacks::setPermissionGrantState, new IntegerPolicySerializer()); - /** - * Passing in {@code null} for {@code packageName} or {@code permissionName} will return a - * {@link #GENERIC_PERMISSION_GRANT}. - */ static PolicyDefinition<Integer> PERMISSION_GRANT( @NonNull String packageName, @NonNull String permissionName) { Objects.requireNonNull(packageName, "packageName must not be null"); @@ -170,9 +163,6 @@ final class PolicyDefinition<V> { PolicyEnforcerCallbacks::setUserControlDisabledPackages, new PackageSetPolicySerializer()); - // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the - // actual policy with the correct arguments (i.e. packageName) when reading the policies from - // xml. static PolicyDefinition<ComponentName> GENERIC_PERSISTENT_PREFERRED_ACTIVITY = new PolicyDefinition<>( new IntentFilterPolicyKey( @@ -184,10 +174,6 @@ final class PolicyDefinition<V> { PolicyEnforcerCallbacks::addPersistentPreferredActivity, new ComponentNamePolicySerializer()); - /** - * Passing in {@code null} for {@code intentFilter} will return - * {@link #GENERIC_PERSISTENT_PREFERRED_ACTIVITY}. - */ static PolicyDefinition<ComponentName> PERSISTENT_PREFERRED_ACTIVITY( @NonNull IntentFilter intentFilter) { Objects.requireNonNull(intentFilter, "intentFilter must not be null"); @@ -197,9 +183,6 @@ final class PolicyDefinition<V> { intentFilter)); } - // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the - // actual policy with the correct arguments (i.e. packageName) when reading the policies from - // xml. static PolicyDefinition<Boolean> GENERIC_PACKAGE_UNINSTALL_BLOCKED = new PolicyDefinition<>( new PackagePolicyKey( @@ -209,10 +192,6 @@ final class PolicyDefinition<V> { PolicyEnforcerCallbacks::setUninstallBlocked, new BooleanPolicySerializer()); - /** - * Passing in {@code null} for {@code packageName} will return - * {@link #GENERIC_PACKAGE_UNINSTALL_BLOCKED}. - */ static PolicyDefinition<Boolean> PACKAGE_UNINSTALL_BLOCKED(@NonNull String packageName) { Objects.requireNonNull(packageName, "packageName must not be null"); return GENERIC_PACKAGE_UNINSTALL_BLOCKED.createPolicyDefinition( @@ -220,9 +199,6 @@ final class PolicyDefinition<V> { DevicePolicyIdentifiers.PACKAGE_UNINSTALL_BLOCKED_POLICY, packageName)); } - // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the - // actual policy with the correct arguments (i.e. packageName) when reading the policies from - // xml. static PolicyDefinition<Bundle> GENERIC_APPLICATION_RESTRICTIONS = new PolicyDefinition<>( new PackagePolicyKey( @@ -237,10 +213,6 @@ final class PolicyDefinition<V> { PolicyEnforcerCallbacks::setApplicationRestrictions, new BundlePolicySerializer()); - /** - * Passing in {@code null} for {@code packageName} will return - * {@link #GENERIC_APPLICATION_RESTRICTIONS}. - */ static PolicyDefinition<Bundle> APPLICATION_RESTRICTIONS(@NonNull String packageName) { Objects.requireNonNull(packageName, "packageName must not be null"); return GENERIC_APPLICATION_RESTRICTIONS.createPolicyDefinition( @@ -266,9 +238,6 @@ final class PolicyDefinition<V> { PolicyEnforcerCallbacks::noOp, new IntegerPolicySerializer()); - // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the - // actual policy with the correct arguments (i.e. packageName) when reading the policies from - // xml. static PolicyDefinition<Boolean> GENERIC_APPLICATION_HIDDEN = new PolicyDefinition<>( new PackagePolicyKey( @@ -281,10 +250,6 @@ final class PolicyDefinition<V> { PolicyEnforcerCallbacks::setApplicationHidden, new BooleanPolicySerializer()); - /** - * Passing in {@code null} for {@code packageName} will return - * {@link #GENERIC_APPLICATION_HIDDEN}. - */ static PolicyDefinition<Boolean> APPLICATION_HIDDEN(@NonNull String packageName) { Objects.requireNonNull(packageName, "packageName must not be null"); return GENERIC_APPLICATION_HIDDEN.createPolicyDefinition( @@ -292,9 +257,6 @@ final class PolicyDefinition<V> { DevicePolicyIdentifiers.APPLICATION_HIDDEN_POLICY, packageName)); } - // This is saved in the static map sPolicyDefinitions so that we're able to reconstruct the - // actual policy with the correct arguments (i.e. packageName) when reading the policies from - // xml. static PolicyDefinition<Boolean> GENERIC_ACCOUNT_MANAGEMENT_DISABLED = new PolicyDefinition<>( new AccountTypePolicyKey( @@ -305,10 +267,6 @@ final class PolicyDefinition<V> { PolicyEnforcerCallbacks::noOp, new BooleanPolicySerializer()); - /** - * Passing in {@code null} for {@code accountType} will return - * {@link #GENERIC_ACCOUNT_MANAGEMENT_DISABLED}. - */ static PolicyDefinition<Boolean> ACCOUNT_MANAGEMENT_DISABLED(@NonNull String accountType) { Objects.requireNonNull(accountType, "accountType must not be null"); return GENERIC_ACCOUNT_MANAGEMENT_DISABLED.createPolicyDefinition( @@ -668,8 +626,6 @@ final class PolicyDefinition<V> { throw new UnsupportedOperationException("Non-coexistable global policies not supported," + "please add support."); } - // TODO: maybe use this instead of manually adding to the map -// sPolicyDefinitions.put(policyDefinitionKey, this); } void saveToXml(TypedXmlSerializer serializer) throws IOException { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index ab459df1cdf6..9fdf088c3d1d 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -107,7 +107,7 @@ import com.android.internal.os.BinderInternal; import com.android.internal.os.RuntimeInit; import com.android.internal.policy.AttributeCache; import com.android.internal.protolog.ProtoLog; -import com.android.internal.protolog.ProtoLogConfigurationService; +import com.android.internal.protolog.ProtoLogConfigurationServiceImpl; import com.android.internal.protolog.ProtoLogGroup; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.EmergencyAffordanceManager; @@ -1097,7 +1097,7 @@ public final class SystemServer implements Dumpable { if (android.tracing.Flags.clientSideProtoLogging()) { t.traceBegin("StartProtoLogConfigurationService"); ServiceManager.addService( - Context.PROTOLOG_CONFIGURATION_SERVICE, new ProtoLogConfigurationService()); + Context.PROTOLOG_CONFIGURATION_SERVICE, new ProtoLogConfigurationServiceImpl()); t.traceEnd(); } diff --git a/services/lint-baseline.xml b/services/lint-baseline.xml index a311d07e52fb..95da56da156c 100644 --- a/services/lint-baseline.xml +++ b/services/lint-baseline.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<issues format="6" by="lint 8.4.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha01"> +<issues format="6" by="lint 8.4.0-alpha08" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha08"> <issue id="SimpleManualPermissionEnforcement" @@ -8,7 +8,7 @@ errorLine2=" ^"> <location file="frameworks/base/services/java/com/android/server/SystemConfigService.java" - line="46" + line="50" column="13"/> </issue> @@ -19,7 +19,7 @@ errorLine2=" ^"> <location file="frameworks/base/services/java/com/android/server/SystemConfigService.java" - line="54" + line="58" column="13"/> </issue> @@ -30,7 +30,7 @@ errorLine2=" ^"> <location file="frameworks/base/services/java/com/android/server/SystemConfigService.java" - line="67" + line="71" column="13"/> </issue> @@ -41,7 +41,7 @@ errorLine2=" ^"> <location file="frameworks/base/services/java/com/android/server/SystemConfigService.java" - line="76" + line="80" column="13"/> </issue> @@ -52,8 +52,30 @@ errorLine2=" ^"> <location file="frameworks/base/services/java/com/android/server/SystemConfigService.java" - line="107" + line="111" column="13"/> </issue> -</issues>
\ No newline at end of file + <issue + id="SimpleManualPermissionEnforcement" + message="ISystemConfig permission check should be converted to @EnforcePermission annotation" + errorLine1=" getContext().enforceCallingOrSelfPermission(" + errorLine2=" ^"> + <location + file="frameworks/base/services/java/com/android/server/SystemConfigService.java" + line="127" + column="13"/> + </issue> + + <issue + id="SimpleManualPermissionEnforcement" + message="ISystemConfig permission check should be converted to @EnforcePermission annotation" + errorLine1=" getContext().enforceCallingOrSelfPermission(" + errorLine2=" ^"> + <location + file="frameworks/base/services/java/com/android/server/SystemConfigService.java" + line="137" + column="13"/> + </issue> + +</issues> diff --git a/services/tests/appfunctions/src/com/android/server/appfunctions/MetadataSyncAdapterTest.kt b/services/tests/appfunctions/src/com/android/server/appfunctions/MetadataSyncAdapterTest.kt index 63cf7bf7cb5e..c05c3819ca28 100644 --- a/services/tests/appfunctions/src/com/android/server/appfunctions/MetadataSyncAdapterTest.kt +++ b/services/tests/appfunctions/src/com/android/server/appfunctions/MetadataSyncAdapterTest.kt @@ -139,16 +139,15 @@ class MetadataSyncAdapterTest { runtimeSearchSession.put(putDocumentsRequest).get() staticSearchSession.put(putDocumentsRequest).get() val metadataSyncAdapter = - MetadataSyncAdapter( - testExecutor, - runtimeSearchSession, + MetadataSyncAdapter(testExecutor, packageManager, appSearchManager) + + val submitSyncRequest = + metadataSyncAdapter.trySyncAppFunctionMetadataBlocking( staticSearchSession, - packageManager, + runtimeSearchSession, ) - val submitSyncRequest = metadataSyncAdapter.submitSyncRequest() - - assertThat(submitSyncRequest.get()).isTrue() + assertThat(submitSyncRequest).isInstanceOf(Unit::class.java) } @Test @@ -182,16 +181,15 @@ class MetadataSyncAdapterTest { PutDocumentsRequest.Builder().addGenericDocuments(functionRuntimeMetadata).build() staticSearchSession.put(putDocumentsRequest).get() val metadataSyncAdapter = - MetadataSyncAdapter( - testExecutor, - runtimeSearchSession, + MetadataSyncAdapter(testExecutor, packageManager, appSearchManager) + + val submitSyncRequest = + metadataSyncAdapter.trySyncAppFunctionMetadataBlocking( staticSearchSession, - packageManager, + runtimeSearchSession, ) - val submitSyncRequest = metadataSyncAdapter.submitSyncRequest() - - assertThat(submitSyncRequest.get()).isTrue() + assertThat(submitSyncRequest).isInstanceOf(Unit::class.java) } @Test @@ -239,16 +237,15 @@ class MetadataSyncAdapterTest { PutDocumentsRequest.Builder().addGenericDocuments(functionRuntimeMetadata).build() runtimeSearchSession.put(putDocumentsRequest).get() val metadataSyncAdapter = - MetadataSyncAdapter( - testExecutor, - runtimeSearchSession, + MetadataSyncAdapter(testExecutor, packageManager, appSearchManager) + + val submitSyncRequest = + metadataSyncAdapter.trySyncAppFunctionMetadataBlocking( staticSearchSession, - packageManager, + runtimeSearchSession, ) - val submitSyncRequest = metadataSyncAdapter.submitSyncRequest() - - assertThat(submitSyncRequest.get()).isTrue() + assertThat(submitSyncRequest).isInstanceOf(Unit::class.java) } @Test 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 8b80f85aec00..255dcb083518 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -27,6 +27,7 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_D import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION; import static android.view.ContentRecordingSession.RECORD_CONTENT_DISPLAY; import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK; +import static android.view.Display.HdrCapabilities.HDR_TYPE_INVALID; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.server.display.ExternalDisplayPolicy.ENABLE_ON_CONNECT; @@ -195,8 +196,8 @@ public class DisplayManagerServiceTest { private static final String VIRTUAL_DISPLAY_NAME = "Test Virtual Display"; private static final String PACKAGE_NAME = "com.android.frameworks.displayservicetests"; private static final long STANDARD_DISPLAY_EVENTS = DisplayManager.EVENT_FLAG_DISPLAY_ADDED - | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED - | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED; + | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED + | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED; private static final long STANDARD_AND_CONNECTION_DISPLAY_EVENTS = STANDARD_DISPLAY_EVENTS | DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED; @@ -238,6 +239,8 @@ public class DisplayManagerServiceTest { private UserManager mUserManager; + private int[] mAllowedHdrOutputTypes; + private final DisplayManagerService.Injector mShortMockedInjector = new DisplayManagerService.Injector() { @Override @@ -256,11 +259,12 @@ public class DisplayManagerServiceTest { displayAdapterListener, flags, mMockedDisplayNotificationManager, new LocalDisplayAdapter.Injector() { - @Override - public LocalDisplayAdapter.SurfaceControlProxy getSurfaceControlProxy() { - return mSurfaceControlProxy; - } - }); + @Override + public LocalDisplayAdapter.SurfaceControlProxy + getSurfaceControlProxy() { + return mSurfaceControlProxy; + } + }); } @Override @@ -320,7 +324,7 @@ public class DisplayManagerServiceTest { @Override int setHdrConversionMode(int conversionMode, int preferredHdrOutputType, - int[] autoHdrTypes) { + int[] allowedHdrOutputTypes) { mHdrConversionMode = conversionMode; mPreferredHdrOutputType = preferredHdrOutputType; return Display.HdrCapabilities.HDR_TYPE_INVALID; @@ -1295,11 +1299,11 @@ public class DisplayManagerServiceTest { .setUniqueId("uniqueId --- mirror display"); assertThrows(SecurityException.class, () -> { localService.createVirtualDisplay( - builder.build(), - mMockAppToken /* callback */, - null /* virtualDeviceToken */, - mock(DisplayWindowPolicyController.class), - PACKAGE_NAME); + builder.build(), + mMockAppToken /* callback */, + null /* virtualDeviceToken */, + mock(DisplayWindowPolicyController.class), + PACKAGE_NAME); }); } @@ -1433,7 +1437,7 @@ public class DisplayManagerServiceTest { // The virtual display should not have FLAG_ALWAYS_UNLOCKED set. assertEquals(0, (displayManager.getDisplayDeviceInfoInternal(displayId).flags - & DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED)); + & DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED)); } /** @@ -1466,7 +1470,7 @@ public class DisplayManagerServiceTest { // The virtual display should not have FLAG_PRESENTATION set. assertEquals(0, (displayManager.getDisplayDeviceInfoInternal(displayId).flags - & DisplayDeviceInfo.FLAG_PRESENTATION)); + & DisplayDeviceInfo.FLAG_PRESENTATION)); } @Test @@ -2358,6 +2362,7 @@ public class DisplayManagerServiceTest { HdrConversionMode.HDR_CONVERSION_FORCE, Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION); displayManager.setHdrConversionModeInternal(mode); + assertEquals(mode, displayManager.getHdrConversionModeSettingInternal()); assertEquals(mode.getConversionMode(), mHdrConversionMode); assertEquals(mode.getPreferredHdrOutputType(), mPreferredHdrOutputType); @@ -2402,6 +2407,86 @@ public class DisplayManagerServiceTest { } @Test + public void testSetAreUserDisabledHdrTypesAllowed_withFalse_whenHdrDisabled_stripsHdrType() { + DisplayManagerService displayManager = new DisplayManagerService( + mContext, new BasicInjector() { + @Override + int setHdrConversionMode(int conversionMode, int preferredHdrOutputType, + int[] allowedTypes) { + mAllowedHdrOutputTypes = allowedTypes; + return Display.HdrCapabilities.HDR_TYPE_INVALID; + } + + // Overriding this method to capture the allowed HDR type + @Override + int[] getSupportedHdrOutputTypes() { + return new int[]{Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION}; + } + }); + + // Setup: no HDR types disabled, userDisabledTypes allowed, system conversion + displayManager.setUserDisabledHdrTypesInternal(new int [0]); + displayManager.setAreUserDisabledHdrTypesAllowedInternal(true); + displayManager.setHdrConversionModeInternal( + new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM)); + + assertEquals(1, mAllowedHdrOutputTypes.length); + assertTrue(Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION == mAllowedHdrOutputTypes[0]); + + // Action: disable Dolby Vision, set userDisabledTypes not allowed + displayManager.setUserDisabledHdrTypesInternal( + new int [] {Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION}); + displayManager.setAreUserDisabledHdrTypesAllowedInternal(false); + + assertEquals(0, mAllowedHdrOutputTypes.length); + } + + @Test + public void testGetEnabledHdrTypesLocked_whenTypesDisabled_stripsDisabledTypes() { + DisplayManagerService displayManager = new DisplayManagerService( + mContext, new BasicInjector() { + @Override + int[] getSupportedHdrOutputTypes() { + return new int[]{Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION}; + } + }); + + displayManager.setUserDisabledHdrTypesInternal(new int [0]); + displayManager.setAreUserDisabledHdrTypesAllowedInternal(true); + int [] enabledHdrOutputTypes = displayManager.getEnabledHdrOutputTypes(); + assertEquals(1, enabledHdrOutputTypes.length); + assertTrue(Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION == enabledHdrOutputTypes[0]); + + displayManager.setAreUserDisabledHdrTypesAllowedInternal(false); + enabledHdrOutputTypes = displayManager.getEnabledHdrOutputTypes(); + assertEquals(1, enabledHdrOutputTypes.length); + assertTrue(Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION == enabledHdrOutputTypes[0]); + + displayManager.setUserDisabledHdrTypesInternal( + new int [] {Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION}); + enabledHdrOutputTypes = displayManager.getEnabledHdrOutputTypes(); + assertEquals(0, enabledHdrOutputTypes.length); + } + + @Test + public void testSetHdrConversionModeInternal_isForceSdrIsUpdated() { + DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); + LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper(); + FakeDisplayDevice displayDevice = + createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL); + LogicalDisplay logicalDisplay = + logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true); + + displayManager.setHdrConversionModeInternal( + new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, HDR_TYPE_INVALID)); + assertTrue(logicalDisplay.getDisplayInfoLocked().isForceSdr); + + displayManager.setHdrConversionModeInternal( + new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM)); + assertFalse(logicalDisplay.getDisplayInfoLocked().isForceSdr); + } + + @Test public void testReturnsRefreshRateForDisplayAndSensor_proximitySensorSet() { DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); DisplayManagerInternal localService = displayManager.new LocalService(); @@ -3505,7 +3590,7 @@ public class DisplayManagerServiceTest { } private FakeDisplayDevice createFakeDisplayDevice(DisplayManagerService displayManager, - Display.Mode[] modes) { + Display.Mode[] modes) { FakeDisplayDevice displayDevice = new FakeDisplayDevice(); DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo(); displayDeviceInfo.supportedModes = modes; @@ -3761,9 +3846,9 @@ public class DisplayManagerServiceTest { public void setUserPreferredDisplayModeLocked(Display.Mode preferredMode) { for (Display.Mode mode : mDisplayDeviceInfo.supportedModes) { if (mode.matchesIfValid( - preferredMode.getPhysicalWidth(), - preferredMode.getPhysicalHeight(), - preferredMode.getRefreshRate())) { + preferredMode.getPhysicalWidth(), + preferredMode.getPhysicalHeight(), + preferredMode.getRefreshRate())) { mPreferredMode = mode; break; } diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java index 8b653378664e..32135f1cb7fa 100644 --- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java @@ -22,9 +22,10 @@ import static android.permission.flags.Flags.FLAG_SENSITIVE_NOTIFICATION_APP_PRO import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 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.doCallRealMethod; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.never; @@ -36,6 +37,7 @@ import android.content.pm.PackageManagerInternal; import android.media.projection.MediaProjectionInfo; import android.media.projection.MediaProjectionManager; import android.os.Process; +import android.os.RemoteException; import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; @@ -137,9 +139,17 @@ public class SensitiveContentProtectionManagerServiceNotificationTest { mSensitiveContentProtectionManagerService.mNotificationListener = spy(mSensitiveContentProtectionManagerService.mNotificationListener); - doCallRealMethod() - .when(mSensitiveContentProtectionManagerService.mNotificationListener) - .onListenerConnected(); + + // Unexpected NLS interactions when registered cause test flakes. For purposes of this test, + // the test will control any NLS calls. + try { + doNothing().when(mSensitiveContentProtectionManagerService.mNotificationListener) + .registerAsSystemService(any(), any(), anyInt()); + doNothing().when(mSensitiveContentProtectionManagerService.mNotificationListener) + .unregisterAsSystemService(); + } catch (RemoteException e) { + // Intra-process call, should never happen. + } // Setup RankingMap and two possilbe rankings when(mSensitiveRanking.hasSensitiveContent()).thenReturn(true); diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java index 5ec53023dc67..f6ad07d03673 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -62,6 +62,7 @@ import static com.android.server.am.ProcessList.PERSISTENT_SERVICE_ADJ; import static com.android.server.am.ProcessList.PREVIOUS_APP_ADJ; import static com.android.server.am.ProcessList.SCHED_GROUP_BACKGROUND; import static com.android.server.am.ProcessList.SCHED_GROUP_DEFAULT; +import static com.android.server.am.ProcessList.SCHED_GROUP_FOREGROUND_WINDOW; import static com.android.server.am.ProcessList.SCHED_GROUP_RESTRICTED; import static com.android.server.am.ProcessList.SCHED_GROUP_TOP_APP; import static com.android.server.am.ProcessList.SCHED_GROUP_TOP_APP_BOUND; @@ -534,6 +535,14 @@ public class MockingOomAdjusterTests { updateOomAdj(app); assertProcStates(app, PROCESS_STATE_TOP, VISIBLE_APP_ADJ, SCHED_GROUP_TOP_APP); assertEquals("perceptible-freeform-activity", app.mState.getAdjType()); + + doReturn(WindowProcessController.ACTIVITY_STATE_FLAG_IS_VISIBLE + | WindowProcessController.ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE) + .when(wpc).getActivityStateFlags(); + updateOomAdj(app); + assertProcStates(app, PROCESS_STATE_TOP, VISIBLE_APP_ADJ, + SCHED_GROUP_FOREGROUND_WINDOW); + assertEquals("vis-multi-window-activity", app.mState.getAdjType()); } @SuppressWarnings("GuardedBy") diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundUserSoundNotifierTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundUserSoundNotifierTest.java index a82658b52a77..3062d5120e6f 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundUserSoundNotifierTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundUserSoundNotifierTest.java @@ -16,13 +16,19 @@ package com.android.server.pm; +import static android.media.AudioAttributes.USAGE_ALARM; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; 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 static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.testng.AssertJUnit.assertEquals; import android.app.Notification; import android.app.NotificationManager; @@ -31,6 +37,9 @@ import android.content.pm.UserInfo; import android.media.AudioAttributes; import android.media.AudioFocusInfo; import android.media.AudioManager; +import android.media.AudioPlaybackConfiguration; +import android.media.PlayerProxy; +import android.media.audiopolicy.AudioPolicy; import android.os.Build; import android.os.RemoteException; import android.os.UserHandle; @@ -45,6 +54,10 @@ import org.junit.runners.JUnit4; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + @RunWith(JUnit4.class) public class BackgroundUserSoundNotifierTest { @@ -63,7 +76,10 @@ public class BackgroundUserSoundNotifierTest { MockitoAnnotations.initMocks(this); mSpiedContext = spy(mRealContext); mUsersToRemove = new ArraySet<>(); - mUserManager = UserManager.get(mRealContext); + + mUserManager = spy(mSpiedContext.getSystemService(UserManager.class)); + doReturn(mUserManager) + .when(mSpiedContext).getSystemService(UserManager.class); doReturn(mNotificationManager) .when(mSpiedContext).getSystemService(NotificationManager.class); mBackgroundUserSoundNotifier = new BackgroundUserSoundNotifier(mSpiedContext); @@ -74,12 +90,9 @@ public class BackgroundUserSoundNotifierTest { mUsersToRemove.stream().toList().forEach(this::removeUser); } @Test - public void testAlarmOnBackgroundUser_ForegroundUserNotified() throws RemoteException { - AudioAttributes aa = new AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_ALARM).build(); - UserInfo user = createUser("User", - UserManager.USER_TYPE_FULL_SECONDARY, - 0); + public void testAlarmOnBackgroundUser_foregroundUserNotified() throws RemoteException { + AudioAttributes aa = new AudioAttributes.Builder().setUsage(USAGE_ALARM).build(); + UserInfo user = createUser("User", UserManager.USER_TYPE_FULL_SECONDARY, 0); final int fgUserId = mSpiedContext.getUserId(); final int bgUserUid = user.id * 100000; doReturn(UserHandle.of(fgUserId)).when(mSpiedContext).getUser(); @@ -95,10 +108,9 @@ public class BackgroundUserSoundNotifierTest { } @Test - public void testMediaOnBackgroundUser_ForegroundUserNotNotified() throws RemoteException { + public void testMediaOnBackgroundUser_foregroundUserNotNotified() throws RemoteException { AudioAttributes aa = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA).build(); - UserInfo user = createUser("User", UserManager.USER_TYPE_FULL_SECONDARY, 0); final int bgUserUid = mSpiedContext.getUserId() * 100000; AudioFocusInfo afi = new AudioFocusInfo(aa, bgUserUid, "", /* packageName= */ "com.android.car.audio", AudioManager.AUDIOFOCUS_GAIN, @@ -109,9 +121,9 @@ public class BackgroundUserSoundNotifierTest { } @Test - public void testAlarmOnForegroundUser_ForegroundUserNotNotified() throws RemoteException { + public void testAlarmOnForegroundUser_foregroundUserNotNotified() throws RemoteException { AudioAttributes aa = new AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_ALARM).build(); + .setUsage(USAGE_ALARM).build(); final int fgUserId = mSpiedContext.getUserId(); final int fgUserUid = fgUserId * 100000; doReturn(UserHandle.of(fgUserId)).when(mSpiedContext).getUser(); @@ -123,6 +135,109 @@ public class BackgroundUserSoundNotifierTest { verifyZeroInteractions(mNotificationManager); } + @Test + public void testMuteAlarmSounds() { + final int fgUserId = mSpiedContext.getUserId(); + int bgUserId = fgUserId + 1; + int bgUserUid = bgUserId * 100000; + mBackgroundUserSoundNotifier.mNotificationClientUid = bgUserUid; + + AudioManager mockAudioManager = mock(AudioManager.class); + when(mSpiedContext.getSystemService(AudioManager.class)).thenReturn(mockAudioManager); + + AudioPlaybackConfiguration apc1 = mock(AudioPlaybackConfiguration.class); + when(apc1.getClientUid()).thenReturn(bgUserUid); + when(apc1.getPlayerProxy()).thenReturn(mock(PlayerProxy.class)); + + AudioPlaybackConfiguration apc2 = mock(AudioPlaybackConfiguration.class); + when(apc2.getClientUid()).thenReturn(bgUserUid + 1); + when(apc2.getPlayerProxy()).thenReturn(mock(PlayerProxy.class)); + + List<AudioPlaybackConfiguration> configs = new ArrayList<>(); + configs.add(apc1); + configs.add(apc2); + when(mockAudioManager.getActivePlaybackConfigurations()).thenReturn(configs); + + AudioPolicy mockAudioPolicy = mock(AudioPolicy.class); + + AudioAttributes aa = new AudioAttributes.Builder().setUsage(USAGE_ALARM).build(); + AudioFocusInfo afi = new AudioFocusInfo(aa, bgUserUid, "", /* packageName= */ "", + AudioManager.AUDIOFOCUS_GAIN, AudioManager.AUDIOFOCUS_NONE, /* flags= */ 0, + Build.VERSION.SDK_INT); + Stack<AudioFocusInfo> focusStack = new Stack<>(); + focusStack.add(afi); + doReturn(focusStack).when(mockAudioPolicy).getFocusStack(); + mBackgroundUserSoundNotifier.mFocusControlAudioPolicy = mockAudioPolicy; + + mBackgroundUserSoundNotifier.muteAlarmSounds(mSpiedContext); + + verify(apc1.getPlayerProxy()).stop(); + verify(apc2.getPlayerProxy(), never()).stop(); + } + + @Test + public void testOnAudioFocusGrant_alarmOnBackgroundUser_notifiesForegroundUser() { + final int fgUserId = mSpiedContext.getUserId(); + UserInfo bgUser = createUser("Background User", UserManager.USER_TYPE_FULL_SECONDARY, 0); + int bgUserUid = bgUser.id * 100000; + + AudioAttributes aa = new AudioAttributes.Builder().setUsage(USAGE_ALARM).build(); + AudioFocusInfo afi = new AudioFocusInfo(aa, bgUserUid, "", "", + AudioManager.AUDIOFOCUS_GAIN, 0, 0, Build.VERSION.SDK_INT); + + mBackgroundUserSoundNotifier.getAudioPolicyFocusListener() + .onAudioFocusGrant(afi, AudioManager.AUDIOFOCUS_REQUEST_GRANTED); + + verify(mNotificationManager) + .notifyAsUser(eq(BackgroundUserSoundNotifier.class.getSimpleName()), + eq(afi.getClientUid()), any(Notification.class), + eq(UserHandle.of(fgUserId))); + } + + + @Test + public void testCreateNotification_UserSwitcherEnabled_bothActionsAvailable() { + String userName = "BgUser"; + + doReturn(true).when(mUserManager).isUserSwitcherEnabled(); + doReturn(UserManager.SWITCHABILITY_STATUS_OK) + .when(mUserManager).getUserSwitchability(any()); + + Notification notification = mBackgroundUserSoundNotifier.createNotification(userName, + mSpiedContext); + + assertEquals("Alarm for BgUser", notification.extras.getString( + Notification.EXTRA_TITLE)); + assertEquals(Notification.CATEGORY_REMINDER, notification.category); + assertEquals(Notification.VISIBILITY_PUBLIC, notification.visibility); + assertEquals(com.android.internal.R.drawable.ic_audio_alarm, + notification.getSmallIcon().getResId()); + + assertEquals(2, notification.actions.length); + assertEquals(mSpiedContext.getString( + com.android.internal.R.string.bg_user_sound_notification_button_mute), + notification.actions[0].title); + assertEquals(mSpiedContext.getString( + com.android.internal.R.string.bg_user_sound_notification_button_switch_user), + notification.actions[1].title); + } + + @Test + public void testCreateNotification_UserSwitcherDisabled_onlyMuteActionAvailable() { + String userName = "BgUser"; + + doReturn(false).when(mUserManager).isUserSwitcherEnabled(); + doReturn(UserManager.SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED) + .when(mUserManager).getUserSwitchability(any()); + + Notification notification = mBackgroundUserSoundNotifier.createNotification(userName, + mSpiedContext); + + assertEquals(1, notification.actions.length); + assertEquals(mSpiedContext.getString( + com.android.internal.R.string.bg_user_sound_notification_button_mute), + notification.actions[0].title); + } private UserInfo createUser(String name, String userType, int flags) { UserInfo user = mUserManager.createUser(name, userType, flags); diff --git a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java index 1a398c5f1ec3..e0c393cada49 100644 --- a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java @@ -100,6 +100,7 @@ import com.android.modules.utils.testing.ExtendedMockitoRule; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.SystemServiceManager; +import com.android.server.pm.UserManagerInternal; import org.junit.After; import org.junit.Before; @@ -145,6 +146,7 @@ public class TrustManagerServiceTest { private static final String URI_SCHEME_PACKAGE = "package"; private static final int TEST_USER_ID = 50; + private static final int TEST_VISIBLE_BACKGROUND_USER_ID = 51; private static final UserInfo TEST_USER = new UserInfo(TEST_USER_ID, "user", UserInfo.FLAG_FULL); private static final int PARENT_USER_ID = 60; @@ -170,6 +172,7 @@ public class TrustManagerServiceTest { private @Mock KeyStoreAuthorization mKeyStoreAuthorization; private @Mock LockPatternUtils mLockPatternUtils; private @Mock LockSettingsInternal mLockSettingsInternal; + private @Mock UserManagerInternal mUserManagerInternal; private @Mock PackageManager mPackageManager; private @Mock UserManager mUserManager; private @Mock IWindowManager mWindowManager; @@ -224,6 +227,7 @@ public class TrustManagerServiceTest { when(mUserManager.getAliveUsers()).thenReturn(List.of(TEST_USER)); when(mUserManager.getEnabledProfileIds(TEST_USER_ID)).thenReturn(new int[0]); when(mUserManager.getUserInfo(TEST_USER_ID)).thenReturn(TEST_USER); + when(mUserManager.isVisibleBackgroundUsersSupported()).thenReturn(false); when(mWindowManager.isKeyguardLocked()).thenReturn(true); @@ -593,6 +597,54 @@ public class TrustManagerServiceTest { verify(mTrustListener, never()).onTrustManagedChanged(anyBoolean(), anyInt()); } + @Test + public void testDeviceLocked_visibleBackgroundUser_userLocked() throws RemoteException { + setupVisibleBackgroundUser(/* visible= */ true, /* unlocked= */ false); + mService.waitForIdle(); + mTrustManager.reportEnabledTrustAgentsChanged(TEST_VISIBLE_BACKGROUND_USER_ID); + mService.waitForIdle(); + assertThat(mService.isDeviceLockedInner(TEST_VISIBLE_BACKGROUND_USER_ID)).isTrue(); + } + + @Test + public void testDeviceLocked_visibleBackgroundUser_userUnlocked() throws RemoteException { + setupVisibleBackgroundUser(/* visible= */ true, /* unlocked= */ true); + mService.waitForIdle(); + mTrustManager.reportEnabledTrustAgentsChanged(TEST_VISIBLE_BACKGROUND_USER_ID); + mService.waitForIdle(); + assertThat(mService.isDeviceLockedInner(TEST_VISIBLE_BACKGROUND_USER_ID)).isFalse(); + } + + @Test + public void testDeviceLocked_invisibleBackgroundUser_userUnlocked() throws RemoteException { + setupVisibleBackgroundUser(/* visible= */ false, /* unlocked= */ true); + mService.waitForIdle(); + mTrustManager.reportEnabledTrustAgentsChanged(TEST_VISIBLE_BACKGROUND_USER_ID); + mService.waitForIdle(); + assertThat(mService.isDeviceLockedInner(TEST_VISIBLE_BACKGROUND_USER_ID)).isTrue(); + } + + private void setupVisibleBackgroundUser(boolean visible, boolean unlocked) { + UserInfo info = new UserInfo(TEST_VISIBLE_BACKGROUND_USER_ID, "visible bg user", + UserInfo.FLAG_FULL); + + when(mActivityManager.isUserRunning(TEST_VISIBLE_BACKGROUND_USER_ID)).thenReturn(true); + + when(mLockPatternUtils.isSecure(TEST_VISIBLE_BACKGROUND_USER_ID)).thenReturn(true); + + when(mUserManager.getAliveUsers()).thenReturn(List.of(TEST_USER, info)); + when(mUserManager.getEnabledProfileIds(TEST_VISIBLE_BACKGROUND_USER_ID)).thenReturn( + new int[0]); + when(mUserManager.getUserInfo(TEST_VISIBLE_BACKGROUND_USER_ID)).thenReturn(info); + when(mUserManager.isUserUnlocked(TEST_VISIBLE_BACKGROUND_USER_ID)).thenReturn(unlocked); + when(mUserManager.isVisibleBackgroundUsersSupported()).thenReturn(true); + + LocalServices.removeServiceForTest(UserManagerInternal.class); + LocalServices.addService(UserManagerInternal.class, mUserManagerInternal); + when(mUserManagerInternal.isVisibleBackgroundFullUser( + TEST_VISIBLE_BACKGROUND_USER_ID)).thenReturn(visible); + } + private void setUpRenewableTrust(ITrustAgentService trustAgent) throws RemoteException { ITrustAgentServiceCallback callback = getCallback(trustAgent); callback.setManagingTrust(true); diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java index 15ae4634b573..0b762df86df9 100644 --- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java @@ -290,7 +290,7 @@ public class WallpaperManagerServiceTests { final WallpaperData fallbackData = mService.mFallbackWallpaper; assertEquals("Fallback wallpaper component should be ImageWallpaper.", - sImageWallpaperComponentName, fallbackData.wallpaperComponent); + sImageWallpaperComponentName, fallbackData.getComponent()); verifyLastWallpaperData(USER_SYSTEM, sDefaultWallpaperComponent); verifyDisplayData(); @@ -580,7 +580,7 @@ public class WallpaperManagerServiceTests { final WallpaperData lastData = mService.mLastWallpaper; assertNotNull("Last wallpaper must not be null", lastData); assertEquals("Last wallpaper component must be equals.", expectedComponent, - lastData.wallpaperComponent); + lastData.getComponent()); assertEquals("The user id in last wallpaper should be the last switched user", lastUserId, lastData.userId); assertNotNull("Must exist user data connection on last wallpaper data", diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java index 44aa868716eb..a55aa2364aa5 100644 --- a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java +++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java @@ -30,7 +30,6 @@ import android.graphics.fonts.SystemFonts; import android.os.FileUtils; import android.os.ParcelFileDescriptor; import android.platform.test.annotations.Presubmit; -import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.system.Os; @@ -41,8 +40,6 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.text.flags.Flags; - import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -1106,7 +1103,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void signatureMissingCase_fontFamilyInstalled_fontFamilyInstallLater() { // Install font families, foo.ttf, bar.ttf. installTestFontFamilies(1 /* version */); @@ -1126,7 +1122,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void signatureMissingCase_fontFamilyInstalled_fontInstallLater() { // Install font families, foo.ttf, bar.ttf. installTestFontFamilies(1); @@ -1146,7 +1141,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void signatureMissingCase_fontFileInstalled_fontFamilyInstallLater() { // Install font file, foo.ttf and bar.ttf installTestFontFile(2 /* numFonts */, 1 /* version */); @@ -1166,7 +1160,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void signatureMissingCase_fontFileInstalled_fontFileInstallLater() { // Install font file, foo.ttf and bar.ttf installTestFontFile(2 /* numFonts */, 1 /* version */); @@ -1186,7 +1179,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void signatureAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() { // Install font families, foo.ttf, bar.ttf. installTestFontFamilies(1 /* version */); @@ -1206,7 +1198,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void signatureAllMissingCase_fontFamilyInstalled_fontInstallLater() { // Install font families, foo.ttf, bar.ttf. installTestFontFamilies(1 /* version */); @@ -1226,7 +1217,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void signatureAllMissingCase_fontFileInstalled_fontFamilyInstallLater() { // Install font file, foo.ttf installTestFontFile(1 /* numFonts */, 1 /* version */); @@ -1246,7 +1236,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void signatureAllMissingCase_fontFileInstalled_fontFileInstallLater() { // Install font file, foo.ttf installTestFontFile(1 /* numFonts */, 1 /* version */); @@ -1266,7 +1255,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void fontMissingCase_fontFamilyInstalled_fontFamilyInstallLater() { // Install font families, foo.ttf, bar.ttf. installTestFontFamilies(1 /* version */); @@ -1286,7 +1274,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void fontMissingCase_fontFamilyInstalled_fontInstallLater() { // Install font families, foo.ttf, bar.ttf. installTestFontFamilies(1); @@ -1306,7 +1293,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void fontMissingCase_fontFileInstalled_fontFamilyInstallLater() { // Install font file, foo.ttf and bar.ttf installTestFontFile(2 /* numFonts */, 1 /* version */); @@ -1326,7 +1312,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void fontMissingCase_fontFileInstalled_fontFileInstallLater() { // Install font file, foo.ttf and bar.ttf installTestFontFile(2 /* numFonts */, 1 /* version */); @@ -1346,7 +1331,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void fontAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() { // Install font families, foo.ttf, bar.ttf. installTestFontFamilies(1 /* version */); @@ -1366,7 +1350,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void fontAllMissingCase_fontFamilyInstalled_fontInstallLater() { // Install font families, foo.ttf, bar.ttf. installTestFontFamilies(1 /* version */); @@ -1386,7 +1369,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void fontAllMissingCase_fontFileInstalled_fontFamilyInstallLater() { // Install font file, foo.ttf installTestFontFile(1 /* numFonts */, 1 /* version */); @@ -1406,7 +1388,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void fontAllMissingCase_fontFileInstalled_fontFileInstallLater() { // Install font file, foo.ttf installTestFontFile(1 /* numFonts */, 1 /* version */); @@ -1426,7 +1407,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void fontDirAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() { // Install font families, foo.ttf, bar.ttf. installTestFontFamilies(1 /* version */); @@ -1446,7 +1426,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void fontDirAllMissingCase_fontFamilyInstalled_fontInstallLater() { // Install font families, foo.ttf, bar.ttf. installTestFontFamilies(1 /* version */); @@ -1466,7 +1445,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void fontDirAllMissingCase_fontFileInstalled_fontFamilyInstallLater() { // Install font file, foo.ttf installTestFontFile(1 /* numFonts */, 1 /* version */); @@ -1486,7 +1464,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void fontDirAllMissingCase_fontFileInstalled_fontFileInstallLater() { // Install font file, foo.ttf installTestFontFile(1 /* numFonts */, 1 /* version */); @@ -1506,7 +1483,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void dirContentAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() { // Install font families, foo.ttf, bar.ttf. installTestFontFamilies(1 /* version */); @@ -1527,7 +1503,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void dirContentAllMissingCase_fontFamilyInstalled_fontInstallLater() { // Install font families, foo.ttf, bar.ttf. installTestFontFamilies(1 /* version */); @@ -1548,7 +1523,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void dirContentAllMissingCase_fontFileInstalled_fontFamilyInstallLater() { // Install font file, foo.ttf installTestFontFile(1 /* numFonts */, 1 /* version */); @@ -1569,7 +1543,6 @@ public final class UpdatableFontDirTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_FIX_FONT_UPDATE_FAILURE) public void dirContentAllMissingCase_fontFileInstalled_fontFileInstallLater() { // Install font file, foo.ttf installTestFontFile(1 /* numFonts */, 1 /* version */); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java index 95a7f4b6c80f..a0005d968e31 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -25,6 +25,7 @@ import static com.android.server.hdmi.HdmiCecLocalDevicePlayback.POPUP_AFTER_ACT import static com.android.server.hdmi.HdmiCecLocalDevicePlayback.STANDBY_AFTER_ACTIVE_SOURCE_LOST_DELAY_MS; import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_BOOT_UP; import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC; +import static com.android.server.hdmi.PowerStatusMonitorActionFromPlayback.MONITORING_INTERVAL_MS; import static com.google.common.truth.Truth.assertThat; @@ -145,6 +146,11 @@ public class HdmiCecLocalDevicePlaybackTest { protected void sendBroadcastAsUser(@RequiresPermission Intent intent) { // do nothing } + + @Override + protected boolean isHdmiControlEnhancedBehaviorFlagEnabled() { + return true; + } }; mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context)); @@ -2556,6 +2562,44 @@ public class HdmiCecLocalDevicePlaybackTest { assertThat(mNativeWrapper.getResultMessages()).doesNotContain(unexpectedMessage); } + @Test + public void powerStatusMonitorActionFromPlayback_TvReportPowerOff_goToSleep() { + mHdmiControlService.onWakeUp(HdmiControlService.WAKE_UP_SCREEN_ON); + mTestLooper.dispatchAll(); + + assertThat(mHdmiCecLocalDevicePlayback.getActions( + PowerStatusMonitorActionFromPlayback.class)).hasSize(1); + assertThat(mPowerManager.isInteractive()).isTrue(); + mNativeWrapper.clearResultMessages(); + mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); + mTestLooper.dispatchAll(); + + HdmiCecMessage givePowerStatus = + HdmiCecMessageBuilder.buildGiveDevicePowerStatus(mPlaybackLogicalAddress, + Constants.ADDR_TV); + HdmiCecMessage reportPowerStatusTvOn = + HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV, mPlaybackLogicalAddress, + HdmiControlManager.POWER_STATUS_ON); + HdmiCecMessage reportPowerStatusTvStandby = + HdmiCecMessageBuilder.buildReportPowerStatus(ADDR_TV, mPlaybackLogicalAddress, + HdmiControlManager.POWER_STATUS_STANDBY); + + assertThat(mNativeWrapper.getResultMessages().contains(givePowerStatus)).isTrue(); + mNativeWrapper.onCecMessage(reportPowerStatusTvOn); + mTestLooper.dispatchAll(); + + assertThat(mPowerManager.isInteractive()).isTrue(); + mNativeWrapper.clearResultMessages(); + mTestLooper.moveTimeForward(MONITORING_INTERVAL_MS); + mTestLooper.dispatchAll(); + + assertThat(mNativeWrapper.getResultMessages().contains(givePowerStatus)).isTrue(); + mNativeWrapper.onCecMessage(reportPowerStatusTvStandby); + mTestLooper.dispatchAll(); + + assertThat(mPowerManager.isInteractive()).isFalse(); + } + private void skipActiveSourceLostUi(long idleDuration) { mTestLooper.moveTimeForward(POPUP_AFTER_ACTIVE_SOURCE_LOST_DELAY_MS); mTestLooper.dispatchAll(); 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 689b241f0faa..abc9ce3fdc36 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 @@ -50,11 +50,12 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.testng.Assert.assertThrows; +import android.annotation.SuppressLint; import android.app.ActivityManagerInternal; import android.app.ActivityOptions.LaunchCookie; +import android.app.AppOpsManager; import android.app.KeyguardManager; import android.content.Context; -import android.content.ContextWrapper; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.ApplicationInfoFlags; @@ -72,6 +73,7 @@ import android.os.test.TestLooper; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; +import android.testing.TestableContext; import android.view.ContentRecordingSession; import android.view.ContentRecordingSession.RecordContent; @@ -99,13 +101,14 @@ import java.util.concurrent.TimeUnit; /** * Tests for the {@link MediaProjectionManagerService} class. - * + * <p> * Build/Install/Run: * atest FrameworksServicesTests:MediaProjectionManagerServiceTest */ @SmallTest @Presubmit @RunWith(AndroidJUnit4.class) +@SuppressLint({"UseCheckPermission", "VisibleForTests", "MissingPermission"}) public class MediaProjectionManagerServiceTest { private static final int UID = 10; private static final String PACKAGE_NAME = "test.package"; @@ -151,7 +154,10 @@ public class MediaProjectionManagerServiceTest { } }; - private Context mContext; + @Rule + public final TestableContext mContext = spy( + new TestableContext(InstrumentationRegistry.getInstrumentation().getContext())); + private MediaProjectionManagerService mService; private OffsettableClock mClock; private ContentRecordingSession mWaitingDisplaySession = @@ -169,6 +175,8 @@ public class MediaProjectionManagerServiceTest { @Mock private KeyguardManager mKeyguardManager; @Mock + AppOpsManager mAppOpsManager; + @Mock private IMediaProjectionWatcherCallback mWatcherCallback; @Mock private MediaProjectionMetricsLogger mMediaProjectionMetricsLogger; @@ -185,10 +193,9 @@ public class MediaProjectionManagerServiceTest { LocalServices.removeServiceForTest(WindowManagerInternal.class); LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal); - mContext = spy(new ContextWrapper( - InstrumentationRegistry.getInstrumentation().getTargetContext())); - doReturn(mPackageManager).when(mContext).getPackageManager(); - doReturn(mKeyguardManager).when(mContext).getSystemService(eq(Context.KEYGUARD_SERVICE)); + mContext.addMockSystemService(AppOpsManager.class, mAppOpsManager); + mContext.addMockSystemService(KeyguardManager.class, mKeyguardManager); + mContext.setMockPackageManager(mPackageManager); mClock = new OffsettableClock.Stopped(); mWaitingDisplaySession.setWaitingForConsent(true); @@ -291,6 +298,27 @@ public class MediaProjectionManagerServiceTest { assertThat(mService.getActiveProjectionInfo()).isNotNull(); } + @SuppressLint("MissingPermission") + @EnableFlags(android.companion.virtualdevice.flags + .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) + @Test + public void testCreateProjection_keyguardLocked_AppOpMediaProjection() + throws NameNotFoundException { + MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions(); + doReturn(true).when(mAppOpsManager).isOperationActive(eq(AppOpsManager.OP_PROJECT_MEDIA), + eq(projection.uid), eq(projection.packageName)); + 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. + assertThat(mService.getActiveProjectionInfo()).isNotNull(); + } + @Test public void testCreateProjection_attemptReuse_noPriorProjectionGrant() throws NameNotFoundException { diff --git a/services/tests/servicestests/src/com/android/server/supervision/OWNERS b/services/tests/servicestests/src/com/android/server/supervision/OWNERS new file mode 100644 index 000000000000..a5de8007cfda --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/supervision/OWNERS @@ -0,0 +1 @@ +include /services/supervision/OWNERS
\ No newline at end of file diff --git a/services/tests/uiservicestests/src/com/android/server/notification/VibratorHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/VibratorHelperTest.java index 4d2396c78d16..65b4ac116b34 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/VibratorHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/VibratorHelperTest.java @@ -104,6 +104,12 @@ public class VibratorHelperTest extends UiServiceTestCase { } @Test + public void createVibrationEffectFromSoundUri_opaqueUri() { + Uri uri = Uri.parse("a:b#c"); + assertNull(mVibratorHelper.createVibrationEffectFromSoundUri(uri)); + } + + @Test public void createVibrationEffectFromSoundUri_uriWithoutRequiredQueryParameter() { Uri uri = Settings.System.DEFAULT_NOTIFICATION_URI; assertNull(mVibratorHelper.createVibrationEffectFromSoundUri(uri)); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java index efcf027a0b90..84c4f620f394 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java @@ -32,6 +32,7 @@ import static android.service.notification.Condition.STATE_FALSE; import static android.service.notification.Condition.STATE_TRUE; import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON; import static android.service.notification.ZenModeConfig.XML_VERSION_MODES_API; +import static android.service.notification.ZenModeConfig.XML_VERSION_MODES_UI; import static android.service.notification.ZenModeConfig.ZEN_TAG; import static android.service.notification.ZenModeConfig.ZenRule.OVERRIDE_DEACTIVATE; import static android.service.notification.ZenModeConfig.ZenRule.OVERRIDE_NONE; @@ -1169,6 +1170,23 @@ public class ZenModeConfigTest extends UiServiceTestCase { assertThat(suppressedEffectsOf(result)).isEqualTo(suppressedEffectsOf(policy)); } + @Test + public void readXml_fixesWronglyDisabledManualRule() throws Exception { + ZenModeConfig config = getCustomConfig(); + if (!Flags.modesUi()) { + config.manualRule = new ZenModeConfig.ZenRule(); + config.manualRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; + } + config.manualRule.enabled = false; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + writeConfigXml(config, XML_VERSION_MODES_UI, /* forBackup= */ false, baos); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ZenModeConfig fromXml = readConfigXml(bais); + + assertThat(fromXml.manualRule.enabled).isTrue(); + } + private static String suppressedEffectsOf(Policy policy) { return suppressedEffectsToString(policy.suppressedVisualEffects) + "(" + policy.suppressedVisualEffects + ")"; @@ -1274,7 +1292,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { out.setOutput(new BufferedOutputStream(os), "utf-8"); out.startDocument(null, true); out.startTag(null, tag); - ZenModeConfig.writeRuleXml(rule, out); + ZenModeConfig.writeRuleXml(rule, out, /* forBackup= */ false); out.endTag(null, tag); out.endDocument(); } 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 39a9d30e7a92..9b87947b6980 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -6923,6 +6923,75 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertThat(eventsRule.triggerDescription).isNotEmpty(); } + @Test + @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI}) + public void setAutomaticZenRuleState_withManualActivation_activeOnReboot() + throws Exception { + AutomaticZenRule rule = new AutomaticZenRule.Builder("Rule", Uri.parse("cond")) + .setPackage(mPkg) + .build(); + String ruleId = mZenModeHelper.addAutomaticZenRule(mPkg, rule, ORIGIN_APP, "adding", + CUSTOM_PKG_UID); + mZenModeHelper.setAutomaticZenRuleState(ruleId, + new Condition(rule.getConditionId(), "manual-on", STATE_TRUE, SOURCE_USER_ACTION), + ORIGIN_USER_IN_SYSTEMUI, SYSTEM_UID); + assertThat(mZenModeHelper.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); + ZenRule zenRule = mZenModeHelper.mConfig.automaticRules.get(ruleId); + assertThat(zenRule.getConditionOverride()).isEqualTo(OVERRIDE_ACTIVATE); + assertThat(zenRule.condition).isNull(); + + ByteArrayOutputStream xmlBytes = writeXmlAndPurge(ZenModeConfig.XML_VERSION_MODES_UI); + zenRule = mZenModeHelper.mConfig.automaticRules.get(ruleId); + assertThat(zenRule).isNull(); + + // Now simulate a reboot -> reload the configuration after purging. + TypedXmlPullParser parser = getParserForByteStream(xmlBytes); + mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL); + + if (Flags.modesUi()) { + assertThat(mZenModeHelper.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); + zenRule = mZenModeHelper.mConfig.automaticRules.get(ruleId); + assertThat(zenRule.getConditionOverride()).isEqualTo(OVERRIDE_ACTIVATE); + assertThat(zenRule.condition).isNull(); + } else { + assertThat(mZenModeHelper.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); + } + } + + @Test + @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI}) + public void setAutomaticZenRuleState_withManualDeactivation_clearedOnReboot() + throws Exception { + AutomaticZenRule rule = new AutomaticZenRule.Builder("Rule", Uri.parse("cond")) + .setPackage(mPkg) + .build(); + String ruleId = mZenModeHelper.addAutomaticZenRule(mPkg, rule, ORIGIN_APP, "adding", + CUSTOM_PKG_UID); + mZenModeHelper.setAutomaticZenRuleState(ruleId, + new Condition(rule.getConditionId(), "auto-on", STATE_TRUE, SOURCE_CONTEXT), + ORIGIN_APP, CUSTOM_PKG_UID); + mZenModeHelper.setAutomaticZenRuleState(ruleId, + new Condition(rule.getConditionId(), "snooze", STATE_FALSE, SOURCE_USER_ACTION), + ORIGIN_USER_IN_SYSTEMUI, SYSTEM_UID); + assertThat(mZenModeHelper.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); + ZenRule zenRule = mZenModeHelper.mConfig.automaticRules.get(ruleId); + assertThat(zenRule.getConditionOverride()).isEqualTo(OVERRIDE_DEACTIVATE); + assertThat(zenRule.condition).isNotNull(); + + ByteArrayOutputStream xmlBytes = writeXmlAndPurge(ZenModeConfig.XML_VERSION_MODES_UI); + zenRule = mZenModeHelper.mConfig.automaticRules.get(ruleId); + assertThat(zenRule).isNull(); + + // Now simulate a reboot -> reload the configuration after purging. + TypedXmlPullParser parser = getParserForByteStream(xmlBytes); + mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL); + + assertThat(mZenModeHelper.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); + zenRule = mZenModeHelper.mConfig.automaticRules.get(ruleId); + assertThat(zenRule.getConditionOverride()).isEqualTo(OVERRIDE_NONE); + assertThat(zenRule.condition).isNotNull(); + } + private static void addZenRule(ZenModeConfig config, String id, String ownerPkg, int zenMode, @Nullable ZenPolicy zenPolicy) { ZenRule rule = new ZenRule(); diff --git a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java index 6076d3318c40..f7127df0ee33 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java @@ -18,6 +18,7 @@ package com.android.server.vibrator; import static android.os.VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY; import static android.os.VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF; +import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK; import static android.os.VibrationAttributes.USAGE_IME_FEEDBACK; import static android.os.VibrationAttributes.USAGE_TOUCH; import static android.os.VibrationEffect.Composition.PRIMITIVE_CLICK; @@ -105,7 +106,7 @@ public class HapticFeedbackVibrationProviderTest { @Before public void setUp() { - mSetFlagsRule.enableFlags(FLAG_HAPTIC_FEEDBACK_INPUT_SOURCE_CUSTOMIZATION_ENABLED); + mSetFlagsRule.disableFlags(FLAG_HAPTIC_FEEDBACK_INPUT_SOURCE_CUSTOMIZATION_ENABLED); } @Test @@ -398,7 +399,7 @@ public class HapticFeedbackVibrationProviderTest { HapticFeedbackVibrationProvider provider = createProviderWithoutCustomizations(); for (int effectId : BIOMETRIC_FEEDBACK_CONSTANTS) { - VibrationAttributes attrs = provider.getVibrationAttributesForHapticFeedback( + VibrationAttributes attrs = provider.getVibrationAttributes( effectId, /* flags */ 0, /* privFlags */ 0); assertThat(attrs.getUsage()).isEqualTo(VibrationAttributes.USAGE_COMMUNICATION_REQUEST); } @@ -408,7 +409,7 @@ public class HapticFeedbackVibrationProviderTest { public void testVibrationAttribute_forNotBypassingIntensitySettings() { HapticFeedbackVibrationProvider provider = createProviderWithoutCustomizations(); - VibrationAttributes attrs = provider.getVibrationAttributesForHapticFeedback( + VibrationAttributes attrs = provider.getVibrationAttributes( SAFE_MODE_ENABLED, /* flags */ 0, /* privFlags */ 0); assertThat(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)).isFalse(); @@ -418,7 +419,7 @@ public class HapticFeedbackVibrationProviderTest { public void testVibrationAttribute_forByassingIntensitySettings() { HapticFeedbackVibrationProvider provider = createProviderWithoutCustomizations(); - VibrationAttributes attrs = provider.getVibrationAttributesForHapticFeedback( + VibrationAttributes attrs = provider.getVibrationAttributes( SAFE_MODE_ENABLED, /* flags */ HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING, /* privFlags */ 0); @@ -431,7 +432,7 @@ public class HapticFeedbackVibrationProviderTest { HapticFeedbackVibrationProvider provider = createProviderWithoutCustomizations(); for (int effectId : SCROLL_FEEDBACK_CONSTANTS) { - VibrationAttributes attrs = provider.getVibrationAttributesForHapticFeedback( + VibrationAttributes attrs = provider.getVibrationAttributes( effectId, /* flags */ 0, /* privFlags */ 0); assertWithMessage("Expected FLAG_BYPASS_INTERRUPTION_POLICY for effect " + effectId) .that(attrs.isFlagSet(FLAG_BYPASS_INTERRUPTION_POLICY)).isTrue(); @@ -444,7 +445,7 @@ public class HapticFeedbackVibrationProviderTest { HapticFeedbackVibrationProvider provider = createProviderWithoutCustomizations(); for (int effectId : SCROLL_FEEDBACK_CONSTANTS) { - VibrationAttributes attrs = provider.getVibrationAttributesForHapticFeedback( + VibrationAttributes attrs = provider.getVibrationAttributes( effectId, /* flags */ 0, /* privFlags */ 0); assertWithMessage("Expected no FLAG_BYPASS_INTERRUPTION_POLICY for effect " + effectId) .that(attrs.isFlagSet(FLAG_BYPASS_INTERRUPTION_POLICY)).isFalse(); @@ -452,11 +453,64 @@ public class HapticFeedbackVibrationProviderTest { } @Test + public void testVibrationAttribute_scrollFeedback_inputCustomizedFlag_useTouchUsage() { + mSetFlagsRule.enableFlags(FLAG_HAPTIC_FEEDBACK_INPUT_SOURCE_CUSTOMIZATION_ENABLED); + HapticFeedbackVibrationProvider provider = createProviderWithoutCustomizations(); + + for (int effectId : SCROLL_FEEDBACK_CONSTANTS) { + VibrationAttributes attrs = provider.getVibrationAttributes(effectId, /* flags */ + 0, /* privFlags */ 0); + assertWithMessage("Expected USAGE_TOUCH for scroll effect " + effectId + + ", if no input customization").that(attrs.getUsage()).isEqualTo(USAGE_TOUCH); + } + } + + @Test + public void testVibrationAttribute_scrollFeedback_noInputCustomizedFlag_useHardwareFeedback() { + HapticFeedbackVibrationProvider provider = createProviderWithoutCustomizations(); + + for (int effectId : SCROLL_FEEDBACK_CONSTANTS) { + VibrationAttributes attrs = provider.getVibrationAttributes(effectId, /* flags */ + 0, /* privFlags */ 0); + assertWithMessage("Expected USAGE_HARDWARE_FEEDBACK for scroll effect " + effectId + + ", if no input customization").that(attrs.getUsage()).isEqualTo( + USAGE_HARDWARE_FEEDBACK); + } + } + + @Test + public void testVibrationAttribute_scrollFeedback_rotaryInputSource_useHardwareFeedback() { + mSetFlagsRule.enableFlags(FLAG_HAPTIC_FEEDBACK_INPUT_SOURCE_CUSTOMIZATION_ENABLED); + HapticFeedbackVibrationProvider provider = createProviderWithoutCustomizations(); + + for (int effectId : SCROLL_FEEDBACK_CONSTANTS) { + VibrationAttributes attrs = provider.getVibrationAttributes( + effectId, InputDevice.SOURCE_ROTARY_ENCODER, /* flags */ 0, /* privFlags */ 0); + assertWithMessage( + "Expected USAGE_HARDWARE_FEEDBACK for input source SOURCE_ROTARY_ENCODER").that( + attrs.getUsage()).isEqualTo(USAGE_HARDWARE_FEEDBACK); + } + } + + @Test + public void testVibrationAttribute_scrollFeedback_touchInputSource_useTouchUsage() { + mSetFlagsRule.enableFlags(FLAG_HAPTIC_FEEDBACK_INPUT_SOURCE_CUSTOMIZATION_ENABLED); + HapticFeedbackVibrationProvider provider = createProviderWithoutCustomizations(); + + for (int effectId : SCROLL_FEEDBACK_CONSTANTS) { + VibrationAttributes attrs = provider.getVibrationAttributes( + effectId, InputDevice.SOURCE_TOUCHSCREEN, /* flags */ 0, /* privFlags */ 0); + assertWithMessage("Expected USAGE_TOUCH for input source SOURCE_TOUCHSCREEN").that( + attrs.getUsage()).isEqualTo(USAGE_TOUCH); + } + } + + @Test public void testVibrationAttribute_notIme_useTouchUsage() { HapticFeedbackVibrationProvider provider = createProviderWithoutCustomizations(); for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { - VibrationAttributes attrs = provider.getVibrationAttributesForHapticFeedback( + VibrationAttributes attrs = provider.getVibrationAttributes( effectId, /* flags */ 0, /* privFlags */ 0); assertWithMessage("Expected USAGE_TOUCH for effect " + effectId) .that(attrs.getUsage()).isEqualTo(USAGE_TOUCH); @@ -468,7 +522,7 @@ public class HapticFeedbackVibrationProviderTest { HapticFeedbackVibrationProvider provider = createProviderWithoutCustomizations(); for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) { - VibrationAttributes attrs = provider.getVibrationAttributesForHapticFeedback( + VibrationAttributes attrs = provider.getVibrationAttributes( effectId, /* flags */ 0, HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS); assertWithMessage("Expected USAGE_IME_FEEDBACK for effect " + effectId) diff --git a/services/tests/wmtests/src/com/android/server/policy/MetaKeyEventsInterceptionTests.java b/services/tests/wmtests/src/com/android/server/policy/MetaKeyEventsInterceptionTests.java deleted file mode 100644 index b979335233e3..000000000000 --- a/services/tests/wmtests/src/com/android/server/policy/MetaKeyEventsInterceptionTests.java +++ /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.server.policy; - -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS; - -import static com.google.common.truth.Truth.assertThat; - -import android.view.KeyEvent; -import android.view.WindowManager; - -import androidx.test.filters.SmallTest; - -import com.android.internal.policy.KeyInterceptionInfo; - -import org.junit.Before; -import org.junit.Test; - -import java.util.Arrays; -import java.util.List; - -/** - * Testing {@link PhoneWindowManager} functionality of letting app intercepting key events - * containing META. - */ -@SmallTest -public class MetaKeyEventsInterceptionTests extends ShortcutKeyTestBase { - - private static final List<KeyEvent> META_KEY_EVENTS = Arrays.asList( - new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_META_LEFT), - new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_META_RIGHT), - new KeyEvent(/* downTime= */ 0, /* eventTime= */ - 0, /* action= */ 0, /* code= */ 0, /* repeat= */ 0, - /* metaState= */ KeyEvent.META_META_ON)); - - @Before - public void setUp() { - setUpPhoneWindowManager(); - } - - @Test - public void doesntInterceptMetaKeyEvents_whenWindowAskedForIt() { - mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(/* granted= */ true); - setWindowKeyInterceptionWithPrivateFlags(PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS); - - META_KEY_EVENTS.forEach(keyEvent -> { - assertKeyInterceptionResult(keyEvent, /* intercepted= */ false); - }); - } - - @Test - public void interceptsMetaKeyEvents_whenWindowDoesntHaveFlagSet() { - mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(/* granted= */ true); - setWindowKeyInterceptionWithPrivateFlags(0); - - META_KEY_EVENTS.forEach(keyEvent -> { - assertKeyInterceptionResult(keyEvent, /* intercepted= */ true); - }); - } - - @Test - public void interceptsMetaKeyEvents_whenWindowDoesntHavePermission() { - mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(/* granted= */ false); - setWindowKeyInterceptionWithPrivateFlags(PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS); - - META_KEY_EVENTS.forEach(keyEvent -> { - assertKeyInterceptionResult(keyEvent, /* intercepted= */ true); - }); - } - - private void setWindowKeyInterceptionWithPrivateFlags(int privateFlags) { - KeyInterceptionInfo info = new KeyInterceptionInfo( - WindowManager.LayoutParams.TYPE_APPLICATION, privateFlags, "title", 0); - mPhoneWindowManager.overrideWindowKeyInterceptionInfo(info); - } - - private void assertKeyInterceptionResult(KeyEvent keyEvent, boolean intercepted) { - long result = mPhoneWindowManager.interceptKeyBeforeDispatching(keyEvent); - int expected = intercepted ? -1 : 0; - assertThat(result).isEqualTo(expected); - } -} diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java index 0b55e2b9313e..98401b33840f 100644 --- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java +++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java @@ -52,7 +52,6 @@ import static org.mockito.Mockito.after; import static org.mockito.Mockito.description; import static org.mockito.Mockito.mockingDetails; import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; import android.app.ActivityManagerInternal; @@ -634,10 +633,6 @@ class TestPhoneWindowManager { .when(mButtonOverridePermissionChecker).canAppOverrideSystemKey(any(), anyInt()); } - void overrideWindowKeyInterceptionInfo(KeyInterceptionInfo info) { - when(mWindowManagerInternal.getKeyInterceptionInfoFromToken(any())).thenReturn(info); - } - void overrideKeyEventPolicyFlags(int flags) { mKeyEventPolicyFlags = flags; } 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 f74340113a04..7bce8285972c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -1640,7 +1640,7 @@ public class SizeCompatTests extends WindowTestsBase { .build(); setUpApp(display); prepareUnresizable(mActivity, /* maxAspect */ 0f, SCREEN_ORIENTATION_PORTRAIT); - mActivity.setWindowingMode(WINDOWING_MODE_FREEFORM); + mTask.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FREEFORM); assertFalse(mActivity.inSizeCompatMode()); // Resize app to make original app bounds larger than parent bounds. @@ -1667,7 +1667,7 @@ public class SizeCompatTests extends WindowTestsBase { .build(); setUpApp(display); prepareUnresizable(mActivity, /* maxAspect */ 0f, SCREEN_ORIENTATION_PORTRAIT); - mActivity.setWindowingMode(WINDOWING_MODE_FREEFORM); + mTask.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FREEFORM); assertFalse(mActivity.inSizeCompatMode()); // Resize app to make original app bounds smaller than parent bounds. @@ -1692,7 +1692,7 @@ public class SizeCompatTests extends WindowTestsBase { .build(); setUpApp(display); prepareUnresizable(mActivity, /* maxAspect */ 0f, SCREEN_ORIENTATION_PORTRAIT); - mActivity.setWindowingMode(WINDOWING_MODE_FREEFORM); + mTask.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FREEFORM); assertFalse(mActivity.inSizeCompatMode()); final Rect originalAppBounds = mActivity.getBounds(); @@ -1705,6 +1705,38 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(originalAppBounds, mActivity.getBounds()); } + /** + * Test that when desktop mode is enabled, a freeform unresizeable activity is not up-scaled + * when exiting freeform despite its larger parent bounds. + */ + @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) + public void testCompatScaling_freeformUnresizeableApp_exitFreeform_notScaled() { + doReturn(true).when(() -> + DesktopModeHelper.canEnterDesktopMode(any())); + final int dw = 600; + final int dh = 800; + final DisplayContent display = new TestDisplayContent.Builder(mAtm, dw, dh) + .setWindowingMode(WINDOWING_MODE_FREEFORM) + .build(); + setUpApp(display); + prepareUnresizable(mActivity, /* maxAspect */ 0f, SCREEN_ORIENTATION_PORTRAIT); + mTask.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FREEFORM); + final Rect originalAppBounds = mActivity.getBounds(); + + assertFalse(mActivity.inSizeCompatMode()); + + // Resize app to make original app bounds smaller than parent bounds. + mTask.getWindowConfiguration().setAppBounds( + new Rect(0, 0, dw + 300, dh + 400)); + // Change windowing mode from freeform to fullscreen + mTask.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FULLSCREEN); + mActivity.onConfigurationChanged(mTask.getConfiguration()); + // App should enter size compat mode but remain its original size. + assertTrue(mActivity.inSizeCompatMode()); + assertEquals(originalAppBounds, mActivity.getBounds()); + } + @Test public void testGetLetterboxInnerBounds_noScalingApplied() { // Set up a display in portrait and ignoring orientation request. diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java index b80610a76cc8..4ccbc32c4b54 100644 --- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java @@ -816,7 +816,8 @@ public final class TelephonyPermissions { * @param callingUid pass Binder.callingUid(). */ public static void enforceShellOnly(int callingUid, String message) { - if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) { + if (UserHandle.isSameApp(callingUid, Process.SHELL_UID) + || UserHandle.isSameApp(callingUid, Process.ROOT_UID)) { return; // okay } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 41223db750c0..2ef057350033 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -5038,7 +5038,7 @@ public class CarrierConfigManager { * {@code true} - Enable NI SUPL message injection. */ @FlaggedApi(android.location.flags.Flags - .FLAG_ENABLE_NI_SUPL_MESSAGE_INJECTION_BY_CARRIER_CONFIG) + .FLAG_ENABLE_NI_SUPL_MESSAGE_INJECTION_BY_CARRIER_CONFIG_BUGFIX) public static final String KEY_ENABLE_NI_SUPL_MESSAGE_INJECTION_BOOL = KEY_PREFIX + "enable_ni_supl_message_injection_bool"; @@ -5059,7 +5059,7 @@ public class CarrierConfigManager { defaults.putInt(KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT, SUPL_EMERGENCY_MODE_TYPE_CP_ONLY); defaults.putStringArray(KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY, null); - if (android.location.flags.Flags.enableNiSuplMessageInjectionByCarrierConfig()) { + if (android.location.flags.Flags.enableNiSuplMessageInjectionByCarrierConfigBugfix()) { defaults.putBoolean(KEY_ENABLE_NI_SUPL_MESSAGE_INJECTION_BOOL, false); } return defaults; diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 51e0c33ff705..6faef7ecfa1b 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -3785,7 +3785,7 @@ public class SubscriptionManager { } private boolean isSystemProcess() { - return Process.myUid() == Process.SYSTEM_UID; + return UserHandle.isSameApp(Process.myUid(), Process.SYSTEM_UID); } /** 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 92b6b934874f..82e53c81daaa 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 @@ -54,7 +54,7 @@ class ShowImeOnUnlockScreenTest(flicker: LegacyFlickerTest) : BaseTest(flicker) } transitions { device.sleep() - wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify() + wmHelper.StateSyncBuilder().withKeyguardShowing().waitForAndVerify() UnlockScreenRule.unlockScreen(device) wmHelper.StateSyncBuilder().withImeShown().waitForAndVerify() } diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/StartMediaProjectionAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/StartMediaProjectionAppHelper.kt new file mode 100644 index 000000000000..69fde0168b14 --- /dev/null +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/StartMediaProjectionAppHelper.kt @@ -0,0 +1,126 @@ +/* + * 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.flicker.helpers + +import android.app.Instrumentation +import android.tools.device.apphelpers.StandardAppHelper +import android.tools.helpers.SYSTEMUI_PACKAGE +import android.tools.traces.component.ComponentNameMatcher +import android.tools.traces.parsers.WindowManagerStateHelper +import android.tools.traces.parsers.toFlickerComponent +import android.util.Log +import androidx.test.uiautomator.By +import androidx.test.uiautomator.BySelector +import androidx.test.uiautomator.UiObject2 +import androidx.test.uiautomator.UiObjectNotFoundException +import androidx.test.uiautomator.UiScrollable +import androidx.test.uiautomator.UiSelector +import androidx.test.uiautomator.Until +import com.android.server.wm.flicker.testapp.ActivityOptions +import java.util.regex.Pattern + +class StartMediaProjectionAppHelper +@JvmOverloads +constructor( + instr: Instrumentation, + launcherName: String = ActivityOptions.StartMediaProjectionActivity.LABEL, + component: ComponentNameMatcher = + ActivityOptions.StartMediaProjectionActivity.COMPONENT.toFlickerComponent() +) : StandardAppHelper(instr, launcherName, component) { + private val packageManager = instr.context.packageManager + + fun startEntireScreenMediaProjection(wmHelper: WindowManagerStateHelper) { + clickStartMediaProjectionButton() + chooseEntireScreenOption() + startScreenSharing() + wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify() + } + + fun startSingleAppMediaProjection( + wmHelper: WindowManagerStateHelper, + targetApp: StandardAppHelper + ) { + clickStartMediaProjectionButton() + chooseSingleAppOption() + startScreenSharing() + selectTargetApp(targetApp.appName) + wmHelper + .StateSyncBuilder() + .withAppTransitionIdle() + .withWindowSurfaceAppeared(targetApp) + .waitForAndVerify() + } + + private fun clickStartMediaProjectionButton() { + findObject(By.res(packageName, START_MEDIA_PROJECTION_BUTTON_ID)).also { it.click() } + } + + private fun chooseEntireScreenOption() { + findObject(By.res(SCREEN_SHARE_OPTIONS_PATTERN)).also { it.click() } + + val entireScreenString = getSysUiResourceString(ENTIRE_SCREEN_STRING_RES_NAME) + findObject(By.text(entireScreenString)).also { it.click() } + } + + private fun selectTargetApp(targetAppName: String) { + // Scroll to to find target app to launch then click app icon it to start capture + val scrollable = UiScrollable(UiSelector().scrollable(true)) + try { + scrollable.scrollForward() + if (!scrollable.scrollIntoView(UiSelector().text(targetAppName))) { + Log.e(TAG, "Didn't find target app when scrolling") + return + } + } catch (e: UiObjectNotFoundException) { + Log.d(TAG, "There was no scrolling (UI may not be scrollable") + } + + findObject(By.text(targetAppName)).also { it.click() } + } + + private fun chooseSingleAppOption() { + findObject(By.res(SCREEN_SHARE_OPTIONS_PATTERN)).also { it.click() } + + val singleAppString = getSysUiResourceString(SINGLE_APP_STRING_RES_NAME) + findObject(By.text(singleAppString)).also { it.click() } + } + + private fun startScreenSharing() { + findObject(By.res(ACCEPT_RESOURCE_ID)).also { it.click() } + } + + private fun findObject(selector: BySelector): UiObject2 = + uiDevice.wait(Until.findObject(selector), TIMEOUT) ?: error("Can't find object $selector") + + private fun getSysUiResourceString(resName: String): String = + with(packageManager.getResourcesForApplication(SYSTEMUI_PACKAGE)) { + getString(getIdentifier(resName, "string", SYSTEMUI_PACKAGE)) + } + + companion object { + const val TAG: String = "StartMediaProjectionAppHelper" + const val TIMEOUT: Long = 5000L + const val ACCEPT_RESOURCE_ID: String = "android:id/button1" + const val START_MEDIA_PROJECTION_BUTTON_ID: String = "button_start_mp" + val SCREEN_SHARE_OPTIONS_PATTERN: Pattern = + Pattern.compile("$SYSTEMUI_PACKAGE:id/screen_share_mode_(options|spinner)") + const val ENTIRE_SCREEN_STRING_RES_NAME: String = + "screen_share_permission_dialog_option_entire_screen" + const val SINGLE_APP_STRING_RES_NAME: String = + "screen_share_permission_dialog_option_single_app" + } +} diff --git a/tests/FlickerTests/test-apps/flickerapp/Android.bp b/tests/FlickerTests/test-apps/flickerapp/Android.bp index a186679790b6..c55df8604362 100644 --- a/tests/FlickerTests/test-apps/flickerapp/Android.bp +++ b/tests/FlickerTests/test-apps/flickerapp/Android.bp @@ -47,6 +47,7 @@ android_test { "wm-flicker-common-app-helpers", "wm-flicker-common-assertions", "wm-flicker-window-extensions", + "wm-shell-flicker-utils", ], } diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml index 45260bddd355..f891606f0066 100644 --- a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml +++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml @@ -21,6 +21,15 @@ android:targetSdkVersion="35"/> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> + <uses-permission android:name="android.permission.MANAGE_MEDIA_PROJECTION" /> + <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> + <uses-permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"/> + <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> + <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/> + <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION"/> + <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" /> + <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> + <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <application android:allowBackup="false" android:supportsRtl="true"> @@ -106,6 +115,17 @@ <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> + <activity android:name=".StartMediaProjectionActivity" + android:theme="@style/CutoutNever" + android:resizeableActivity="false" + android:taskAffinity="com.android.server.wm.flicker.testapp.StartMediaProjectionActivity" + android:label="StartMediaProjectionActivity" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> <activity android:name=".PortraitImmersiveActivity" android:taskAffinity="com.android.server.wm.flicker.testapp.PortraitImmersiveActivity" android:immersive="true" @@ -404,6 +424,11 @@ android:name="android.voice_interaction" android:resource="@xml/interaction_service"/> </service> + <service android:name="com.android.wm.shell.flicker.utils.MediaProjectionService" + android:foregroundServiceType="mediaProjection" + android:label="WMShellTestsMediaProjectionService" + android:enabled="true"> + </service> </application> <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/> </manifest> diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_start_media_projection.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_start_media_projection.xml new file mode 100644 index 000000000000..46f01e6c9752 --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_start_media_projection.xml @@ -0,0 +1,32 @@ +<?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" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + android:background="@android:color/holo_orange_light"> + + <Button + android:id="@+id/button_start_mp" + android:layout_width="500dp" + android:layout_height="500dp" + android:gravity="center_vertical|center_horizontal" + android:text="Start Media Projection" + android:textAppearance="?android:attr/textAppearanceLarge"/> + +</LinearLayout>
\ No newline at end of file diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java index 80c1dd072df7..e4de2c574553 100644 --- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java @@ -85,6 +85,12 @@ public class ActivityOptions { FLICKER_APP_PACKAGE + ".NonResizeablePortraitActivity"); } + public static class StartMediaProjectionActivity { + public static final String LABEL = "StartMediaProjectionActivity"; + public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE, + FLICKER_APP_PACKAGE + ".StartMediaProjectionActivity"); + } + public static class PortraitImmersiveActivity { public static final String LABEL = "PortraitImmersiveActivity"; public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE, diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/StartMediaProjectionActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/StartMediaProjectionActivity.java new file mode 100644 index 000000000000..a24a48269d7c --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/StartMediaProjectionActivity.java @@ -0,0 +1,156 @@ +/* + * 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.server.wm.flicker.testapp; + +import static com.android.wm.shell.flicker.utils.MediaProjectionUtils.EXTRA_MESSENGER; +import static com.android.wm.shell.flicker.utils.MediaProjectionUtils.MSG_SERVICE_DESTROYED; +import static com.android.wm.shell.flicker.utils.MediaProjectionUtils.MSG_START_FOREGROUND_DONE; +import static com.android.wm.shell.flicker.utils.MediaProjectionUtils.REQUEST_CODE; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Intent; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.hardware.display.VirtualDisplay; +import android.media.ImageReader; +import android.media.projection.MediaProjection; +import android.media.projection.MediaProjectionManager; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Messenger; +import android.util.DisplayMetrics; +import android.util.Log; +import android.widget.Button; + +import com.android.wm.shell.flicker.utils.MediaProjectionService; + +public class StartMediaProjectionActivity extends Activity { + + private static final String TAG = "StartMediaProjectionActivity"; + private MediaProjectionManager mService; + private ImageReader mImageReader; + private VirtualDisplay mVirtualDisplay; + private MediaProjection mMediaProjection; + private MediaProjection.Callback mMediaProjectionCallback = new MediaProjection.Callback() { + @Override + public void onStop() { + super.onStop(); + } + + @Override + public void onCapturedContentResize(int width, int height) { + super.onCapturedContentResize(width, height); + } + + @Override + public void onCapturedContentVisibilityChanged(boolean isVisible) { + super.onCapturedContentVisibilityChanged(isVisible); + } + }; + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + mService = getSystemService(MediaProjectionManager.class); + setContentView(R.layout.activity_start_media_projection); + + Button startMediaProjectionButton = findViewById(R.id.button_start_mp); + startMediaProjectionButton.setOnClickListener(v -> + startActivityForResult(mService.createScreenCaptureIntent(), REQUEST_CODE)); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode != REQUEST_CODE) { + throw new IllegalStateException("Unknown request code: " + requestCode); + } + if (resultCode != RESULT_OK) { + throw new IllegalStateException("User denied screen sharing permission"); + } + Log.d(TAG, "onActivityResult"); + startMediaProjectionService(resultCode, data); + } + + private void startMediaProjectionService(int resultCode, Intent resultData) { + final Messenger messenger = new Messenger(new Handler(Looper.getMainLooper(), + msg -> { + switch (msg.what) { + case MSG_START_FOREGROUND_DONE: + setupMediaProjection(resultCode, resultData); + return true; + case MSG_SERVICE_DESTROYED: + return true; + } + Log.e(TAG, "Unknown message from the FlickerMPService: " + msg.what); + return false; + } + )); + + final Intent intent = new Intent() + .setComponent(new ComponentName(this, MediaProjectionService.class)) + .putExtra(EXTRA_MESSENGER, messenger); + startForegroundService(intent); + } + + private void setupMediaProjection(int resultCode, Intent resultData) { + mMediaProjection = mService.getMediaProjection(resultCode, resultData); + if (mMediaProjection == null) { + throw new IllegalStateException("cannot create new MediaProjection"); + } + + mMediaProjection.registerCallback( + mMediaProjectionCallback, new Handler(Looper.getMainLooper())); + + Rect displayBounds = getWindowManager().getMaximumWindowMetrics().getBounds(); + mImageReader = ImageReader.newInstance( + displayBounds.width(), displayBounds.height(), PixelFormat.RGBA_8888, 1); + + mVirtualDisplay = mMediaProjection.createVirtualDisplay( + "DanielDisplay", + displayBounds.width(), + displayBounds.height(), + DisplayMetrics.DENSITY_HIGH, + /* flags= */ 0, + mImageReader.getSurface(), + new VirtualDisplay.Callback() { + @Override + public void onStopped() { + if (mMediaProjection != null) { + if (mMediaProjectionCallback != null) { + mMediaProjection.unregisterCallback(mMediaProjectionCallback); + mMediaProjectionCallback = null; + } + mMediaProjection.stop(); + mMediaProjection = null; + } + if (mImageReader != null) { + mImageReader = null; + } + if (mVirtualDisplay != null) { + mVirtualDisplay.getSurface().release(); + mVirtualDisplay.release(); + mVirtualDisplay = null; + } + } + }, + new Handler(Looper.getMainLooper()) + ); + } + +} diff --git a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt index 8829f74f5092..2a82d5f9bd7c 100644 --- a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt +++ b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt @@ -17,8 +17,12 @@ package com.android.server.input +import android.Manifest import android.content.Context import android.content.ContextWrapper +import android.content.PermissionChecker +import android.content.pm.PackageManager +import android.content.pm.PackageManagerInternal import android.hardware.display.DisplayManager import android.hardware.display.DisplayViewport import android.hardware.display.VirtualDisplay @@ -27,20 +31,30 @@ import android.hardware.input.InputManagerGlobal import android.os.InputEventInjectionSync import android.os.SystemClock import android.os.test.TestLooper +import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.Presubmit -import android.platform.test.flag.junit.DeviceFlagsValueProvider +import android.platform.test.flag.junit.SetFlagsRule import android.provider.Settings import android.view.View.OnKeyListener import android.view.InputDevice +import android.view.KeyCharacterMap import android.view.KeyEvent import android.view.SurfaceHolder import android.view.SurfaceView +import android.view.WindowManager import android.test.mock.MockContentResolver import androidx.test.platform.app.InstrumentationRegistry +import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity +import com.android.dx.mockito.inline.extended.ExtendedMockito +import com.android.internal.policy.KeyInterceptionInfo import com.android.internal.util.test.FakeSettingsProvider +import com.android.modules.utils.testing.ExtendedMockitoRule +import com.android.server.LocalServices +import com.android.server.wm.WindowManagerInternal import com.google.common.truth.Truth.assertThat -import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotEquals import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Rule @@ -49,15 +63,15 @@ import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyFloat import org.mockito.ArgumentMatchers.anyInt +import org.mockito.ArgumentMatchers.eq import org.mockito.Mock -import org.mockito.Mockito.`when` import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.spy import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.verifyZeroInteractions -import org.mockito.junit.MockitoJUnit +import org.mockito.Mockito.`when` import org.mockito.stubbing.OngoingStubbing /** @@ -69,14 +83,28 @@ import org.mockito.stubbing.OngoingStubbing @Presubmit class InputManagerServiceTests { - @get:Rule - val mockitoRule = MockitoJUnit.rule()!! + companion object { + val ACTION_KEY_EVENTS = listOf( + KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_META_LEFT), + KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_META_RIGHT), + KeyEvent( /* downTime= */0, /* eventTime= */0, /* action= */0, /* code= */0, + /* repeat= */0, KeyEvent.META_META_ON + ) + ) + } - @get:Rule - val fakeSettingsProviderRule = FakeSettingsProvider.rule()!! + @JvmField + @Rule + val extendedMockitoRule = + ExtendedMockitoRule.Builder(this).mockStatic(LocalServices::class.java) + .mockStatic(PermissionChecker::class.java).build()!! + + @JvmField + @Rule + val setFlagsRule = SetFlagsRule() @get:Rule - val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()!! + val fakeSettingsProviderRule = FakeSettingsProvider.rule()!! @Mock private lateinit var native: NativeInputManagerService @@ -85,8 +113,17 @@ class InputManagerServiceTests { private lateinit var wmCallbacks: InputManagerService.WindowManagerCallbacks @Mock + private lateinit var windowManagerInternal: WindowManagerInternal + + @Mock + private lateinit var packageManagerInternal: PackageManagerInternal + + @Mock private lateinit var uEventManager: UEventManager + @Mock + private lateinit var kbdController: InputManagerService.KeyboardBacklightControllerInterface + private lateinit var service: InputManagerService private lateinit var localService: InputManagerInternal private lateinit var context: Context @@ -113,11 +150,29 @@ class InputManagerServiceTests { override fun registerLocalService(service: InputManagerInternal?) { localService = service!! } + + override fun getKeyboardBacklightController( + nativeService: NativeInputManagerService?, + dataStore: PersistentDataStore? + ): InputManagerService.KeyboardBacklightControllerInterface { + return kbdController + } }) inputManagerGlobalSession = InputManagerGlobal.createTestSession(service) val inputManager = InputManager(context) whenever(context.getSystemService(InputManager::class.java)).thenReturn(inputManager) whenever(context.getSystemService(Context.INPUT_SERVICE)).thenReturn(inputManager) + whenever(context.checkCallingOrSelfPermission(Manifest.permission.MANAGE_KEY_GESTURES)) + .thenReturn( + PackageManager.PERMISSION_GRANTED + ) + + ExtendedMockito.doReturn(windowManagerInternal).`when` { + LocalServices.getService(eq(WindowManagerInternal::class.java)) + } + ExtendedMockito.doReturn(packageManagerInternal).`when` { + LocalServices.getService(eq(PackageManagerInternal::class.java)) + } assertTrue("Local service must be registered", this::localService.isInitialized) service.setWindowManagerCallbacks(wmCallbacks) @@ -195,7 +250,7 @@ class InputManagerServiceTests { } @Test - fun testAddAndRemoveVirtualmKeyboardLayoutAssociation() { + fun testAddAndRemoveVirtualKeyboardLayoutAssociation() { val inputPort = "input port" val languageTag = "language" val layoutType = "layoutType" @@ -206,6 +261,48 @@ class InputManagerServiceTests { verify(native, times(2)).changeKeyboardLayoutAssociation() } + @Test + fun testActionKeyEventsForwardedToFocusedWindow_whenCorrectlyRequested() { + service.systemRunning() + overrideSendActionKeyEventsToFocusedWindow( + /* hasPermission = */true, + /* hasPrivateFlag = */true + ) + whenever(wmCallbacks.interceptKeyBeforeDispatching(any(), any(), anyInt())).thenReturn(-1) + + for (event in ACTION_KEY_EVENTS) { + assertEquals(0, service.interceptKeyBeforeDispatching(null, event, 0)) + } + } + + @Test + fun testActionKeyEventsNotForwardedToFocusedWindow_whenNoPermissions() { + service.systemRunning() + overrideSendActionKeyEventsToFocusedWindow( + /* hasPermission = */false, + /* hasPrivateFlag = */true + ) + whenever(wmCallbacks.interceptKeyBeforeDispatching(any(), any(), anyInt())).thenReturn(-1) + + for (event in ACTION_KEY_EVENTS) { + assertNotEquals(0, service.interceptKeyBeforeDispatching(null, event, 0)) + } + } + + @Test + fun testActionKeyEventsNotForwardedToFocusedWindow_whenNoPrivateFlag() { + service.systemRunning() + overrideSendActionKeyEventsToFocusedWindow( + /* hasPermission = */true, + /* hasPrivateFlag = */false + ) + whenever(wmCallbacks.interceptKeyBeforeDispatching(any(), any(), anyInt())).thenReturn(-1) + + for (event in ACTION_KEY_EVENTS) { + assertNotEquals(0, service.interceptKeyBeforeDispatching(null, event, 0)) + } + } + private fun createVirtualDisplays(count: Int): List<VirtualDisplay> { val displayManager: DisplayManager = context.getSystemService( DisplayManager::class.java @@ -373,6 +470,91 @@ class InputManagerServiceTests { verify(mockOnKeyListener).onKey(mockSurfaceView2, KeyEvent.KEYCODE_A, upEvent) verify(mockOnKeyListener, never()).onKey(mockSurfaceView1, KeyEvent.KEYCODE_A, upEvent) } + + @Test + @EnableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER) + fun handleKeyGestures_keyboardBacklight() { + service.systemRunning() + + val backlightDownEvent = createKeyEvent(KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN) + service.interceptKeyBeforeDispatching(null, backlightDownEvent, /* policyFlags = */0) + verify(kbdController).decrementKeyboardBacklight(anyInt()) + + val backlightUpEvent = createKeyEvent(KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP) + service.interceptKeyBeforeDispatching(null, backlightUpEvent, /* policyFlags = */0) + verify(kbdController).incrementKeyboardBacklight(anyInt()) + } + + @Test + @EnableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER) + fun handleKeyGestures_toggleCapsLock() { + service.systemRunning() + + val metaDownEvent = createKeyEvent(KeyEvent.KEYCODE_META_LEFT) + service.interceptKeyBeforeDispatching(null, metaDownEvent, /* policyFlags = */0) + val altDownEvent = + createKeyEvent(KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.META_META_ON, KeyEvent.ACTION_DOWN) + service.interceptKeyBeforeDispatching(null, altDownEvent, /* policyFlags = */0) + val altUpEvent = + createKeyEvent(KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.META_META_ON, KeyEvent.ACTION_UP) + service.interceptKeyBeforeDispatching(null, altUpEvent, /* policyFlags = */0) + + verify(native).toggleCapsLock(anyInt()) + } + + fun overrideSendActionKeyEventsToFocusedWindow( + hasPermission: Boolean, + hasPrivateFlag: Boolean + ) { + ExtendedMockito.doReturn( + if (hasPermission) { + PermissionChecker.PERMISSION_GRANTED + } else { + PermissionChecker.PERMISSION_HARD_DENIED + } + ).`when` { + PermissionChecker.checkPermissionForDataDelivery( + any(), + eq(Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW), + anyInt(), + anyInt(), + any(), + any(), + any() + ) + } + + val info = KeyInterceptionInfo( + /* type = */0, + if (hasPrivateFlag) { + WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS + } else { + 0 + }, + "title", + /* uid = */0 + ) + whenever(windowManagerInternal.getKeyInterceptionInfoFromToken(any())).thenReturn(info) + } + + private fun createKeyEvent( + keycode: Int, + modifierState: Int = 0, + action: Int = KeyEvent.ACTION_DOWN + ): KeyEvent { + return KeyEvent( + /* downTime = */0, + /* eventTime = */0, + action, + keycode, + /* repeat = */0, + modifierState, + KeyCharacterMap.VIRTUAL_KEYBOARD, + /* scancode = */0, + /* flags = */0, + InputDevice.SOURCE_KEYBOARD + ) + } } private fun <T> whenever(methodCall: T): OngoingStubbing<T> = `when`(methodCall) diff --git a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt index 28550cd4f354..ba360070abc3 100644 --- a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt +++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt @@ -286,6 +286,18 @@ class KeyGestureControllerTests { intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE) ), TestData( + "META + CTRL + N -> Open Notes", + intArrayOf( + KeyEvent.KEYCODE_META_LEFT, + KeyEvent.KEYCODE_CTRL_LEFT, + KeyEvent.KEYCODE_N + ), + KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES, + intArrayOf(KeyEvent.KEYCODE_N), + KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON, + intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE) + ), + TestData( "META + CTRL + S -> Take Screenshot", intArrayOf( KeyEvent.KEYCODE_META_LEFT, diff --git a/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java index 681b7f28451b..b3a998ebca0d 100644 --- a/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java +++ b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java @@ -16,6 +16,7 @@ package com.android.server.input.debug; +import static android.view.InputDevice.SOURCE_MOUSE; import static android.view.InputDevice.SOURCE_TOUCHSCREEN; import static org.junit.Assert.assertEquals; @@ -29,7 +30,9 @@ import android.content.Context; import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; +import android.hardware.input.InputManager; import android.testing.TestableContext; +import android.view.InputDevice; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; @@ -60,13 +63,15 @@ import org.mockito.MockitoAnnotations; */ @RunWith(AndroidJUnit4.class) public class TouchpadDebugViewTest { - private static final int TOUCHPAD_DEVICE_ID = 6; + private static final int TOUCHPAD_DEVICE_ID = 60; private TouchpadDebugView mTouchpadDebugView; private WindowManager.LayoutParams mWindowLayoutParams; @Mock WindowManager mWindowManager; + @Mock + InputManager mInputManager; Rect mWindowBounds; WindowMetrics mWindowMetrics; @@ -79,12 +84,21 @@ public class TouchpadDebugViewTest { mTestableContext = new TestableContext(context); mTestableContext.addMockSystemService(WindowManager.class, mWindowManager); + mTestableContext.addMockSystemService(InputManager.class, mInputManager); mWindowBounds = new Rect(0, 0, 2560, 1600); mWindowMetrics = new WindowMetrics(mWindowBounds, new WindowInsets(mWindowBounds), 1.0f); when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics); + InputDevice inputDevice = new InputDevice.Builder() + .setId(TOUCHPAD_DEVICE_ID) + .setSources(InputDevice.SOURCE_TOUCHPAD | SOURCE_MOUSE) + .setName("Test Device " + TOUCHPAD_DEVICE_ID) + .build(); + + when(mInputManager.getInputDevice(TOUCHPAD_DEVICE_ID)).thenReturn(inputDevice); + mTouchpadDebugView = new TouchpadDebugView(mTestableContext, TOUCHPAD_DEVICE_ID, new TouchpadHardwareProperties.Builder(0f, 0f, 500f, 500f, 45f, 47f, -4f, 5f, (short) 10, true, @@ -341,4 +355,43 @@ public class TouchpadDebugViewTest { mTouchpadDebugView.updateGestureInfo(gestureType, TOUCHPAD_DEVICE_ID); assertEquals(child.getText().toString(), TouchpadDebugView.getGestureText(gestureType)); } -} + + @Test + public void testTwoFingerDrag() { + float offsetX = ViewConfiguration.get(mTestableContext).getScaledTouchSlop() + 10; + float offsetY = ViewConfiguration.get(mTestableContext).getScaledTouchSlop() + 10; + + // Simulate ACTION_DOWN event (gesture starts). + MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_MOUSE) + .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER) + .x(40f) + .y(40f) + ) + .classification(MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE) + .build(); + mTouchpadDebugView.dispatchTouchEvent(actionDown); + + // Simulate ACTION_MOVE event (dragging with two fingers, processed as one pointer). + MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_MOUSE) + .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER) + .x(40f + offsetX) + .y(40f + offsetY) + ) + .classification(MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE) + .build(); + mTouchpadDebugView.dispatchTouchEvent(actionMove); + + // Simulate ACTION_UP event (gesture ends). + MotionEvent actionUp = new MotionEventBuilder(MotionEvent.ACTION_UP, SOURCE_MOUSE) + .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER) + .x(40f + offsetX) + .y(40f + offsetY) + ) + .classification(MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE) + .build(); + mTouchpadDebugView.dispatchTouchEvent(actionUp); + + // Verify that no updateViewLayout is called (as expected for a two-finger drag gesture). + verify(mWindowManager, times(0)).updateViewLayout(any(), any()); + } +}
\ No newline at end of file diff --git a/tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt b/tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt index aa73c397a663..c61a25021949 100644 --- a/tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt +++ b/tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt @@ -36,7 +36,6 @@ import com.android.cts.input.inputeventmatchers.withMotionAction import com.android.cts.input.inputeventmatchers.withPressure import com.android.cts.input.inputeventmatchers.withRawCoords import com.android.cts.input.inputeventmatchers.withSource -import java.io.InputStream import junit.framework.Assert.fail import org.hamcrest.Matchers.allOf import org.junit.Before @@ -130,17 +129,18 @@ class UinputRecordingIntegrationTests { scenario.virtualDisplay.display.uniqueId!!, ) - injectUinputEvents() - - if (DEBUG_RECEIVED_EVENTS) { - printReceivedEventsToLogcat(scenario.activity) - fail("Test cannot pass in debug mode!") + injectUinputEvents().use { + if (DEBUG_RECEIVED_EVENTS) { + printReceivedEventsToLogcat(scenario.activity) + fail("Test cannot pass in debug mode!") + } + + val verifier = EventVerifier( + BatchedEventSplitter { scenario.activity.getInputEvent() } + ) + verifyEvents(verifier) + scenario.activity.assertNoEvents() } - - val verifier = - EventVerifier(BatchedEventSplitter { scenario.activity.getInputEvent() }) - verifyEvents(verifier) - scenario.activity.assertNoEvents() } finally { inputManager.removeUniqueIdAssociationByPort(inputPort) } @@ -162,14 +162,32 @@ class UinputRecordingIntegrationTests { } } - private fun injectUinputEvents() { + /** + * Plays back the evemu recording associated with the current test case by injecting it via + * the `uinput` shell command in interactive mode. The recording playback will begin + * immediately, and the shell command (and the associated input device) will remain alive + * until the returned [AutoCloseable] is closed. + */ + private fun injectUinputEvents(): AutoCloseable { val fds = instrumentation.uiAutomation!!.executeShellCommandRw("uinput -") + // We do not need to use stdout in this test. + fds[0].close() - ParcelFileDescriptor.AutoCloseOutputStream(fds[1]).use { stdIn -> - val inputStream: InputStream = instrumentation.context.resources.openRawResource( + return ParcelFileDescriptor.AutoCloseOutputStream(fds[1]).also { stdin -> + instrumentation.context.resources.openRawResource( testData.uinputRecordingResource, - ) - stdIn.write(inputStream.readBytes()) + ).use { inputStream -> + stdin.write(inputStream.readBytes()) + + // TODO(b/367419268): Remove extra event injection when uinput parsing is fixed. + // Inject an extra sync event with an arbitrarily large timestamp, because the + // uinput command will not process the last event until either the next event is + // parsed, or fd is closed. Injecting this sync allows us complete injection of + // the evemu recording and extend the lifetime of the input device by keeping this + // fd open. + stdin.write("\nE: 9999.99 0 0 0\n".toByteArray()) + stdin.flush() + } } } diff --git a/tests/Tracing/Android.bp b/tests/Tracing/Android.bp new file mode 100644 index 000000000000..90998e67ae31 --- /dev/null +++ b/tests/Tracing/Android.bp @@ -0,0 +1,33 @@ +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_team: "trendy_team_windowing_tools", + default_applicable_licenses: ["frameworks_base_license"], +} + +android_test { + name: "TracingTests", + proto: { + type: "nano", + }, + // Include some source files directly to be able to access package members + srcs: ["src/**/*.java"], + libs: ["android.test.runner.stubs.system"], + static_libs: [ + "junit", + "androidx.test.rules", + "mockito-target-minus-junit4", + "truth", + "platform-test-annotations", + "flickerlib-parsers", + "perfetto_trace_java_protos", + "flickerlib-trace_processor_shell", + ], + java_resource_dirs: ["res"], + certificate: "platform", + platform_apis: true, + test_suites: ["device-tests"], +} diff --git a/tests/Tracing/AndroidManifest.xml b/tests/Tracing/AndroidManifest.xml new file mode 100644 index 000000000000..7254f81307ad --- /dev/null +++ b/tests/Tracing/AndroidManifest.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.tracing.tests"> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> + <uses-permission android:name="android.permission.BIND_WALLPAPER"/> + <!-- Allow the test to connect to perfetto trace processor --> + <uses-permission android:name="android.permission.INTERNET"/> + <application + android:requestLegacyExternalStorage="true" + android:networkSecurityConfig="@xml/network_security_config"> + <uses-library android:name="android.test.runner"/> + </application> + + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.tracing.tests" + android:label="Tracing Tests"/> +</manifest> diff --git a/tests/Tracing/AndroidTest.xml b/tests/Tracing/AndroidTest.xml new file mode 100644 index 000000000000..9a404203ee18 --- /dev/null +++ b/tests/Tracing/AndroidTest.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<configuration description="Runs tests for tracing classes/utilities."> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="test-file-name" value="TracingTests.apk" /> + </target_preparer> + + <!-- Needed for pushing the trace config file --> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/> + + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="framework-base-presubmit" /> + <option name="test-tag" value="TracingTests" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.android.tracing.tests" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> + </test> + + <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> + <option name="pull-pattern-keys" value="perfetto_file_path"/> + <option name="directory-keys" + value="/data/user/0/com.android.tracing.tests/files"/> + <option name="collect-on-run-ended-only" value="true"/> + <option name="clean-up" value="true"/> + </metrics_collector> +</configuration>
\ No newline at end of file diff --git a/tests/Internal/src/com/android/internal/protolog/OWNERS b/tests/Tracing/OWNERS index 18cf2be9f7df..4a5033800b8e 100644 --- a/tests/Internal/src/com/android/internal/protolog/OWNERS +++ b/tests/Tracing/OWNERS @@ -1,3 +1,3 @@ -# ProtoLog owners +# Tracing owners # Bug component: 1157642 include platform/development:/tools/winscope/OWNERS diff --git a/tests/Tracing/TEST_MAPPING b/tests/Tracing/TEST_MAPPING new file mode 100644 index 000000000000..7f58fceee24d --- /dev/null +++ b/tests/Tracing/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "postsubmit": [ + { + "name": "TracingTests" + } + ] +}
\ No newline at end of file diff --git a/tests/Tracing/res/xml/network_security_config.xml b/tests/Tracing/res/xml/network_security_config.xml new file mode 100644 index 000000000000..fdf1dbbe7672 --- /dev/null +++ b/tests/Tracing/res/xml/network_security_config.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. + --> +<network-security-config> + <domain-config cleartextTrafficPermitted="true"> + <domain includeSubdomains="true">localhost</domain> + </domain-config> +</network-security-config> diff --git a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java b/tests/Tracing/src/com/android/internal/protolog/LegacyProtoLogImplTest.java index 9657225588b7..8913e8c1996e 100644 --- a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogImplTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/LegacyProtoLogImplTest.java @@ -180,7 +180,6 @@ public class LegacyProtoLogImplTest { verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq( LogLevel.INFO), eq("test 5")); - verify(mReader, never()).getViewerString(anyLong()); } @Test diff --git a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogViewerConfigReaderTest.java b/tests/Tracing/src/com/android/internal/protolog/LegacyProtoLogViewerConfigReaderTest.java index 253965337824..253965337824 100644 --- a/tests/Internal/src/com/android/internal/protolog/LegacyProtoLogViewerConfigReaderTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/LegacyProtoLogViewerConfigReaderTest.java diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Tracing/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java index e841d9ea0880..c882b4e569a1 100644 --- a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java @@ -42,7 +42,7 @@ import android.util.proto.ProtoInputStream; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.internal.protolog.ProtoLogConfigurationService.ViewerConfigFileTracer; +import com.android.internal.protolog.ProtoLogConfigurationServiceImpl.ViewerConfigFileTracer; import com.android.internal.protolog.common.IProtoLogGroup; import com.android.internal.protolog.common.LogDataType; import com.android.internal.protolog.common.LogLevel; @@ -166,7 +166,8 @@ public class PerfettoProtoLogImplTest { return new ProtoInputStream(sViewerConfigBuilder.build().toByteArray()); }); }; - sProtoLogConfigurationService = new ProtoLogConfigurationService(dataSourceBuilder, tracer); + sProtoLogConfigurationService = + new ProtoLogConfigurationServiceImpl(dataSourceBuilder, tracer); if (android.tracing.Flags.clientSideProtoLogging()) { sProtoLog = new PerfettoProtoLogImpl( diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogCommandHandlerTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtoLogCommandHandlerTest.java index aba6722c0813..be0c7daebb57 100644 --- a/tests/Internal/src/com/android/internal/protolog/ProtoLogCommandHandlerTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/ProtoLogCommandHandlerTest.java @@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.endsWith; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.times; +import android.os.Binder; import android.platform.test.annotations.Presubmit; import org.junit.Test; @@ -44,6 +45,8 @@ public class ProtoLogCommandHandlerTest { ProtoLogConfigurationService mProtoLogConfigurationService; @Mock PrintWriter mPrintWriter; + @Mock + Binder mMockBinder; @Test public void printsHelpForAllAvailableCommands() { @@ -70,7 +73,7 @@ public class ProtoLogCommandHandlerTest { final ProtoLogCommandHandler cmdHandler = new ProtoLogCommandHandler(mProtoLogConfigurationService, mPrintWriter); - cmdHandler.exec(mProtoLogConfigurationService, FileDescriptor.in, FileDescriptor.out, + cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, new String[] { "groups", "list" }); Mockito.verify(mPrintWriter, times(1)) @@ -84,7 +87,7 @@ public class ProtoLogCommandHandlerTest { final ProtoLogCommandHandler cmdHandler = new ProtoLogCommandHandler(mProtoLogConfigurationService, mPrintWriter); - cmdHandler.exec(mProtoLogConfigurationService, FileDescriptor.in, FileDescriptor.out, + cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, new String[] { "groups" }); Mockito.verify(mPrintWriter, times(1)) @@ -99,7 +102,7 @@ public class ProtoLogCommandHandlerTest { final ProtoLogCommandHandler cmdHandler = new ProtoLogCommandHandler(mProtoLogConfigurationService, mPrintWriter); - cmdHandler.exec(mProtoLogConfigurationService, FileDescriptor.in, FileDescriptor.out, + cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, new String[] { "groups", "status", "MY_GROUP" }); Mockito.verify(mPrintWriter, times(1)) @@ -114,7 +117,7 @@ public class ProtoLogCommandHandlerTest { final ProtoLogCommandHandler cmdHandler = new ProtoLogCommandHandler(mProtoLogConfigurationService, mPrintWriter); - cmdHandler.exec(mProtoLogConfigurationService, FileDescriptor.in, FileDescriptor.out, + cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, new String[] { "groups", "status", "MY_GROUP" }); Mockito.verify(mPrintWriter, times(1)) @@ -128,7 +131,7 @@ public class ProtoLogCommandHandlerTest { final ProtoLogCommandHandler cmdHandler = new ProtoLogCommandHandler(mProtoLogConfigurationService, mPrintWriter); - cmdHandler.exec(mProtoLogConfigurationService, FileDescriptor.in, FileDescriptor.out, + cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, new String[] { "groups", "status" }); Mockito.verify(mPrintWriter, times(1)) @@ -140,7 +143,7 @@ public class ProtoLogCommandHandlerTest { final ProtoLogCommandHandler cmdHandler = new ProtoLogCommandHandler(mProtoLogConfigurationService, mPrintWriter); - cmdHandler.exec(mProtoLogConfigurationService, FileDescriptor.in, FileDescriptor.out, + cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, new String[] { "logcat" }); Mockito.verify(mPrintWriter, times(1)) @@ -152,11 +155,11 @@ public class ProtoLogCommandHandlerTest { final ProtoLogCommandHandler cmdHandler = new ProtoLogCommandHandler(mProtoLogConfigurationService, mPrintWriter); - cmdHandler.exec(mProtoLogConfigurationService, FileDescriptor.in, FileDescriptor.out, + cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, new String[] { "logcat", "enable", "MY_GROUP" }); Mockito.verify(mProtoLogConfigurationService).enableProtoLogToLogcat("MY_GROUP"); - cmdHandler.exec(mProtoLogConfigurationService, FileDescriptor.in, FileDescriptor.out, + cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, new String[] { "logcat", "enable", "MY_GROUP", "MY_OTHER_GROUP" }); Mockito.verify(mProtoLogConfigurationService) @@ -168,11 +171,11 @@ public class ProtoLogCommandHandlerTest { final ProtoLogCommandHandler cmdHandler = new ProtoLogCommandHandler(mProtoLogConfigurationService, mPrintWriter); - cmdHandler.exec(mProtoLogConfigurationService, FileDescriptor.in, FileDescriptor.out, + cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, new String[] { "logcat", "disable", "MY_GROUP" }); Mockito.verify(mProtoLogConfigurationService).disableProtoLogToLogcat("MY_GROUP"); - cmdHandler.exec(mProtoLogConfigurationService, FileDescriptor.in, FileDescriptor.out, + cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, new String[] { "logcat", "disable", "MY_GROUP", "MY_OTHER_GROUP" }); Mockito.verify(mProtoLogConfigurationService) @@ -184,7 +187,7 @@ public class ProtoLogCommandHandlerTest { final ProtoLogCommandHandler cmdHandler = new ProtoLogCommandHandler(mProtoLogConfigurationService, mPrintWriter); - cmdHandler.exec(mProtoLogConfigurationService, FileDescriptor.in, FileDescriptor.out, + cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, new String[] { "logcat", "enable" }); Mockito.verify(mPrintWriter).println(contains("Incomplete command")); } @@ -194,7 +197,7 @@ public class ProtoLogCommandHandlerTest { final ProtoLogCommandHandler cmdHandler = new ProtoLogCommandHandler(mProtoLogConfigurationService, mPrintWriter); - cmdHandler.exec(mProtoLogConfigurationService, FileDescriptor.in, FileDescriptor.out, + cmdHandler.exec(mMockBinder, FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, new String[] { "logcat", "disable" }); Mockito.verify(mPrintWriter).println(contains("Incomplete command")); } diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogConfigurationServiceTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtoLogConfigurationServiceTest.java index e1bdd777dc5f..a3d03a8278ed 100644 --- a/tests/Internal/src/com/android/internal/protolog/ProtoLogConfigurationServiceTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/ProtoLogConfigurationServiceTest.java @@ -150,11 +150,11 @@ public class ProtoLogConfigurationServiceTest { @Test public void canRegisterClientWithGroupsOnly() throws RemoteException { - final ProtoLogConfigurationService service = new ProtoLogConfigurationService(); + final ProtoLogConfigurationService service = new ProtoLogConfigurationServiceImpl(); - final ProtoLogConfigurationService.RegisterClientArgs args = - new ProtoLogConfigurationService.RegisterClientArgs() - .setGroups(new ProtoLogConfigurationService.RegisterClientArgs + final ProtoLogConfigurationServiceImpl.RegisterClientArgs args = + new ProtoLogConfigurationServiceImpl.RegisterClientArgs() + .setGroups(new ProtoLogConfigurationServiceImpl.RegisterClientArgs .GroupConfig(TEST_GROUP, true)); service.registerClient(mMockClient, args); @@ -165,11 +165,11 @@ public class ProtoLogConfigurationServiceTest { @Test public void willDumpViewerConfigOnlyOnceOnTraceStop() throws RemoteException, InvalidProtocolBufferException { - final ProtoLogConfigurationService service = new ProtoLogConfigurationService(); + final ProtoLogConfigurationService service = new ProtoLogConfigurationServiceImpl(); - final ProtoLogConfigurationService.RegisterClientArgs args = - new ProtoLogConfigurationService.RegisterClientArgs() - .setGroups(new ProtoLogConfigurationService.RegisterClientArgs + final ProtoLogConfigurationServiceImpl.RegisterClientArgs args = + new ProtoLogConfigurationServiceImpl.RegisterClientArgs() + .setGroups(new ProtoLogConfigurationServiceImpl.RegisterClientArgs .GroupConfig(TEST_GROUP, true)) .setViewerConfigFile(mViewerConfigFile.getAbsolutePath()); service.registerClient(mMockClient, args); @@ -200,13 +200,13 @@ public class ProtoLogConfigurationServiceTest { @Test public void willDumpViewerConfigOnLastClientDisconnected() throws RemoteException, FileNotFoundException { - final ProtoLogConfigurationService.ViewerConfigFileTracer tracer = - Mockito.mock(ProtoLogConfigurationService.ViewerConfigFileTracer.class); - final ProtoLogConfigurationService service = new ProtoLogConfigurationService(tracer); + final ProtoLogConfigurationServiceImpl.ViewerConfigFileTracer tracer = + Mockito.mock(ProtoLogConfigurationServiceImpl.ViewerConfigFileTracer.class); + final ProtoLogConfigurationService service = new ProtoLogConfigurationServiceImpl(tracer); - final ProtoLogConfigurationService.RegisterClientArgs args = - new ProtoLogConfigurationService.RegisterClientArgs() - .setGroups(new ProtoLogConfigurationService.RegisterClientArgs + final ProtoLogConfigurationServiceImpl.RegisterClientArgs args = + new ProtoLogConfigurationServiceImpl.RegisterClientArgs() + .setGroups(new ProtoLogConfigurationServiceImpl.RegisterClientArgs .GroupConfig(TEST_GROUP, true)) .setViewerConfigFile(mViewerConfigFile.getAbsolutePath()); service.registerClient(mMockClient, args); @@ -225,10 +225,10 @@ public class ProtoLogConfigurationServiceTest { @Test public void sendEnableLoggingToLogcatToClient() throws RemoteException { - final var service = new ProtoLogConfigurationService(); + final var service = new ProtoLogConfigurationServiceImpl(); - final var args = new ProtoLogConfigurationService.RegisterClientArgs() - .setGroups(new ProtoLogConfigurationService.RegisterClientArgs + final var args = new ProtoLogConfigurationServiceImpl.RegisterClientArgs() + .setGroups(new ProtoLogConfigurationServiceImpl.RegisterClientArgs .GroupConfig(TEST_GROUP, false)); service.registerClient(mMockClient, args); @@ -242,11 +242,11 @@ public class ProtoLogConfigurationServiceTest { @Test public void sendDisableLoggingToLogcatToClient() throws RemoteException { - final ProtoLogConfigurationService service = new ProtoLogConfigurationService(); + final ProtoLogConfigurationService service = new ProtoLogConfigurationServiceImpl(); - final ProtoLogConfigurationService.RegisterClientArgs args = - new ProtoLogConfigurationService.RegisterClientArgs() - .setGroups(new ProtoLogConfigurationService.RegisterClientArgs + final ProtoLogConfigurationServiceImpl.RegisterClientArgs args = + new ProtoLogConfigurationServiceImpl.RegisterClientArgs() + .setGroups(new ProtoLogConfigurationServiceImpl.RegisterClientArgs .GroupConfig(TEST_GROUP, true)); service.registerClient(mMockClient, args); @@ -260,11 +260,11 @@ public class ProtoLogConfigurationServiceTest { @Test public void doNotSendLoggingToLogcatToClientWithoutRegisteredGroup() throws RemoteException { - final ProtoLogConfigurationService service = new ProtoLogConfigurationService(); + final ProtoLogConfigurationService service = new ProtoLogConfigurationServiceImpl(); - final ProtoLogConfigurationService.RegisterClientArgs args = - new ProtoLogConfigurationService.RegisterClientArgs() - .setGroups(new ProtoLogConfigurationService.RegisterClientArgs + final ProtoLogConfigurationServiceImpl.RegisterClientArgs args = + new ProtoLogConfigurationServiceImpl.RegisterClientArgs() + .setGroups(new ProtoLogConfigurationServiceImpl.RegisterClientArgs .GroupConfig(TEST_GROUP, false)); service.registerClient(mMockClient, args); @@ -277,15 +277,15 @@ public class ProtoLogConfigurationServiceTest { @Test public void handlesToggleToLogcatBeforeClientIsRegistered() throws RemoteException { - final ProtoLogConfigurationService service = new ProtoLogConfigurationService(); + final ProtoLogConfigurationService service = new ProtoLogConfigurationServiceImpl(); Truth.assertThat(service.getGroups()).asList().doesNotContain(TEST_GROUP); service.enableProtoLogToLogcat(TEST_GROUP); Truth.assertThat(service.isLoggingToLogcat(TEST_GROUP)).isTrue(); - final ProtoLogConfigurationService.RegisterClientArgs args = - new ProtoLogConfigurationService.RegisterClientArgs() - .setGroups(new ProtoLogConfigurationService.RegisterClientArgs + final ProtoLogConfigurationServiceImpl.RegisterClientArgs args = + new ProtoLogConfigurationServiceImpl.RegisterClientArgs() + .setGroups(new ProtoLogConfigurationServiceImpl.RegisterClientArgs .GroupConfig(TEST_GROUP, false)); service.registerClient(mMockClient, args); diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtoLogImplTest.java index 0496240f01e4..0496240f01e4 100644 --- a/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/ProtoLogImplTest.java diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtoLogTest.java index 9d56a92fad52..9d56a92fad52 100644 --- a/tests/Internal/src/com/android/internal/protolog/ProtoLogTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/ProtoLogTest.java diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java index be0e8bc0fc07..28d7b42764c4 100644 --- a/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java @@ -27,7 +27,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import perfetto.protos.Protolog; import perfetto.protos.ProtologCommon; @Presubmit @@ -48,7 +47,7 @@ public class ProtoLogViewerConfigReaderTest { .setTag(TEST_GROUP_TAG) ).addGroups( perfetto.protos.Protolog.ProtoLogViewerConfig.Group.newBuilder() - .setId(1) + .setId(2) .setName(OTHER_TEST_GROUP_NAME) .setTag(OTHER_TEST_GROUP_TAG) ).addMessages( diff --git a/tests/Internal/src/com/android/internal/protolog/ProtologDataSourceTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtologDataSourceTest.java index 9a062e3b2f80..ce519b7a1576 100644 --- a/tests/Internal/src/com/android/internal/protolog/ProtologDataSourceTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/ProtologDataSourceTest.java @@ -67,7 +67,8 @@ public class ProtologDataSourceTest { @Test public void allEnabledTraceMode() { - final ProtoLogDataSource ds = new ProtoLogDataSource((idx, c) -> {}, () -> {}, (idx, c) -> {}); + final ProtoLogDataSource ds = + new ProtoLogDataSource((idx, c) -> {}, () -> {}, (idx, c) -> {}); final ProtoLogDataSource.TlsState tlsState = createTlsState( DataSourceConfigOuterClass.DataSourceConfig.newBuilder().setProtologConfig( diff --git a/tests/Internal/src/com/android/internal/protolog/common/LogDataTypeTest.java b/tests/Tracing/src/com/android/internal/protolog/common/LogDataTypeTest.java index 9c2f74eabe02..9c2f74eabe02 100644 --- a/tests/Internal/src/com/android/internal/protolog/common/LogDataTypeTest.java +++ b/tests/Tracing/src/com/android/internal/protolog/common/LogDataTypeTest.java diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index 580efe126ea3..4cb7c91b2451 100644 --- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java +++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java @@ -146,6 +146,8 @@ public class VcnManagementServiceTest { private static final LinkProperties TEST_LP_1 = new LinkProperties(); private static final LinkProperties TEST_LP_2 = new LinkProperties(); + private static final int ACTIVE_MODEM_COUNT = 2; + static { TEST_LP_1.setInterfaceName(TEST_IFACE_NAME); TEST_LP_2.setInterfaceName(TEST_IFACE_NAME_2); @@ -233,6 +235,7 @@ public class VcnManagementServiceTest { setupSystemService(mMockContext, mUserManager, Context.USER_SERVICE, UserManager.class); doReturn(TEST_USER_HANDLE).when(mUserManager).getMainUser(); + doReturn(ACTIVE_MODEM_COUNT).when(mTelMgr).getActiveModemCount(); doReturn(TEST_PACKAGE_NAME).when(mMockContext).getOpPackageName(); diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt index 290e7be9f6c4..94674348df08 100644 --- a/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt +++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt @@ -22,6 +22,7 @@ import com.android.tools.lint.detector.api.CURRENT_API import com.google.android.lint.aidl.EnforcePermissionDetector import com.google.android.lint.aidl.PermissionAnnotationDetector import com.google.android.lint.aidl.SimpleManualPermissionEnforcementDetector +import com.google.android.lint.aidl.SimpleRequiresNoPermissionDetector import com.google.auto.service.AutoService @AutoService(IssueRegistry::class) @@ -34,6 +35,7 @@ class AndroidGlobalIssueRegistry : IssueRegistry() { EnforcePermissionDetector.ISSUE_MISUSING_ENFORCE_PERMISSION, PermissionAnnotationDetector.ISSUE_MISSING_PERMISSION_ANNOTATION, SimpleManualPermissionEnforcementDetector.ISSUE_SIMPLE_MANUAL_PERMISSION_ENFORCEMENT, + SimpleRequiresNoPermissionDetector.ISSUE_SIMPLE_REQUIRES_NO_PERMISSION, ) override val api: Int diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleRequiresNoPermissionDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleRequiresNoPermissionDetector.kt new file mode 100644 index 000000000000..1a13c0280ec6 --- /dev/null +++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleRequiresNoPermissionDetector.kt @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.lint.aidl + +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import org.jetbrains.uast.UastCallKind +import org.jetbrains.uast.UBlockExpression +import org.jetbrains.uast.UCallExpression +import org.jetbrains.uast.UElement +import org.jetbrains.uast.UMethod +import org.jetbrains.uast.visitor.AbstractUastVisitor + +/** + * Ensures all AIDL implementations hosted by system_server which don't call other methods are + * annotated with @RequiresNoPermission. AIDL Interfaces part of `exemptAidlInterfaces` are skipped + * during this search to ensure the detector targets only new AIDL Interfaces. + */ +class SimpleRequiresNoPermissionDetector : AidlImplementationDetector() { + override fun visitAidlMethod( + context: JavaContext, + node: UMethod, + interfaceName: String, + body: UBlockExpression + ) { + if (!isSystemServicePath(context)) return + if (context.evaluator.isAbstract(node)) return + + val fullyQualifiedInterfaceName = + getContainingAidlInterfaceQualified(context, node) ?: return + if (exemptAidlInterfaces.contains(fullyQualifiedInterfaceName)) return + + if (node.hasAnnotation(ANNOTATION_REQUIRES_NO_PERMISSION)) return + + if (!isCallingMethod(node)) { + context.report( + ISSUE_SIMPLE_REQUIRES_NO_PERMISSION, + node, + context.getLocation(node), + """ + Method ${node.name} doesn't perform any permission checks, meaning it should \ + be annotated with @RequiresNoPermission. + """.trimMargin() + ) + } + } + + private fun isCallingMethod(node: UMethod): Boolean { + val uCallExpressionVisitor = UCallExpressionVisitor() + node.accept(uCallExpressionVisitor) + + return uCallExpressionVisitor.isCallingMethod + } + + /** + * Visits the body of a `UMethod` and determines if it encounters a `UCallExpression` which is + * a `UastCallKind.METHOD_CALL`. `isCallingMethod` will hold the result of the search procedure. + */ + private class UCallExpressionVisitor : AbstractUastVisitor() { + var isCallingMethod = false + + override fun visitElement(node: UElement): Boolean { + // Stop the search early when a method call has been found. + return isCallingMethod + } + + override fun visitCallExpression(node: UCallExpression): Boolean { + if (node.kind != UastCallKind.METHOD_CALL) return false + + isCallingMethod = true + return true + } + } + + companion object { + + private val EXPLANATION = """ + Method implementations of AIDL Interfaces hosted by the `system_server` which do not + call any other methods should be annotated with @RequiresNoPermission. That is because + not calling any other methods implies that the method does not perform any permission + checking. + + Please migrate to an @RequiresNoPermission annotation. + """.trimIndent() + + @JvmField + val ISSUE_SIMPLE_REQUIRES_NO_PERMISSION = Issue.create( + id = "SimpleRequiresNoPermission", + briefDescription = "System Service APIs not calling other methods should use @RNP", + explanation = EXPLANATION, + category = Category.SECURITY, + priority = 5, + severity = Severity.ERROR, + implementation = Implementation( + SimpleRequiresNoPermissionDetector::class.java, + Scope.JAVA_FILE_SCOPE + ), + ) + } +} diff --git a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/PermissionAnnotationDetectorTest.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/PermissionAnnotationDetectorTest.kt index 92d0829911bf..824be9309dbc 100644 --- a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/PermissionAnnotationDetectorTest.kt +++ b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/PermissionAnnotationDetectorTest.kt @@ -17,7 +17,6 @@ package com.google.android.lint.aidl import com.android.tools.lint.checks.infrastructure.LintDetectorTest -import com.android.tools.lint.checks.infrastructure.TestFile import com.android.tools.lint.checks.infrastructure.TestLintTask import com.android.tools.lint.detector.api.Detector import com.android.tools.lint.detector.api.Issue @@ -64,7 +63,7 @@ class PermissionAnnotationDetectorTest : LintDetectorTest() { """ package com.android.server; public class Bar extends IBar.Stub { - public void testMethod() { } + public void testMethod(int parameter1, int parameter2) { } } """ ) @@ -75,8 +74,8 @@ class PermissionAnnotationDetectorTest : LintDetectorTest() { .expect( """ src/frameworks/base/services/java/com/android/server/Bar.java:3: Error: The method testMethod is not permission-annotated. [MissingPermissionAnnotation] - public void testMethod() { } - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + public void testMethod(int parameter1, int parameter2) { } + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 errors, 0 warnings """ ) @@ -90,7 +89,7 @@ class PermissionAnnotationDetectorTest : LintDetectorTest() { """ package com.android.server; public class Bar extends IBar.Stub { - public void testMethod() { } + public void testMethod(int parameter1, int parameter2) { } } """ ) @@ -132,7 +131,7 @@ class PermissionAnnotationDetectorTest : LintDetectorTest() { """ package com.android.server; public abstract class Bar extends IBar.Stub { - public abstract void testMethod(); + public abstract void testMethod(int parameter1, int parameter2); } """ ) @@ -177,50 +176,6 @@ class PermissionAnnotationDetectorTest : LintDetectorTest() { .expectClean() } - /* Stubs */ - - // A service with permission annotation on the method. - private val interfaceIFoo: TestFile = java( - """ - public interface IFoo extends android.os.IInterface { - public static abstract class Stub extends android.os.Binder implements IFoo { - } - @Override - @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) - public void testMethod(); - @Override - @android.annotation.RequiresNoPermission - public void testMethodNoPermission(); - @Override - @android.annotation.PermissionManuallyEnforced - public void testMethodManual(); - } - """ - ).indented() - - // A service with no permission annotation. - private val interfaceIBar: TestFile = java( - """ - public interface IBar extends android.os.IInterface { - public static abstract class Stub extends android.os.Binder implements IBar { - } - public void testMethod(); - } - """ - ).indented() - - // A service whose AIDL Interface is exempted. - private val interfaceIExempted: TestFile = java( - """ - package android.accessibilityservice; - public interface IBrailleDisplayConnection extends android.os.IInterface { - public static abstract class Stub extends android.os.Binder implements IBrailleDisplayConnection { - } - public void testMethod(); - } - """ - ).indented() - private val stubs = arrayOf(interfaceIFoo, interfaceIBar, interfaceIExempted) private fun createVisitedPath(filename: String) = diff --git a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleRequiresNoPermissionDetectorTest.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleRequiresNoPermissionDetectorTest.kt new file mode 100644 index 000000000000..a33b48c7eaa0 --- /dev/null +++ b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleRequiresNoPermissionDetectorTest.kt @@ -0,0 +1,244 @@ +/* + * 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.google.android.lint.aidl + +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.checks.infrastructure.TestLintTask +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue + +class SimpleRequiresNoPermissionDetectorTest : LintDetectorTest() { + override fun getDetector(): Detector = SimpleRequiresNoPermissionDetector() + override fun getIssues(): List<Issue> = listOf( + SimpleRequiresNoPermissionDetector + .ISSUE_SIMPLE_REQUIRES_NO_PERMISSION + ) + + override fun lint(): TestLintTask = super.lint().allowMissingSdk() + + fun testRequiresNoPermissionUsedCorrectly_shouldNotWarn() { + lint() + .files( + java( + createVisitedPath("Foo.java"), + """ + package com.android.server; + public class Foo extends IFoo.Stub { + private int memberInt; + + @Override + @android.annotation.RequiresNoPermission + public void testMethodNoPermission(int parameter1, int parameter2) { + if (parameter1 < parameter2) { + memberInt = parameter1; + } else { + memberInt = parameter2; + } + } + } + """ + ) + .indented(), + *stubs + ) + .run() + .expectClean() + } + + fun testMissingRequiresNoPermission_shouldWarn() { + lint() + .files( + java( + createVisitedPath("Bar.java"), + """ + package com.android.server; + public class Bar extends IBar.Stub { + private int memberInt; + + @Override + public void testMethod(int parameter1, int parameter2) { + if (parameter1 < parameter2) { + memberInt = parameter1; + } else { + memberInt = parameter2; + } + } + } + """ + ) + .indented(), + *stubs + ) + .run() + .expect( + """ + src/frameworks/base/services/java/com/android/server/Bar.java:5: Error: Method testMethod doesn't perform any permission checks, meaning it should be annotated with @RequiresNoPermission. [SimpleRequiresNoPermission] + @Override + ^ + 1 errors, 0 warnings + """ + ) + } + + fun testMethodOnlyPerformsConstructorCall_shouldWarn() { + lint() + .files( + java( + createVisitedPath("Bar.java"), + """ + package com.android.server; + public class Bar extends IBar.Stub { + private IntPair memberIntPair; + + @Override + public void testMethod(int parameter1, int parameter2) { + memberIntPair = new IntPair(parameter1, parameter2); + } + + private static class IntPair { + public int first; + public int second; + + public IntPair(int first, int second) { + this.first = first; + this.second = second; + } + } + } + """ + ) + .indented(), + *stubs + ) + .run() + .expect( + """ + src/frameworks/base/services/java/com/android/server/Bar.java:5: Error: Method testMethod doesn't perform any permission checks, meaning it should be annotated with @RequiresNoPermission. [SimpleRequiresNoPermission] + @Override + ^ + 1 errors, 0 warnings + """ + ) + } + + fun testMissingRequiresNoPermissionInIgnoredDirectory_shouldNotWarn() { + lint() + .files( + java( + ignoredPath, + """ + package com.android.server; + public class Bar extends IBar.Stub { + @Override + public void testMethod(int parameter1, int parameter2) {} + } + """ + ) + .indented(), + *stubs + ) + .run() + .expectClean() + } + + fun testMissingRequiresNoPermissionAbstractMethod_shouldNotWarn() { + lint() + .files( + java( + createVisitedPath("Bar.java"), + """ + package com.android.server; + public abstract class Bar extends IBar.Stub { + private int memberInt; + + @Override + public abstract void testMethodNoPermission(int parameter1, int parameter2); + } + """ + ) + .indented(), + *stubs + ) + .run() + .expectClean() + } + + // If this test fails, consider the following steps: + // 1. Pick the first entry (interface) from `exemptAidlInterfaces`. + // 2. Change `interfaceIExempted` to use that interface. + // 3. Change this test's class to extend the interface's Stub. + fun testMissingRequiresNoPermissionAidlInterfaceExempted_shouldNotWarn() { + lint() + .files( + java( + createVisitedPath("Bar.java"), + """ + package com.android.server; + public class Bar extends android.accessibilityservice.IBrailleDisplayConnection.Stub { + public void testMethod(int parameter1, int parameter2) {} + } + """ + ) + .indented(), + *stubs + ) + .run() + .expectClean() + } + + fun testMethodMakesAnotherMethodCall_shouldNotWarn() { + lint() + .files( + java( + createVisitedPath("Bar.java"), + """ + package com.android.server; + public class Bar extends IBar.Stub { + private int memberInt; + + @Override + public void testMethod(int parameter1, int parameter2) { + if (!hasPermission()) return; + + if (parameter1 < parameter2) { + memberInt = parameter1; + } else { + memberInt = parameter2; + } + } + + private bool hasPermission() { + // Perform a permission check. + return true; + } + } + """ + ) + .indented(), + *stubs + ) + .run() + .expectClean() + } + + private val stubs = arrayOf(interfaceIFoo, interfaceIBar, interfaceIExempted) + + private fun createVisitedPath(filename: String) = + "src/frameworks/base/services/java/com/android/server/$filename" + + private val ignoredPath = "src/test/pkg/TestClass.java" +} diff --git a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt index 2ec8fddbb4e9..18a8f186b624 100644 --- a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt +++ b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt @@ -85,4 +85,46 @@ val manifestStub: TestFile = java( } } """.trimIndent() -)
\ No newline at end of file +) + +// A service with permission annotation on the method. +val interfaceIFoo: TestFile = java( + """ + public interface IFoo extends android.os.IInterface { + public static abstract class Stub extends android.os.Binder implements IFoo { + } + @Override + @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) + public void testMethod(); + @Override + @android.annotation.RequiresNoPermission + public void testMethodNoPermission(int parameter1, int parameter2); + @Override + @android.annotation.PermissionManuallyEnforced + public void testMethodManual(); + } + """ +).indented() + +// A service with no permission annotation. +val interfaceIBar: TestFile = java( + """ + public interface IBar extends android.os.IInterface { + public static abstract class Stub extends android.os.Binder implements IBar { + } + public void testMethod(int parameter1, int parameter2); + } + """ +).indented() + +// A service whose AIDL Interface is exempted. +val interfaceIExempted: TestFile = java( + """ + package android.accessibilityservice; + public interface IBrailleDisplayConnection extends android.os.IInterface { + public static abstract class Stub extends android.os.Binder implements IBrailleDisplayConnection { + } + public void testMethod(); + } + """ +).indented() diff --git a/wifi/java/src/android/net/wifi/WifiMigration.java b/wifi/java/src/android/net/wifi/WifiMigration.java index 7df1d4b47204..f1850dd91b5f 100644 --- a/wifi/java/src/android/net/wifi/WifiMigration.java +++ b/wifi/java/src/android/net/wifi/WifiMigration.java @@ -100,6 +100,39 @@ public final class WifiMigration { public @interface UserStoreFileId { } /** + * Keystore migration was completed successfully. + * @hide + */ + @FlaggedApi(Flags.FLAG_LEGACY_KEYSTORE_TO_WIFI_BLOBSTORE_MIGRATION_READ_ONLY) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int KEYSTORE_MIGRATION_SUCCESS_MIGRATION_COMPLETE = 0; + + /** + * Keystore migration was not needed. + * @hide + */ + @FlaggedApi(Flags.FLAG_LEGACY_KEYSTORE_TO_WIFI_BLOBSTORE_MIGRATION_READ_ONLY) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int KEYSTORE_MIGRATION_SUCCESS_MIGRATION_NOT_NEEDED = 1; + + /** + * Keystore migration failed because an exception was encountered. + * @hide + */ + @FlaggedApi(Flags.FLAG_LEGACY_KEYSTORE_TO_WIFI_BLOBSTORE_MIGRATION_READ_ONLY) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int KEYSTORE_MIGRATION_FAILURE_ENCOUNTERED_EXCEPTION = 2; + + /** @hide */ + @IntDef(prefix = { "KEYSTORE_MIGRATION_" }, value = { + KEYSTORE_MIGRATION_SUCCESS_MIGRATION_COMPLETE, + KEYSTORE_MIGRATION_SUCCESS_MIGRATION_NOT_NEEDED, + KEYSTORE_MIGRATION_FAILURE_ENCOUNTERED_EXCEPTION + }) + @Retention(RetentionPolicy.SOURCE) + public @interface KeystoreMigrationStatus { } + + /** * Mapping of Store file Id to Store file names. * * NOTE: This is the default path for the files on AOSP devices. If the OEM has modified @@ -572,14 +605,17 @@ public final class WifiMigration { /** * Migrate any certificates in Legacy Keystore to the newer WifiBlobstore database. * + * If there are no certificates to migrate, this method will return immediately. + * * @hide */ @FlaggedApi(Flags.FLAG_LEGACY_KEYSTORE_TO_WIFI_BLOBSTORE_MIGRATION_READ_ONLY) @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static void migrateLegacyKeystoreToWifiBlobstore() { + public static @KeystoreMigrationStatus int migrateLegacyKeystoreToWifiBlobstore() { if (!WifiBlobStore.supplicantCanAccessBlobstore()) { + // Supplicant cannot access WifiBlobstore, so keep the certs in Legacy Keystore Log.i(TAG, "Avoiding migration since supplicant cannot access WifiBlobstore"); - return; + return KEYSTORE_MIGRATION_SUCCESS_MIGRATION_NOT_NEEDED; } final long identity = Binder.clearCallingIdentity(); try { @@ -587,7 +623,7 @@ public final class WifiMigration { String[] legacyAliases = legacyKeystore.list("", Process.WIFI_UID); if (legacyAliases == null || legacyAliases.length == 0) { Log.i(TAG, "No aliases need to be migrated"); - return; + return KEYSTORE_MIGRATION_SUCCESS_MIGRATION_NOT_NEEDED; } WifiBlobStore wifiBlobStore = WifiBlobStore.getInstance(); @@ -605,14 +641,17 @@ public final class WifiMigration { legacyKeystore.remove(legacyAlias, Process.WIFI_UID); } Log.i(TAG, "Successfully migrated aliases from Legacy Keystore"); + return KEYSTORE_MIGRATION_SUCCESS_MIGRATION_COMPLETE; } catch (ServiceSpecificException e) { if (e.errorCode == ILegacyKeystore.ERROR_SYSTEM_ERROR) { Log.i(TAG, "Legacy Keystore service has been deprecated"); - } else { - Log.e(TAG, "Encountered an exception while migrating aliases. " + e); + return KEYSTORE_MIGRATION_SUCCESS_MIGRATION_NOT_NEEDED; } + Log.e(TAG, "Encountered a ServiceSpecificException while migrating aliases. " + e); + return KEYSTORE_MIGRATION_FAILURE_ENCOUNTERED_EXCEPTION; } catch (Exception e) { Log.e(TAG, "Encountered an exception while migrating aliases. " + e); + return KEYSTORE_MIGRATION_FAILURE_ENCOUNTERED_EXCEPTION; } finally { Binder.restoreCallingIdentity(identity); } diff --git a/wifi/tests/src/android/net/wifi/WifiMigrationTest.java b/wifi/tests/src/android/net/wifi/WifiMigrationTest.java index d95069d46879..0aa299f959fe 100644 --- a/wifi/tests/src/android/net/wifi/WifiMigrationTest.java +++ b/wifi/tests/src/android/net/wifi/WifiMigrationTest.java @@ -16,6 +16,7 @@ package android.net.wifi; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; @@ -27,6 +28,8 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; +import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.security.legacykeystore.ILegacyKeystore; import com.android.dx.mockito.inline.extended.ExtendedMockito; @@ -77,7 +80,8 @@ public class WifiMigrationTest { @Test public void testKeystoreMigrationAvoidedOnLegacyVendorPartition() { when(WifiBlobStore.supplicantCanAccessBlobstore()).thenReturn(false); - WifiMigration.migrateLegacyKeystoreToWifiBlobstore(); + assertEquals(WifiMigration.KEYSTORE_MIGRATION_SUCCESS_MIGRATION_NOT_NEEDED, + WifiMigration.migrateLegacyKeystoreToWifiBlobstore()); verifyNoMoreInteractions(mLegacyKeystore, mWifiBlobStore); } @@ -88,7 +92,8 @@ public class WifiMigrationTest { @Test public void testKeystoreMigrationNoLegacyAliases() throws Exception { when(mLegacyKeystore.list(anyString(), anyInt())).thenReturn(new String[0]); - WifiMigration.migrateLegacyKeystoreToWifiBlobstore(); + assertEquals(WifiMigration.KEYSTORE_MIGRATION_SUCCESS_MIGRATION_NOT_NEEDED, + WifiMigration.migrateLegacyKeystoreToWifiBlobstore()); verify(mLegacyKeystore).list(anyString(), anyInt()); verifyNoMoreInteractions(mLegacyKeystore, mWifiBlobStore); } @@ -104,7 +109,8 @@ public class WifiMigrationTest { when(mLegacyKeystore.list(anyString(), anyInt())).thenReturn(legacyAliases); when(mWifiBlobStore.list(anyString())).thenReturn(blobstoreAliases); - WifiMigration.migrateLegacyKeystoreToWifiBlobstore(); + assertEquals(WifiMigration.KEYSTORE_MIGRATION_SUCCESS_MIGRATION_COMPLETE, + WifiMigration.migrateLegacyKeystoreToWifiBlobstore()); verify(mWifiBlobStore, times(legacyAliases.length)).put(anyString(), any(byte[].class)); } @@ -122,9 +128,35 @@ public class WifiMigrationTest { when(mWifiBlobStore.list(anyString())).thenReturn(blobstoreAliases); // Expect that only the unique legacy alias is migrated to the blobstore - WifiMigration.migrateLegacyKeystoreToWifiBlobstore(); + assertEquals(WifiMigration.KEYSTORE_MIGRATION_SUCCESS_MIGRATION_COMPLETE, + WifiMigration.migrateLegacyKeystoreToWifiBlobstore()); verify(mWifiBlobStore).list(anyString()); verify(mWifiBlobStore).put(eq(uniqueLegacyAlias), any(byte[].class)); verifyNoMoreInteractions(mWifiBlobStore); } + + /** + * Verify that the Keystore migration is skipped if Legacy Keystore is deprecated, + * since the migration is not needed. + */ + @Test + public void testKeystoreMigrationAvoidedIfLegacyKsDeprecated() throws Exception { + // Legacy Keystore will throw a ServiceSpecificException with + // code ERROR_SYSTEM_ERROR if a method is deprecated + when(mLegacyKeystore.list(anyString(), anyInt())).thenThrow( + new ServiceSpecificException(ILegacyKeystore.ERROR_SYSTEM_ERROR)); + assertEquals(WifiMigration.KEYSTORE_MIGRATION_SUCCESS_MIGRATION_NOT_NEEDED, + WifiMigration.migrateLegacyKeystoreToWifiBlobstore()); + } + + /** + * Verify that the Keystore migration method returns a failure code when an + * unexpected exception is encountered. + */ + @Test + public void testKeystoreMigrationFailsIfExceptionEncountered() throws Exception { + when(mLegacyKeystore.list(anyString(), anyInt())).thenThrow(new RemoteException()); + assertEquals(WifiMigration.KEYSTORE_MIGRATION_FAILURE_ENCOUNTERED_EXCEPTION, + WifiMigration.migrateLegacyKeystoreToWifiBlobstore()); + } } |