diff options
549 files changed, 8440 insertions, 2827 deletions
diff --git a/GAME_MANAGER_OWNERS b/GAME_MANAGER_OWNERS new file mode 100644 index 000000000000..502a9e362202 --- /dev/null +++ b/GAME_MANAGER_OWNERS @@ -0,0 +1,2 @@ +lpy@google.com +timvp@google.com diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java index 8a6c60f44702..1cd5d964e36f 100644 --- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java +++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java @@ -138,6 +138,21 @@ public class StaticLayoutPerfTest { } @Test + public void testCreate_RandomText_NoStyled_Balanced_Hyphenation_Fast() { + final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + state.pauseTiming(); + final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT); + state.resumeTiming(); + + StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) + .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL_FAST) + .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) + .build(); + } + } + + @Test public void testCreate_RandomText_Styled_Greedy_NoHyphenation() { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java index b02e80118814..c147ef83dcf0 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java @@ -2012,9 +2012,8 @@ public final class QuotaController extends StateController { if (DEBUG) { Slog.v(TAG, "Starting to track " + jobStatus.toShortString()); } - // Always track jobs, even when charging. - mRunningBgJobs.add(jobStatus); - if (shouldTrackLocked()) { + // Always maintain list of running jobs, even when quota is free. + if (mRunningBgJobs.add(jobStatus) && shouldTrackLocked()) { mBgJobCount++; if (mRegularJobTimer) { incrementJobCountLocked(mPkg.userId, mPkg.packageName, 1); diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 59f602c11247..af4053fb6c8c 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -1576,7 +1576,7 @@ bool BootAnimation::playAnimation(const Animation& animation) { int err; do { err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, nullptr); - } while (err<0 && errno == EINTR); + } while (err == EINTR); } checkExit(); diff --git a/core/api/current.txt b/core/api/current.txt index ea552665c71d..9d74a8c9ced5 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -1204,6 +1204,7 @@ package android { field public static final int requiredSplitTypes; field public static final int requiresFadingEdge = 16843685; // 0x10103a5 field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364 + field public static final int resetEnabledSettingsOnAppDataCleared; field public static final int resizeClip = 16843983; // 0x10104cf field public static final int resizeMode = 16843619; // 0x1010363 field public static final int resizeable = 16843405; // 0x101028d @@ -9625,6 +9626,7 @@ package android.bluetooth.le { method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData(); method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids(); method public java.util.List<android.os.ParcelUuid> getServiceUuids(); + method @NonNull public java.util.List<android.bluetooth.le.TransportDiscoveryData> getTransportDiscoveryData(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseData> CREATOR; } @@ -9635,6 +9637,7 @@ package android.bluetooth.le { method public android.bluetooth.le.AdvertiseData.Builder addServiceData(android.os.ParcelUuid, byte[]); method @NonNull public android.bluetooth.le.AdvertiseData.Builder addServiceSolicitationUuid(@NonNull android.os.ParcelUuid); method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid); + method @NonNull public android.bluetooth.le.AdvertiseData.Builder addTransportDiscoveryData(@NonNull android.bluetooth.le.TransportDiscoveryData); method public android.bluetooth.le.AdvertiseData build(); method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean); method public android.bluetooth.le.AdvertiseData.Builder setIncludeTxPowerLevel(boolean); @@ -9894,6 +9897,31 @@ package android.bluetooth.le { method public android.bluetooth.le.ScanSettings.Builder setScanMode(int); } + public final class TransportBlock implements android.os.Parcelable { + ctor public TransportBlock(int, int, int, @Nullable byte[]); + method public int describeContents(); + method public int getOrgId(); + method public int getTdsFlags(); + method @Nullable public byte[] getTransportData(); + method public int getTransportDataLength(); + method @Nullable public byte[] toByteArray(); + method public int totalBytes(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportBlock> CREATOR; + } + + public final class TransportDiscoveryData implements android.os.Parcelable { + ctor public TransportDiscoveryData(int, @NonNull java.util.List<android.bluetooth.le.TransportBlock>); + ctor public TransportDiscoveryData(@NonNull byte[]); + method public int describeContents(); + method @NonNull public java.util.List<android.bluetooth.le.TransportBlock> getTransportBlocks(); + method public int getTransportDataType(); + method @Nullable public byte[] toByteArray(); + method public int totalBytes(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportDiscoveryData> CREATOR; + } + } package android.companion { @@ -17273,8 +17301,12 @@ package android.graphics.text { method @NonNull public android.graphics.text.MeasuredText.Builder appendReplacementRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, @FloatRange(from=0) @Px float); method @NonNull public android.graphics.text.MeasuredText.Builder appendStyleRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, boolean); method @NonNull public android.graphics.text.MeasuredText build(); - method @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean); + method @Deprecated @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean); + method @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(int); method @NonNull public android.graphics.text.MeasuredText.Builder setComputeLayout(boolean); + field public static final int HYPHENATION_MODE_FAST = 2; // 0x2 + field public static final int HYPHENATION_MODE_NONE = 0; // 0x0 + field public static final int HYPHENATION_MODE_NORMAL = 1; // 0x1 } public final class PositionedGlyphs { @@ -27606,6 +27638,7 @@ package android.nfc.cardemulation { field public static final String CATEGORY_PAYMENT = "payment"; field public static final String EXTRA_CATEGORY = "category"; field public static final String EXTRA_SERVICE_COMPONENT = "component"; + field public static final String EXTRA_USERID = "android.nfc.cardemulation.extra.USERID"; field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1 field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2 field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0 @@ -40645,7 +40678,7 @@ package android.telecom { method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts(); method public String getDefaultDialerPackage(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telecom.PhoneAccountHandle getDefaultOutgoingPhoneAccount(String); - method @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_SMS, android.Manifest.permission.READ_PHONE_NUMBERS}, conditional=true) public String getLine1Number(android.telecom.PhoneAccountHandle); + method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_SMS, android.Manifest.permission.READ_PHONE_NUMBERS}, conditional=true) public String getLine1Number(android.telecom.PhoneAccountHandle); method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getSelfManagedPhoneAccounts(); method public android.telecom.PhoneAccountHandle getSimCallManager(); @@ -42713,7 +42746,7 @@ package android.telephony { method @Nullable public String getMccString(); method @Deprecated public int getMnc(); method @Nullable public String getMncString(); - method public String getNumber(); + method @Deprecated public String getNumber(); method public int getPortIndex(); method public int getSimSlotIndex(); method public int getSubscriptionId(); @@ -42968,7 +43001,7 @@ package android.telephony { method public String getIccAuthentication(int, int, String); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getImei(); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getImei(int); - method @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_SMS, android.Manifest.permission.READ_PHONE_NUMBERS}) public String getLine1Number(); + method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_SMS, android.Manifest.permission.READ_PHONE_NUMBERS}) public String getLine1Number(); method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public String getManualNetworkSelectionPlmn(); method @Nullable public String getManufacturerCode(); method @Nullable public String getManufacturerCode(int); @@ -43053,7 +43086,7 @@ package android.telephony { method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabledForReason(int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setForbiddenPlmns(@NonNull java.util.List<java.lang.String>); - method public boolean setLine1NumberForDisplay(String, String); + method @Deprecated public boolean setLine1NumberForDisplay(String, String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setNetworkSelectionModeAutomatic(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(String, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(@NonNull String, boolean, int); @@ -44523,8 +44556,10 @@ package android.text { field public static final int DIR_LEFT_TO_RIGHT = 1; // 0x1 field public static final int DIR_RIGHT_TO_LEFT = -1; // 0xffffffff field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2 + field public static final int HYPHENATION_FREQUENCY_FULL_FAST = 4; // 0x4 field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0 field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1 + field public static final int HYPHENATION_FREQUENCY_NORMAL_FAST = 3; // 0x3 field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1 field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0 } diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 29a445322085..6d342db6cdf9 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -961,20 +961,20 @@ package android.app.admin { method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public boolean getBluetoothContactSharingDisabled(@NonNull android.os.UserHandle); method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwner(); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public android.content.ComponentName getDeviceOwnerComponentOnAnyUser(); - method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwnerNameOnAnyUser(); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public String getDeviceOwnerNameOnAnyUser(); method @Nullable public CharSequence getDeviceOwnerOrganizationName(); method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getDeviceOwnerUser(); method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<java.lang.String> getPermittedAccessibilityServices(int); method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<java.lang.String> getPermittedInputMethodsForCurrentUser(); method @Nullable public android.content.ComponentName getProfileOwner() throws java.lang.IllegalArgumentException; - method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getProfileOwnerNameAsUser(int) throws java.lang.IllegalArgumentException; - method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserProvisioningState(); + method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public String getProfileOwnerNameAsUser(int) throws java.lang.IllegalArgumentException; + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public int getUserProvisioningState(); method public boolean isDeviceManaged(); method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioned(); method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioningConfigApplied(); - method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isManagedKiosk(); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public boolean isManagedKiosk(); method public boolean isSecondaryLockscreenEnabled(@NonNull android.os.UserHandle); - method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isUnattendedManagedKiosk(); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public boolean isUnattendedManagedKiosk(); method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long); method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long, boolean); method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean packageHasActiveAdmins(String); @@ -8681,7 +8681,11 @@ package android.os { } public final class NewUserRequest { + method @Nullable public String getAccountName(); + method @Nullable public android.os.PersistableBundle getAccountOptions(); + method @Nullable public String getAccountType(); method @Nullable public String getName(); + method @Nullable public android.graphics.Bitmap getUserIcon(); method @NonNull public String getUserType(); method public boolean isAdmin(); method public boolean isEphemeral(); @@ -8690,9 +8694,13 @@ package android.os { public static final class NewUserRequest.Builder { ctor public NewUserRequest.Builder(); method @NonNull public android.os.NewUserRequest build(); + method @NonNull public android.os.NewUserRequest.Builder setAccountName(@Nullable String); + method @NonNull public android.os.NewUserRequest.Builder setAccountOptions(@Nullable android.os.PersistableBundle); + method @NonNull public android.os.NewUserRequest.Builder setAccountType(@Nullable String); method @NonNull public android.os.NewUserRequest.Builder setAdmin(); method @NonNull public android.os.NewUserRequest.Builder setEphemeral(); method @NonNull public android.os.NewUserRequest.Builder setName(@Nullable String); + method @NonNull public android.os.NewUserRequest.Builder setUserIcon(@Nullable android.graphics.Bitmap); method @NonNull public android.os.NewUserRequest.Builder setUserType(@NonNull String); } @@ -8970,6 +8978,7 @@ package android.os { method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean removeUser(@NonNull android.os.UserHandle); method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(@NonNull android.graphics.Bitmap) throws android.os.UserManager.UserOperationException; method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserName(@Nullable String); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean someUserHasAccount(@NonNull String, @NonNull String); field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED"; field @Deprecated public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock"; field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background"; @@ -8981,6 +8990,7 @@ package android.os { field public static final int SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED = 4; // 0x4 field public static final int SWITCHABILITY_STATUS_USER_IN_CALL = 1; // 0x1 field public static final int SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED = 2; // 0x2 + field public static final int USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS = 7; // 0x7 field public static final String USER_TYPE_FULL_GUEST = "android.os.usertype.full.GUEST"; field public static final String USER_TYPE_FULL_SECONDARY = "android.os.usertype.full.SECONDARY"; field public static final String USER_TYPE_FULL_SYSTEM = "android.os.usertype.full.SYSTEM"; @@ -13164,6 +13174,7 @@ package android.telephony.ims { method @NonNull public java.util.Set<android.telephony.ims.FeatureTagState> getDeregisteredFeatureTags(); method @NonNull public java.util.Set<android.telephony.ims.FeatureTagState> getDeregisteringFeatureTags(); method @NonNull public java.util.Set<java.lang.String> getRegisteredFeatureTags(); + method @NonNull public java.util.Set<java.lang.String> getRegisteringFeatureTags(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.DelegateRegistrationState> CREATOR; field public static final int DEREGISTERED_REASON_NOT_PROVISIONED = 1; // 0x1 @@ -13181,6 +13192,7 @@ package android.telephony.ims { method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addDeregisteringFeatureTag(@NonNull String, int); method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addRegisteredFeatureTag(@NonNull String); method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addRegisteredFeatureTags(@NonNull java.util.Set<java.lang.String>); + method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addRegisteringFeatureTags(@NonNull java.util.Set<java.lang.String>); method @NonNull public android.telephony.ims.DelegateRegistrationState build(); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 6bfde9ab1a29..af907af2ce0d 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -6791,7 +6791,7 @@ public class Notification implements Parcelable // We show these sorts of notifications immediately in the absence of // any explicit app declaration - if (isMediaNotification() || hasMediaSession() + if (isMediaNotification() || CATEGORY_CALL.equals(category) || CATEGORY_NAVIGATION.equals(category) || (actions != null && actions.length > 0)) { @@ -6811,14 +6811,6 @@ public class Notification implements Parcelable } /** - * @return whether this notification has a media session attached - * @hide - */ - public boolean hasMediaSession() { - return extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) != null; - } - - /** * @return the style class of this notification * @hide */ @@ -6861,18 +6853,20 @@ public class Notification implements Parcelable } /** - * @return true if this is a media notification + * @return true if this is a media style notification with a media session * * @hide */ public boolean isMediaNotification() { Class<? extends Style> style = getNotificationStyle(); - if (MediaStyle.class.equals(style)) { - return true; - } else if (DecoratedMediaCustomViewStyle.class.equals(style)) { - return true; - } - return false; + boolean isMediaStyle = (MediaStyle.class.equals(style) + || DecoratedMediaCustomViewStyle.class.equals(style)); + + boolean hasMediaSession = (extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) != null + && extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) + instanceof MediaSession.Token); + + return isMediaStyle && hasMediaSession; } /** diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS index 1da0a74cd0e7..e099716cd45a 100644 --- a/core/java/android/app/OWNERS +++ b/core/java/android/app/OWNERS @@ -30,6 +30,8 @@ per-file Service* = file:/services/core/java/com/android/server/am/OWNERS per-file SystemServiceRegistry.java = file:/services/core/java/com/android/server/am/OWNERS per-file *UserSwitchObserver* = file:/services/core/java/com/android/server/am/OWNERS per-file UiAutomation.java = file:/services/accessibility/OWNERS +per-file GameManager* = file:/GAME_MANAGER_OWNERS +per-file IGameManager* = file:/GAME_MANAGER_OWNERS # ActivityThread per-file ActivityThread.java = file:/services/core/java/com/android/server/am/OWNERS diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index d2963fb71327..57b319634759 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -684,8 +684,9 @@ public class DevicePolicyManager { * A String extra holding the time zone {@link android.app.AlarmManager} that the device * will be set to. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner - * provisioning via an NFC bump. + * <p>Use only for device owner provisioning. This extra can be returned by the admin app when + * performing the admin-integrated provisioning flow as a result of the {@link + * #ACTION_GET_PROVISIONING_MODE} activity. */ public static final String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE"; @@ -694,8 +695,9 @@ public class DevicePolicyManager { * A Long extra holding the wall clock time (in milliseconds) to be set on the device's * {@link android.app.AlarmManager}. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner - * provisioning via an NFC bump. + * <p>Use only for device owner provisioning. This extra can be returned by the admin app when + * performing the admin-integrated provisioning flow as a result of the {@link + * #ACTION_GET_PROVISIONING_MODE} activity. */ public static final String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME"; @@ -704,8 +706,9 @@ public class DevicePolicyManager { * A String extra holding the {@link java.util.Locale} that the device will be set to. * Format: xx_yy, where xx is the language code, and yy the country code. * - * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner - * provisioning via an NFC bump. + * <p>Use only for device owner provisioning. This extra can be returned by the admin app when + * performing the admin-integrated provisioning flow as a result of the {@link + * #ACTION_GET_PROVISIONING_MODE} activity. */ public static final String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE"; @@ -1001,7 +1004,10 @@ public class DevicePolicyManager { * The default for this extra is {@code false} - by default, the admin of a fully-managed * device has the ability to grant sensors-related permissions. * - * <p>Use only for device owner provisioning. + * <p>Use only for device owner provisioning. This extra can be returned by the + * admin app when performing the admin-integrated provisioning flow as a result of the + * {@link #ACTION_GET_PROVISIONING_MODE} activity. + * * @see #ACTION_GET_PROVISIONING_MODE */ public static final String EXTRA_PROVISIONING_SENSORS_PERMISSION_GRANT_OPT_OUT = @@ -1070,6 +1076,9 @@ public class DevicePolicyManager { * * <p>From {@link android.os.Build.VERSION_CODES#N} onwards, this is also supported for an * intent with action {@link #ACTION_PROVISION_MANAGED_PROFILE}. + * + * <p>This extra can also be returned by the admin app when performing the admin-integrated + * provisioning flow as a result of the {@link #ACTION_GET_PROVISIONING_MODE} activity. */ public static final String EXTRA_PROVISIONING_SKIP_ENCRYPTION = "android.app.extra.PROVISIONING_SKIP_ENCRYPTION"; @@ -1109,8 +1118,9 @@ public class DevicePolicyManager { * * <p> Maximum 3 key-value pairs can be specified. The rest will be ignored. * - * <p> Use in an intent with action {@link #ACTION_PROVISION_MANAGED_PROFILE} or - * {@link #ACTION_PROVISION_MANAGED_DEVICE} + * <p> Can be used in an intent with action {@link #ACTION_PROVISION_MANAGED_PROFILE}. This + * extra can also be returned by the admin app when performing the admin-integrated + * provisioning flow as a result of the {@link #ACTION_GET_PROVISIONING_MODE} activity. */ public static final String EXTRA_PROVISIONING_DISCLAIMERS = "android.app.extra.PROVISIONING_DISCLAIMERS"; @@ -7857,7 +7867,7 @@ public class DevicePolicyManager { @SystemApi @RequiresPermission(anyOf = { android.Manifest.permission.MANAGE_USERS, - android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, + android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS }) public ComponentName getDeviceOwnerComponentOnAnyUser() { return getDeviceOwnerComponentInner(/* callingUserOnly =*/ false); @@ -7970,8 +7980,8 @@ public class DevicePolicyManager { * Called by the system to find out whether the device is managed by a Device Owner. * * @return whether the device is managed by a Device Owner. - * @throws SecurityException if the caller is not the device owner, does not hold the - * MANAGE_USERS permission and is not the system. + * @throws SecurityException if the caller is not the device owner, does not hold + * MANAGE_USERS or MANAGE_PROFILE_AND_DEVICE_OWNERS permissions and is not the system. * * @hide */ @@ -7992,7 +8002,10 @@ public class DevicePolicyManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS + }) public String getDeviceOwnerNameOnAnyUser() { throwIfParentInstance("getDeviceOwnerNameOnAnyUser"); if (mService != null) { @@ -8382,7 +8395,10 @@ public class DevicePolicyManager { * @throws IllegalArgumentException if the userId is invalid. */ @SystemApi - @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS + }) public @Nullable String getProfileOwnerNameAsUser(int userId) throws IllegalArgumentException { throwIfParentInstance("getProfileOwnerNameAsUser"); if (mService != null) { @@ -11920,7 +11936,10 @@ public class DevicePolicyManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS + }) @UserProvisioningState public int getUserProvisioningState() { throwIfParentInstance("getUserProvisioningState"); @@ -13429,7 +13448,10 @@ public class DevicePolicyManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS + }) public boolean isManagedKiosk() { throwIfParentInstance("isManagedKiosk"); if (mService != null) { @@ -13458,7 +13480,10 @@ public class DevicePolicyManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS + }) public boolean isUnattendedManagedKiosk() { throwIfParentInstance("isUnattendedManagedKiosk"); if (mService != null) { diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java index cec658049ca5..fdf62ec3a647 100644 --- a/core/java/android/bluetooth/le/AdvertiseData.java +++ b/core/java/android/bluetooth/le/AdvertiseData.java @@ -25,6 +25,7 @@ import android.util.ArrayMap; import android.util.SparseArray; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -47,6 +48,9 @@ public final class AdvertiseData implements Parcelable { @NonNull private final List<ParcelUuid> mServiceSolicitationUuids; + @Nullable + private final List<TransportDiscoveryData> mTransportDiscoveryData; + private final SparseArray<byte[]> mManufacturerSpecificData; private final Map<ParcelUuid, byte[]> mServiceData; private final boolean mIncludeTxPowerLevel; @@ -54,12 +58,14 @@ public final class AdvertiseData implements Parcelable { private AdvertiseData(List<ParcelUuid> serviceUuids, List<ParcelUuid> serviceSolicitationUuids, + List<TransportDiscoveryData> transportDiscoveryData, SparseArray<byte[]> manufacturerData, Map<ParcelUuid, byte[]> serviceData, boolean includeTxPowerLevel, boolean includeDeviceName) { mServiceUuids = serviceUuids; mServiceSolicitationUuids = serviceSolicitationUuids; + mTransportDiscoveryData = transportDiscoveryData; mManufacturerSpecificData = manufacturerData; mServiceData = serviceData; mIncludeTxPowerLevel = includeTxPowerLevel; @@ -83,6 +89,17 @@ public final class AdvertiseData implements Parcelable { } /** + * Returns a list of {@link TransportDiscoveryData} within the advertisement. + */ + @NonNull + public List<TransportDiscoveryData> getTransportDiscoveryData() { + if (mTransportDiscoveryData == null) { + return Collections.emptyList(); + } + return mTransportDiscoveryData; + } + + /** * Returns an array of manufacturer Id and the corresponding manufacturer specific data. The * manufacturer id is a non-negative number assigned by Bluetooth SIG. */ @@ -116,8 +133,8 @@ public final class AdvertiseData implements Parcelable { */ @Override public int hashCode() { - return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mManufacturerSpecificData, - mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel); + return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mTransportDiscoveryData, + mManufacturerSpecificData, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel); } /** @@ -134,6 +151,7 @@ public final class AdvertiseData implements Parcelable { AdvertiseData other = (AdvertiseData) obj; return Objects.equals(mServiceUuids, other.mServiceUuids) && Objects.equals(mServiceSolicitationUuids, other.mServiceSolicitationUuids) + && Objects.equals(mTransportDiscoveryData, other.mTransportDiscoveryData) && BluetoothLeUtils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) && BluetoothLeUtils.equals(mServiceData, other.mServiceData) @@ -144,7 +162,8 @@ public final class AdvertiseData implements Parcelable { @Override public String toString() { return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mServiceSolicitationUuids=" - + mServiceSolicitationUuids + ", mManufacturerSpecificData=" + + mServiceSolicitationUuids + ", mTransportDiscoveryData=" + + mTransportDiscoveryData + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData) + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" @@ -162,6 +181,8 @@ public final class AdvertiseData implements Parcelable { dest.writeTypedArray(mServiceSolicitationUuids.toArray( new ParcelUuid[mServiceSolicitationUuids.size()]), flags); + dest.writeTypedList(mTransportDiscoveryData); + // mManufacturerSpecificData could not be null. dest.writeInt(mManufacturerSpecificData.size()); for (int i = 0; i < mManufacturerSpecificData.size(); ++i) { @@ -197,6 +218,12 @@ public final class AdvertiseData implements Parcelable { builder.addServiceSolicitationUuid(uuid); } + List<TransportDiscoveryData> transportDiscoveryData = + in.createTypedArrayList(TransportDiscoveryData.CREATOR); + for (TransportDiscoveryData tdd : transportDiscoveryData) { + builder.addTransportDiscoveryData(tdd); + } + int manufacturerSize = in.readInt(); for (int i = 0; i < manufacturerSize; ++i) { int manufacturerId = in.readInt(); @@ -223,6 +250,9 @@ public final class AdvertiseData implements Parcelable { private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>(); @NonNull private List<ParcelUuid> mServiceSolicitationUuids = new ArrayList<ParcelUuid>(); + @Nullable + private List<TransportDiscoveryData> mTransportDiscoveryData = + new ArrayList<TransportDiscoveryData>(); private SparseArray<byte[]> mManufacturerSpecificData = new SparseArray<byte[]>(); private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>(); private boolean mIncludeTxPowerLevel; @@ -256,6 +286,7 @@ public final class AdvertiseData implements Parcelable { mServiceSolicitationUuids.add(serviceSolicitationUuid); return this; } + /** * Add service data to advertise data. * @@ -274,6 +305,23 @@ public final class AdvertiseData implements Parcelable { } /** + * Add Transport Discovery Data to advertise data. + * + * @param transportDiscoveryData Transport Discovery Data, consisting of one or more + * Transport Blocks. Transport Discovery Data AD Type Code is already included. + * @throws IllegalArgumentException If the {@code transportDiscoveryData} is empty + */ + @NonNull + public Builder addTransportDiscoveryData( + @NonNull TransportDiscoveryData transportDiscoveryData) { + if (transportDiscoveryData == null) { + throw new IllegalArgumentException("transportDiscoveryData is null"); + } + mTransportDiscoveryData.add(transportDiscoveryData); + return this; + } + + /** * Add manufacturer specific data. * <p> * Please refer to the Bluetooth Assigned Numbers document provided by the <a @@ -319,8 +367,8 @@ public final class AdvertiseData implements Parcelable { */ public AdvertiseData build() { return new AdvertiseData(mServiceUuids, mServiceSolicitationUuids, - mManufacturerSpecificData, mServiceData, mIncludeTxPowerLevel, - mIncludeDeviceName); + mTransportDiscoveryData, mManufacturerSpecificData, mServiceData, + mIncludeTxPowerLevel, mIncludeDeviceName); } } } diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java index 58029745ab9c..b9f8a57a75ea 100644 --- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java +++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java @@ -567,6 +567,9 @@ public final class BluetoothLeAdvertiser { + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT; } } + for (TransportDiscoveryData transportDiscoveryData : data.getTransportDiscoveryData()) { + size += OVERHEAD_BYTES_PER_FIELD + transportDiscoveryData.totalBytes(); + } for (ParcelUuid uuid : data.getServiceData().keySet()) { int uuidLen = BluetoothUuid.uuidToBytes(uuid).length; size += OVERHEAD_BYTES_PER_FIELD + uuidLen diff --git a/core/java/android/bluetooth/le/TransportBlock.java b/core/java/android/bluetooth/le/TransportBlock.java new file mode 100644 index 000000000000..b388beda6b3b --- /dev/null +++ b/core/java/android/bluetooth/le/TransportBlock.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth.le; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; + +/** + * Wrapper for Transport Discovery Data Transport Blocks. + * This class represents a Transport Block from a Transport Discovery Data. + * + * @see TransportDiscoveryData + * @see AdvertiseData + */ +public final class TransportBlock implements Parcelable { + private static final String TAG = "TransportBlock"; + private final int mOrgId; + private final int mTdsFlags; + private final int mTransportDataLength; + private final byte[] mTransportData; + + /** + * Creates an instance of TransportBlock from raw data. + * + * @param orgId the Organization ID + * @param tdsFlags the TDS flags + * @param transportDataLength the total length of the Transport Data + * @param transportData the Transport Data + */ + public TransportBlock(int orgId, int tdsFlags, int transportDataLength, + @Nullable byte[] transportData) { + mOrgId = orgId; + mTdsFlags = tdsFlags; + mTransportDataLength = transportDataLength; + mTransportData = transportData; + } + + private TransportBlock(Parcel in) { + mOrgId = in.readInt(); + mTdsFlags = in.readInt(); + mTransportDataLength = in.readInt(); + mTransportData = new byte[mTransportDataLength]; + in.readByteArray(mTransportData); + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mOrgId); + dest.writeInt(mTdsFlags); + dest.writeInt(mTransportDataLength); + dest.writeByteArray(mTransportData); + } + + /** + * @hide + */ + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Creator<TransportBlock> CREATOR = new Creator<TransportBlock>() { + @Override + public TransportBlock createFromParcel(Parcel in) { + return new TransportBlock(in); + } + + @Override + public TransportBlock[] newArray(int size) { + return new TransportBlock[size]; + } + }; + + /** + * Gets the Organization ID of the Transport Block which corresponds to one of the + * the Bluetooth SIG Assigned Numbers. + */ + public int getOrgId() { + return mOrgId; + } + + /** + * Gets the TDS flags of the Transport Block which represents the role of the device and + * information about its state and supported features. + */ + public int getTdsFlags() { + return mTdsFlags; + } + + /** + * Gets the total number of octets in the Transport Data field in this Transport Block. + */ + public int getTransportDataLength() { + return mTransportDataLength; + } + + /** + * Gets the Transport Data of the Transport Block which contains organization-specific data. + */ + @Nullable + public byte[] getTransportData() { + return mTransportData; + } + + /** + * Converts this TransportBlock to byte array + * + * @return byte array representation of this Transport Block or null if the conversion failed + */ + @Nullable + public byte[] toByteArray() { + try { + ByteBuffer buffer = ByteBuffer.allocate(totalBytes()); + buffer.put((byte) mOrgId); + buffer.put((byte) mTdsFlags); + buffer.put((byte) mTransportDataLength); + if (mTransportData != null) { + buffer.put(mTransportData); + } + return buffer.array(); + } catch (BufferOverflowException e) { + Log.e(TAG, "Error converting to byte array: " + e.toString()); + return null; + } + } + + /** + * @return total byte count of this TransportBlock + */ + public int totalBytes() { + // 3 uint8 + byte[] length + int size = 3 + mTransportDataLength; + return size; + } +} diff --git a/core/java/android/bluetooth/le/TransportDiscoveryData.java b/core/java/android/bluetooth/le/TransportDiscoveryData.java new file mode 100644 index 000000000000..c8e97f9a823a --- /dev/null +++ b/core/java/android/bluetooth/le/TransportDiscoveryData.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth.le; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import java.nio.BufferOverflowException; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Wrapper for Transport Discovery Data AD Type. + * This class contains the Transport Discovery Data AD Type Code as well as + * a list of potential Transport Blocks. + * + * @see AdvertiseData + */ +public final class TransportDiscoveryData implements Parcelable { + private static final String TAG = "TransportDiscoveryData"; + private final int mTransportDataType; + private final List<TransportBlock> mTransportBlocks; + + /** + * Creates a TransportDiscoveryData instance. + * + * @param transportDataType the Transport Discovery Data AD Type + * @param transportBlocks the list of Transport Blocks + */ + public TransportDiscoveryData(int transportDataType, + @NonNull List<TransportBlock> transportBlocks) { + mTransportDataType = transportDataType; + mTransportBlocks = transportBlocks; + } + + /** + * Creates a TransportDiscoveryData instance from byte arrays. + * + * Uses the transport discovery data bytes and parses them into an usable class. + * + * @param transportDiscoveryData the raw discovery data + */ + public TransportDiscoveryData(@NonNull byte[] transportDiscoveryData) { + ByteBuffer byteBuffer = ByteBuffer.wrap(transportDiscoveryData); + mTransportBlocks = new ArrayList(); + if (byteBuffer.remaining() > 0) { + mTransportDataType = byteBuffer.get(); + } else { + mTransportDataType = -1; + } + try { + while (byteBuffer.remaining() > 0) { + int orgId = byteBuffer.get(); + int tdsFlags = byteBuffer.get(); + int transportDataLength = byteBuffer.get(); + byte[] transportData = new byte[transportDataLength]; + byteBuffer.get(transportData, 0, transportDataLength); + mTransportBlocks.add(new TransportBlock(orgId, tdsFlags, + transportDataLength, transportData)); + } + } catch (BufferUnderflowException e) { + Log.e(TAG, "Error while parsing data: " + e.toString()); + } + } + + private TransportDiscoveryData(Parcel in) { + mTransportDataType = in.readInt(); + mTransportBlocks = in.createTypedArrayList(TransportBlock.CREATOR); + } + + /** + * @hide + */ + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mTransportDataType); + dest.writeTypedList(mTransportBlocks); + } + + public static final @NonNull Creator<TransportDiscoveryData> CREATOR = + new Creator<TransportDiscoveryData>() { + @Override + public TransportDiscoveryData createFromParcel(Parcel in) { + return new TransportDiscoveryData(in); + } + + @Override + public TransportDiscoveryData[] newArray(int size) { + return new TransportDiscoveryData[size]; + } + }; + + /** + * Gets the transport data type. + */ + public int getTransportDataType() { + return mTransportDataType; + } + + /** + * @return the list of {@link TransportBlock} in this TransportDiscoveryData + * or an empty list if there are no Transport Blocks + */ + @NonNull + public List<TransportBlock> getTransportBlocks() { + if (mTransportBlocks == null) { + return Collections.emptyList(); + } + return mTransportBlocks; + } + + /** + * Converts this TransportDiscoveryData to byte array + * + * @return byte array representation of this Transport Discovery Data or null if the + * conversion failed + */ + @Nullable + public byte[] toByteArray() { + try { + ByteBuffer buffer = ByteBuffer.allocate(totalBytes()); + buffer.put((byte) mTransportDataType); + for (TransportBlock transportBlock : getTransportBlocks()) { + buffer.put(transportBlock.toByteArray()); + } + return buffer.array(); + } catch (BufferOverflowException e) { + Log.e(TAG, "Error converting to byte array: " + e.toString()); + return null; + } + } + + /** + * @return total byte count of this TransportDataDiscovery + */ + public int totalBytes() { + int size = 1; // Counting Transport Data Type here. + for (TransportBlock transportBlock : getTransportBlocks()) { + size += transportBlock.totalBytes(); + } + return size; + } +} diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index d6271038a425..25d1d53752a7 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -5529,6 +5529,12 @@ public abstract class Context { public static final String STATS_COMPANION_SERVICE = "statscompanion"; /** + * Service to assist statsd in logging atoms from bootstrap atoms. + * @hide + */ + public static final String STATS_BOOTSTRAP_ATOM_SERVICE = "statsbootstrap"; + + /** * Use with {@link #getSystemService(String)} to retrieve an {@link android.app.StatsManager}. * @hide */ @@ -6538,30 +6544,24 @@ public abstract class Context { @NonNull Configuration overrideConfiguration); /** - * Return a new Context object for the current Context but whose resources - * are adjusted to match the metrics of the given Display. Each call to this method - * returns a new instance of a Context object; Context objects are not - * shared, however common state (ClassLoader, other Resources for the - * same configuration) may be so the Context itself can be fairly lightweight. - * - * To obtain an instance of a {@link WindowManager} (see {@link #getSystemService(String)}) that - * is configured to show windows on the given display call - * {@link #createWindowContext(int, Bundle)} on the returned display Context or use an - * {@link android.app.Activity}. - * + * Returns a new <code>Context</code> object from the current context but with resources + * adjusted to match the metrics of <code>display</code>. Each call to this method + * returns a new instance of a context object. Context objects are not shared; however, + * common state (such as the {@link ClassLoader} and other resources for the same + * configuration) can be shared, so the <code>Context</code> itself is lightweight. * <p> - * Note that invoking #createDisplayContext(Display) from an UI context is not regarded - * as an UI context. In other words, it is not suggested to access UI components (such as - * obtain a {@link WindowManager} by {@link #getSystemService(String)}) - * from the context created from #createDisplayContext(Display). - * </p> - * - * @param display A {@link Display} object specifying the display for whose metrics the - * Context's resources should be tailored. + * To obtain an instance of {@link WindowManager} configured to show windows on the given + * display, call {@link #createWindowContext(int, Bundle)} on the returned display context, + * then call {@link #getSystemService(String)} or {@link #getSystemService(Class)} on the + * returned window context. + * <p> + * <b>Note:</b> The context returned by <code>createDisplayContext(Display)</code> is not a UI + * context. Do not access UI components or obtain a {@link WindowManager} from the context + * created by <code>createDisplayContext(Display)</code>. * - * @return A {@link Context} for the display. + * @param display The display to which the current context's resources are adjusted. * - * @see #getSystemService(String) + * @return A context for the display. */ @DisplayContext public abstract Context createDisplayContext(@NonNull Display display); diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index fccb8a785166..a3efbd771fad 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1564,15 +1564,6 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY"; /** - * Activity Action: Show one-handed mode settings to the user. - * <p>Input: Nothing. - * <p>Output: Nothing. - * @hide - */ - public static final String ACTION_ONE_HANDED_SETTINGS = - "android.intent.action.ONE_HANDED_SETTINGS"; - - /** * Activity Action: Setup wizard action provided for OTA provisioning to determine if it needs * to run. * <p>Input: Nothing. @@ -6424,6 +6415,7 @@ public class Intent implements Parcelable, Cloneable { FLAG_RECEIVER_FROM_SHELL, FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS, FLAG_RECEIVER_OFFLOAD, + FLAG_RECEIVER_OFFLOAD_FOREGROUND, }) @Retention(RetentionPolicy.SOURCE) public @interface Flags {} @@ -6469,6 +6461,7 @@ public class Intent implements Parcelable, Cloneable { FLAG_RECEIVER_FROM_SHELL, FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS, FLAG_RECEIVER_OFFLOAD, + FLAG_RECEIVER_OFFLOAD_FOREGROUND, }) @Retention(RetentionPolicy.SOURCE) public @interface MutableFlags {} @@ -6923,6 +6916,14 @@ public class Intent implements Parcelable, Cloneable { */ public static final int FLAG_RECEIVER_OFFLOAD = 0x80000000; /** + /** + * If set, when sending a broadcast the recipient will run on the system dedicated queue. + * + * @hide + */ + public static final int FLAG_RECEIVER_OFFLOAD_FOREGROUND = 0x00000800; + + /** * If this is an ordered broadcast, don't allow receivers to abort the broadcast. * They can still propagate results through to later receivers, but they can not prevent * later receivers from seeing the broadcast. diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java index 14d69ccdf17d..056f99fcc004 100644 --- a/core/java/android/content/pm/parsing/ParsingPackage.java +++ b/core/java/android/content/pm/parsing/ParsingPackage.java @@ -362,6 +362,9 @@ public interface ParsingPackage extends ParsingPackageRead { ParsingPackage setAttributionsAreUserVisible(boolean attributionsAreUserVisible); + ParsingPackage setResetEnabledSettingsOnAppDataCleared( + boolean resetEnabledSettingsOnAppDataCleared); + // TODO(b/135203078): This class no longer has access to ParsedPackage, find a replacement // for moving to the next step @CallSuper diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java index edddf408d1af..f07f3827c1c9 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java +++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java @@ -517,6 +517,7 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, private static final long DISALLOW_PROFILING = 1L << 45; private static final long REQUEST_FOREGROUND_SERVICE_EXEMPTION = 1L << 46; private static final long ATTRIBUTIONS_ARE_USER_VISIBLE = 1L << 47; + private static final long RESET_ENABLED_SETTINGS_ON_APP_DATA_CLEARED = 1L << 48; } private ParsingPackageImpl setBoolean(@Booleans.Values long flag, boolean value) { @@ -2216,6 +2217,11 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, } @Override + public boolean isResetEnabledSettingsOnAppDataCleared() { + return getBoolean(Booleans.RESET_ENABLED_SETTINGS_ON_APP_DATA_CLEARED); + } + + @Override public ParsingPackageImpl setBaseRevisionCode(int value) { baseRevisionCode = value; return this; @@ -2771,4 +2777,12 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, setBoolean(Booleans.ATTRIBUTIONS_ARE_USER_VISIBLE, attributionsAreUserVisible); return this; } + + @Override + public ParsingPackage setResetEnabledSettingsOnAppDataCleared( + boolean resetEnabledSettingsOnAppDataCleared) { + setBoolean(Booleans.RESET_ENABLED_SETTINGS_ON_APP_DATA_CLEARED, + resetEnabledSettingsOnAppDataCleared); + return this; + } } diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java index 4a249bb0846e..2933f955bb8c 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageRead.java +++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java @@ -297,4 +297,12 @@ public interface ParsingPackageRead extends PkgWithoutStateAppInfo, PkgWithoutSt * @see R.styleable#AndroidManifestService_visibleToInstantApps */ boolean isVisibleToInstantApps(); + + /** + * Whether the enabled settings of components in the application should be reset to the default, + * when the application's user data is cleared. + * + * @see R.styleable#AndroidManifestApplication_resetEnabledSettingsOnAppDataCleared + */ + boolean isResetEnabledSettingsOnAppDataCleared(); } diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index e3a5de514b22..d2ac87395f62 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -2288,6 +2288,9 @@ public class ParsingPackageUtils { .setVmSafeMode(bool(false, R.styleable.AndroidManifestApplication_vmSafeMode, sa)) .setAutoRevokePermissions(anInt(R.styleable.AndroidManifestApplication_autoRevokePermissions, sa)) .setAttributionsAreUserVisible(bool(false, R.styleable.AndroidManifestApplication_attributionsAreUserVisible, sa)) + .setResetEnabledSettingsOnAppDataCleared(bool(false, + R.styleable.AndroidManifestApplication_resetEnabledSettingsOnAppDataCleared, + sa)) // targetSdkVersion gated .setAllowAudioPlaybackCapture(bool(targetSdk >= Build.VERSION_CODES.Q, R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture, sa)) .setBaseHardwareAccelerated(bool(targetSdk >= Build.VERSION_CODES.ICE_CREAM_SANDWICH, R.styleable.AndroidManifestApplication_hardwareAccelerated, sa)) diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java index 2b52e967ce54..7d719846f343 100644 --- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java +++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java @@ -109,7 +109,9 @@ public class AmbientDisplayConfiguration { /** {@hide} */ public boolean quickPickupSensorEnabled(int user) { - return !TextUtils.isEmpty(quickPickupSensorType()) && !alwaysOnEnabled(user); + return !TextUtils.isEmpty(quickPickupSensorType()) + && pickupGestureEnabled(user) + && !alwaysOnEnabled(user); } /** {@hide} */ diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl index e9e8935a19b2..89e9cdbd4445 100644 --- a/core/java/android/net/nsd/INsdManager.aidl +++ b/core/java/android/net/nsd/INsdManager.aidl @@ -1,5 +1,5 @@ /** - * Copyright (c) 2012, The Android Open Source Project + * 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. @@ -16,16 +16,15 @@ package android.net.nsd; +import android.net.nsd.INsdManagerCallback; +import android.net.nsd.INsdServiceConnector; import android.os.Messenger; /** - * Interface that NsdService implements + * Interface that NsdService implements to connect NsdManager clients. * * {@hide} */ -interface INsdManager -{ - @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) - Messenger getMessenger(); - void setEnabled(boolean enable); +interface INsdManager { + INsdServiceConnector connect(INsdManagerCallback cb); } diff --git a/core/java/android/net/nsd/INsdManagerCallback.aidl b/core/java/android/net/nsd/INsdManagerCallback.aidl new file mode 100644 index 000000000000..1a262ec0e9dd --- /dev/null +++ b/core/java/android/net/nsd/INsdManagerCallback.aidl @@ -0,0 +1,39 @@ +/** + * 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 android.net.nsd; + +import android.os.Messenger; +import android.net.nsd.NsdServiceInfo; + +/** + * Callbacks from NsdService to NsdManager + * @hide + */ +oneway interface INsdManagerCallback { + void onDiscoverServicesStarted(int listenerKey, in NsdServiceInfo info); + void onDiscoverServicesFailed(int listenerKey, int error); + void onServiceFound(int listenerKey, in NsdServiceInfo info); + void onServiceLost(int listenerKey, in NsdServiceInfo info); + void onStopDiscoveryFailed(int listenerKey, int error); + void onStopDiscoverySucceeded(int listenerKey); + void onRegisterServiceFailed(int listenerKey, int error); + void onRegisterServiceSucceeded(int listenerKey, in NsdServiceInfo info); + void onUnregisterServiceFailed(int listenerKey, int error); + void onUnregisterServiceSucceeded(int listenerKey); + void onResolveServiceFailed(int listenerKey, int error); + void onResolveServiceSucceeded(int listenerKey, in NsdServiceInfo info); +} diff --git a/core/java/android/net/nsd/INsdServiceConnector.aidl b/core/java/android/net/nsd/INsdServiceConnector.aidl new file mode 100644 index 000000000000..b06ae55b150e --- /dev/null +++ b/core/java/android/net/nsd/INsdServiceConnector.aidl @@ -0,0 +1,35 @@ +/** + * 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 android.net.nsd; + +import android.net.nsd.INsdManagerCallback; +import android.net.nsd.NsdServiceInfo; +import android.os.Messenger; + +/** + * Interface that NsdService implements for each NsdManager client. + * + * {@hide} + */ +interface INsdServiceConnector { + void registerService(int listenerKey, in NsdServiceInfo serviceInfo); + void unregisterService(int listenerKey); + void discoverServices(int listenerKey, in NsdServiceInfo serviceInfo); + void stopDiscovery(int listenerKey); + void resolveService(int listenerKey, in NsdServiceInfo serviceInfo); + void startDaemon(); +}
\ No newline at end of file diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index ae8d0101947d..6c597e26e042 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Android Open Source Project + * 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. @@ -31,17 +31,13 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; -import android.os.Messenger; import android.os.RemoteException; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; -import java.util.concurrent.CountDownLatch; - /** * The Network Service Discovery Manager class provides the API to discover services * on a network. As an example, if device A and device B are connected over a Wi-Fi @@ -234,6 +230,11 @@ public final class NsdManager { /** @hide */ public static final int NATIVE_DAEMON_EVENT = BASE + 26; + /** @hide */ + public static final int REGISTER_CLIENT = BASE + 27; + /** @hide */ + public static final int UNREGISTER_CLIENT = BASE + 28; + /** Dns based service discovery protocol */ public static final int PROTOCOL_DNS_SD = 0x0001; @@ -274,7 +275,7 @@ public final class NsdManager { private static final int FIRST_LISTENER_KEY = 1; - private final INsdManager mService; + private final INsdServiceConnector mService; private final Context mContext; private int mListenerKey = FIRST_LISTENER_KEY; @@ -282,9 +283,7 @@ public final class NsdManager { private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<>(); private final Object mMapLock = new Object(); - private final AsyncChannel mAsyncChannel = new AsyncChannel(); - private ServiceHandler mHandler; - private final CountDownLatch mConnected = new CountDownLatch(1); + private final ServiceHandler mHandler; /** * Create a new Nsd instance. Applications use @@ -295,18 +294,108 @@ public final class NsdManager { * is a system private class. */ public NsdManager(Context context, INsdManager service) { - mService = service; mContext = context; - init(); + + HandlerThread t = new HandlerThread("NsdManager"); + t.start(); + mHandler = new ServiceHandler(t.getLooper()); + + try { + mService = service.connect(new NsdCallbackImpl(mHandler)); + } catch (RemoteException e) { + throw new RuntimeException("Failed to connect to NsdService"); + } + + // Only proactively start the daemon if the target SDK < S, otherwise the internal service + // would automatically start/stop the native daemon as needed. + if (!CompatChanges.isChangeEnabled(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)) { + try { + mService.startDaemon(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to proactively start daemon"); + // Continue: the daemon can still be started on-demand later + } + } } - /** - * @hide - */ - @VisibleForTesting - public void disconnect() { - mAsyncChannel.disconnect(); - mHandler.getLooper().quitSafely(); + private static class NsdCallbackImpl extends INsdManagerCallback.Stub { + private final Handler mServHandler; + + NsdCallbackImpl(Handler serviceHandler) { + mServHandler = serviceHandler; + } + + private void sendInfo(int message, int listenerKey, NsdServiceInfo info) { + mServHandler.sendMessage(mServHandler.obtainMessage(message, 0, listenerKey, info)); + } + + private void sendError(int message, int listenerKey, int error) { + mServHandler.sendMessage(mServHandler.obtainMessage(message, error, listenerKey)); + } + + private void sendNoArg(int message, int listenerKey) { + mServHandler.sendMessage(mServHandler.obtainMessage(message, 0, listenerKey)); + } + + @Override + public void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) { + sendInfo(DISCOVER_SERVICES_STARTED, listenerKey, info); + } + + @Override + public void onDiscoverServicesFailed(int listenerKey, int error) { + sendError(DISCOVER_SERVICES_FAILED, listenerKey, error); + } + + @Override + public void onServiceFound(int listenerKey, NsdServiceInfo info) { + sendInfo(SERVICE_FOUND, listenerKey, info); + } + + @Override + public void onServiceLost(int listenerKey, NsdServiceInfo info) { + sendInfo(SERVICE_LOST, listenerKey, info); + } + + @Override + public void onStopDiscoveryFailed(int listenerKey, int error) { + sendError(STOP_DISCOVERY_FAILED, listenerKey, error); + } + + @Override + public void onStopDiscoverySucceeded(int listenerKey) { + sendNoArg(STOP_DISCOVERY_SUCCEEDED, listenerKey); + } + + @Override + public void onRegisterServiceFailed(int listenerKey, int error) { + sendError(REGISTER_SERVICE_FAILED, listenerKey, error); + } + + @Override + public void onRegisterServiceSucceeded(int listenerKey, NsdServiceInfo info) { + sendInfo(REGISTER_SERVICE_SUCCEEDED, listenerKey, info); + } + + @Override + public void onUnregisterServiceFailed(int listenerKey, int error) { + sendError(UNREGISTER_SERVICE_FAILED, listenerKey, error); + } + + @Override + public void onUnregisterServiceSucceeded(int listenerKey) { + sendNoArg(UNREGISTER_SERVICE_SUCCEEDED, listenerKey); + } + + @Override + public void onResolveServiceFailed(int listenerKey, int error) { + sendError(RESOLVE_SERVICE_FAILED, listenerKey, error); + } + + @Override + public void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info) { + sendInfo(RESOLVE_SERVICE_SUCCEEDED, listenerKey, info); + } } /** @@ -376,19 +465,6 @@ public final class NsdManager { public void handleMessage(Message message) { final int what = message.what; final int key = message.arg2; - switch (what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); - return; - case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: - mConnected.countDown(); - return; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - Log.e(TAG, "Channel lost"); - return; - default: - break; - } final Object listener; final NsdServiceInfo ns; synchronized (mMapLock) { @@ -504,36 +580,6 @@ public final class NsdManager { } /** - * Initialize AsyncChannel - */ - private void init() { - final Messenger messenger = getMessenger(); - if (messenger == null) { - fatal("Failed to obtain service Messenger"); - } - HandlerThread t = new HandlerThread("NsdManager"); - t.start(); - mHandler = new ServiceHandler(t.getLooper()); - mAsyncChannel.connect(mContext, mHandler, messenger); - try { - mConnected.await(); - } catch (InterruptedException e) { - fatal("Interrupted wait at init"); - } - if (CompatChanges.isChangeEnabled(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)) { - return; - } - // Only proactively start the daemon if the target SDK < S, otherwise the internal service - // would automatically start/stop the native daemon as needed. - mAsyncChannel.sendMessage(DAEMON_STARTUP); - } - - private static void fatal(String msg) { - Log.e(TAG, msg); - throw new RuntimeException(msg); - } - - /** * Register a service to be discovered by other services. * * <p> The function call immediately returns after sending a request to register service @@ -556,7 +602,11 @@ public final class NsdManager { checkServiceInfo(serviceInfo); checkProtocol(protocolType); int key = putListener(listener, serviceInfo); - mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, key, serviceInfo); + try { + mService.registerService(key, serviceInfo); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } } /** @@ -574,7 +624,11 @@ public final class NsdManager { */ public void unregisterService(RegistrationListener listener) { int id = getListenerKey(listener); - mAsyncChannel.sendMessage(UNREGISTER_SERVICE, 0, id); + try { + mService.unregisterService(id); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } } /** @@ -613,7 +667,11 @@ public final class NsdManager { s.setServiceType(serviceType); int key = putListener(listener, s); - mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, key, s); + try { + mService.discoverServices(key, s); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } } /** @@ -634,7 +692,11 @@ public final class NsdManager { */ public void stopServiceDiscovery(DiscoveryListener listener) { int id = getListenerKey(listener); - mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, id); + try { + mService.stopDiscovery(id); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } } /** @@ -649,29 +711,10 @@ public final class NsdManager { public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) { checkServiceInfo(serviceInfo); int key = putListener(listener, serviceInfo); - mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, key, serviceInfo); - } - - /** Internal use only @hide */ - public void setEnabled(boolean enabled) { - try { - mService.setEnabled(enabled); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Get a reference to NsdService handler. This is used to establish - * an AsyncChannel communication with the service - * - * @return Messenger pointing to the NsdService handler - */ - private Messenger getMessenger() { try { - return mService.getMessenger(); + mService.resolveService(key, serviceInfo); } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + e.rethrowFromSystemServer(); } } diff --git a/core/java/android/net/nsd/NsdServiceInfo.aidl b/core/java/android/net/nsd/NsdServiceInfo.aidl new file mode 100644 index 000000000000..657bdd1e8706 --- /dev/null +++ b/core/java/android/net/nsd/NsdServiceInfo.aidl @@ -0,0 +1,19 @@ +/* + * 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 android.net.nsd; + +@JavaOnlyStableParcelable parcelable NsdServiceInfo;
\ No newline at end of file diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java index 0af322e885b1..09540132fe0d 100644 --- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java +++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java @@ -528,6 +528,7 @@ public final class ApduServiceInfo implements Parcelable { public String toString() { StringBuilder out = new StringBuilder("ApduService: "); out.append(getComponent()); + out.append(", UID: " + mUid); out.append(", description: " + mDescription); out.append(", Static AID Groups: "); for (AidGroup aidGroup : mStaticAidGroups.values()) { @@ -546,7 +547,8 @@ public final class ApduServiceInfo implements Parcelable { if (!(o instanceof ApduServiceInfo)) return false; ApduServiceInfo thatService = (ApduServiceInfo) o; - return thatService.getComponent().equals(this.getComponent()); + return thatService.getComponent().equals(this.getComponent()) + && thatService.getUid() == this.getUid(); } @Override @@ -619,8 +621,9 @@ public final class ApduServiceInfo implements Parcelable { }; public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println(" " + getComponent() + - " (Description: " + getDescription() + ")"); + pw.println(" " + getComponent() + + " (Description: " + getDescription() + ")" + + " (UID: " + getUid() + ")"); if (mOnHost) { pw.println(" On Host Service"); } else { diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java index d498535ce52c..0a9fe90f2524 100644 --- a/core/java/android/nfc/cardemulation/CardEmulation.java +++ b/core/java/android/nfc/cardemulation/CardEmulation.java @@ -30,6 +30,7 @@ import android.content.pm.PackageManager; import android.nfc.INfcCardEmulation; import android.nfc.NfcAdapter; import android.os.RemoteException; +import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Log; @@ -83,6 +84,13 @@ public final class CardEmulation { public static final String EXTRA_SERVICE_COMPONENT = "component"; /** + * The caller userId extra for {@link #ACTION_CHANGE_DEFAULT}. + * + * @see #ACTION_CHANGE_DEFAULT + */ + public static final String EXTRA_USERID = "android.nfc.cardemulation.extra.USERID"; + + /** * Category used for NFC payment services. */ public static final String CATEGORY_PAYMENT = "payment"; @@ -269,8 +277,8 @@ public final class CardEmulation { if (CATEGORY_PAYMENT.equals(category)) { boolean preferForeground = false; try { - preferForeground = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.NFC_PAYMENT_FOREGROUND) != 0; + preferForeground = Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.NFC_PAYMENT_FOREGROUND, UserHandle.myUserId()) != 0; } catch (SettingNotFoundException e) { } return preferForeground; @@ -829,6 +837,28 @@ public final class CardEmulation { /** * @hide */ + public boolean setDefaultForNextTap(int userId, ComponentName service) { + try { + return sService.setDefaultForNextTap(userId, service); + } catch (RemoteException e) { + // Try one more time + recoverService(); + if (sService == null) { + Log.e(TAG, "Failed to recover CardEmulationService."); + return false; + } + try { + return sService.setDefaultForNextTap(userId, service); + } catch (RemoteException ee) { + Log.e(TAG, "Failed to reach CardEmulationService."); + return false; + } + } + } + + /** + * @hide + */ public List<ApduServiceInfo> getServices(String category) { try { return sService.getServices(mContext.getUserId(), category); @@ -849,6 +879,28 @@ public final class CardEmulation { } /** + * @hide + */ + public List<ApduServiceInfo> getServices(String category, int userId) { + try { + return sService.getServices(userId, category); + } catch (RemoteException e) { + // Try one more time + recoverService(); + if (sService == null) { + Log.e(TAG, "Failed to recover CardEmulationService."); + return null; + } + try { + return sService.getServices(userId, category); + } catch (RemoteException ee) { + Log.e(TAG, "Failed to reach CardEmulationService."); + return null; + } + } + } + + /** * A valid AID according to ISO/IEC 7816-4: * <ul> * <li>Has >= 5 bytes and <=16 bytes (>=10 hex chars and <= 32 hex chars) diff --git a/core/java/android/os/IStatsBootstrapAtomService.aidl b/core/java/android/os/IStatsBootstrapAtomService.aidl new file mode 100644 index 000000000000..9d1df67fa19d --- /dev/null +++ b/core/java/android/os/IStatsBootstrapAtomService.aidl @@ -0,0 +1,36 @@ +/* + * Copyright 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 android.os; + +import android.os.StatsBootstrapAtom; + +/** + * IBootstrapAtomService interface exposes an interface for processes that launch in the + * bootstrap namespace to push atoms to statsd. + * + * @hide + */ +oneway interface IStatsBootstrapAtomService { + /** + * Push an atom to StatsBootstrapAtomService, which will forward it to statsd. + * + * @param atom - parcelled representation of the atom to log. + * + * Errors are reported as service specific errors. + */ + void reportBootstrapAtom(in StatsBootstrapAtom atom); +}
\ No newline at end of file diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index b83970625ee4..50ca9ff3576f 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -20,6 +20,7 @@ package android.os; import android.os.Bundle; import android.os.IUserRestrictionsListener; import android.os.PersistableBundle; +import android.os.UserHandle; import android.os.UserManager; import android.content.pm.UserInfo; import android.content.IntentSender; @@ -91,6 +92,9 @@ interface IUserManager { boolean markGuestForDeletion(int userId); UserInfo findCurrentGuestUser(); boolean isQuietModeEnabled(int userId); + UserHandle createUserWithAttributes(in String userName, in String userType, int flags, + in Bitmap userIcon, + in String accountName, in String accountType, in PersistableBundle accountOptions); void setSeedAccountData(int userId, in String accountName, in String accountType, in PersistableBundle accountOptions, boolean persist); String getSeedAccountName(int userId); @@ -98,6 +102,7 @@ interface IUserManager { PersistableBundle getSeedAccountOptions(int userId); void clearSeedAccountData(int userId); boolean someUserHasSeedAccount(in String accountName, in String accountType); + boolean someUserHasAccount(in String accountName, in String accountType); boolean isProfile(int userId); boolean isManagedProfile(int userId); boolean isCloneProfile(int userId); diff --git a/core/java/android/os/NewUserRequest.java b/core/java/android/os/NewUserRequest.java index 2ebc01f2d3d0..b0e1f91c47c3 100644 --- a/core/java/android/os/NewUserRequest.java +++ b/core/java/android/os/NewUserRequest.java @@ -17,7 +17,11 @@ package android.os; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; +import android.content.pm.UserInfo; +import android.graphics.Bitmap; +import android.text.TextUtils; /** * Contains necessary information to create user using @@ -26,6 +30,7 @@ import android.annotation.SystemApi; * @hide */ @SystemApi +@SuppressLint("PackageLayering") public final class NewUserRequest { @Nullable private final String mName; @@ -33,16 +38,24 @@ public final class NewUserRequest { private final boolean mEphemeral; @NonNull private final String mUserType; + private final Bitmap mUserIcon; + private final String mAccountName; + private final String mAccountType; + private final PersistableBundle mAccountOptions; private NewUserRequest(Builder builder) { mName = builder.mName; mAdmin = builder.mAdmin; mEphemeral = builder.mEphemeral; mUserType = builder.mUserType; + mUserIcon = builder.mUserIcon; + mAccountName = builder.mAccountName; + mAccountType = builder.mAccountType; + mAccountOptions = builder.mAccountOptions; } /** - * Gets the user name. + * Returns the name of the user. */ @Nullable public String getName() { @@ -50,7 +63,7 @@ public final class NewUserRequest { } /** - * Is user Ephemenral? + * Returns whether the user is ephemeral. * * <p> Ephemeral user will be removed after leaving the foreground. */ @@ -59,7 +72,7 @@ public final class NewUserRequest { } /** - * Is user Admin? + * Returns whether the user is an admin. * * <p> Admin user is with administrative privileges and such user can create and * delete users. @@ -69,7 +82,17 @@ public final class NewUserRequest { } /** - * Gets user type. + * Returns the calculated flags for user creation. + */ + int getFlags() { + int flags = 0; + if (isAdmin()) flags |= UserInfo.FLAG_ADMIN; + if (isEphemeral()) flags |= UserInfo.FLAG_EPHEMERAL; + return flags; + } + + /** + * Returns the user type. * * <p> Supported types are {@link UserManager.USER_TYPE_FULL_SECONDARY} and * {@link USER_TYPE_FULL_GUEST} @@ -79,25 +102,71 @@ public final class NewUserRequest { return mUserType; } + /** + * Returns the user icon. + */ + @Nullable + public Bitmap getUserIcon() { + return mUserIcon; + } + + /** + * Returns the account name. + */ + @Nullable + public String getAccountName() { + return mAccountName; + } + + /** + * Returns the account type. + */ + @Nullable + public String getAccountType() { + return mAccountType; + } + + /** + * Returns the account options. + */ + @SuppressLint("NullableCollection") + @Nullable + public PersistableBundle getAccountOptions() { + return mAccountOptions; + } + @Override public String toString() { - return String.format( - "NewUserRequest- UserName:%s, userType:%s, IsAdmin:%s, IsEphemeral:%s.", mName, - mUserType, mAdmin, mEphemeral); + return "NewUserRequest{" + + "mName='" + mName + '\'' + + ", mAdmin=" + mAdmin + + ", mEphemeral=" + mEphemeral + + ", mUserType='" + mUserType + '\'' + + ", mAccountName='" + mAccountName + '\'' + + ", mAccountType='" + mAccountType + '\'' + + ", mAccountOptions=" + mAccountOptions + + '}'; } /** * Builder for building {@link NewUserRequest} */ + @SuppressLint("PackageLayering") public static final class Builder { private String mName; private boolean mAdmin; private boolean mEphemeral; private String mUserType = UserManager.USER_TYPE_FULL_SECONDARY; + private Bitmap mUserIcon; + private String mAccountName; + private String mAccountType; + private PersistableBundle mAccountOptions; /** * Sets user name. + * + * @return This object for method chaining. */ @NonNull public Builder setName(@Nullable String name) { @@ -110,6 +179,8 @@ public final class NewUserRequest { * * <p> Admin user is with administrative privileges and such user can create * and delete users. + * + * @return This object for method chaining. */ @NonNull public Builder setAdmin() { @@ -121,6 +192,8 @@ public final class NewUserRequest { * Sets user as ephemeral. * * <p> Ephemeral user will be removed after leaving the foreground. + * + * @return This object for method chaining. */ @NonNull public Builder setEphemeral() { @@ -134,6 +207,8 @@ public final class NewUserRequest { * Supported types are {@link UserManager.USER_TYPE_FULL_SECONDARY} and * {@link UserManager.USER_TYPE_FULL_GUEST}. Default value is * {@link UserManager.USER_TYPE_FULL_SECONDARY}. + * + * @return This object for method chaining. */ @NonNull public Builder setUserType(@NonNull String type) { @@ -142,6 +217,54 @@ public final class NewUserRequest { } /** + * Sets user icon. + * + * @return This object for method chaining. + */ + @NonNull + public Builder setUserIcon(@Nullable Bitmap userIcon) { + mUserIcon = userIcon; + return this; + } + + /** + * Sets account name that will be used by the setup wizard to initialize the user. + * + * @see android.accounts.Account + * @return This object for method chaining. + */ + @NonNull + public Builder setAccountName(@Nullable String accountName) { + mAccountName = accountName; + return this; + } + + /** + * Sets account type for the account to be created. This is required if the account name + * is not null. This will be used by the setup wizard to initialize the user. + * + * @see android.accounts.Account + * @return This object for method chaining. + */ + @NonNull + public Builder setAccountType(@Nullable String accountType) { + mAccountType = accountType; + return this; + } + + /** + * Sets account options that can contain account-specific extra information + * to be used by setup wizard to initialize the account for the user. + * + * @return This object for method chaining. + */ + @NonNull + public Builder setAccountOptions(@Nullable PersistableBundle accountOptions) { + mAccountOptions = accountOptions; + return this; + } + + /** * Builds {@link NewUserRequest} * * @throws IllegalStateException if builder is configured with incompatible properties and @@ -165,6 +288,11 @@ public final class NewUserRequest { && mUserType != UserManager.USER_TYPE_FULL_GUEST) { throw new IllegalStateException("Unsupported user type: " + mUserType); } + + if (TextUtils.isEmpty(mAccountName) != TextUtils.isEmpty(mAccountType)) { + throw new IllegalStateException( + "Account name and account type should be provided together."); + } } } } diff --git a/core/java/android/os/StatsBootstrapAtom.aidl b/core/java/android/os/StatsBootstrapAtom.aidl new file mode 100644 index 000000000000..47500af8eebf --- /dev/null +++ b/core/java/android/os/StatsBootstrapAtom.aidl @@ -0,0 +1,34 @@ +/* + * Copyright 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 android.os; + +import android.os.StatsBootstrapAtomValue; + +/* + * Generic encapsulation of an atom for bootstrap processes to log. + * + * @hide + */ +parcelable StatsBootstrapAtom { + /* + * Atom ID. Must be between 1 - 10,000. + */ + int atomId; + /* + * Vector of fields in the order of the atom definition. + */ + StatsBootstrapAtomValue[] values; + }
\ No newline at end of file diff --git a/core/java/android/os/StatsBootstrapAtomValue.aidl b/core/java/android/os/StatsBootstrapAtomValue.aidl new file mode 100644 index 000000000000..a90dfa404ee9 --- /dev/null +++ b/core/java/android/os/StatsBootstrapAtomValue.aidl @@ -0,0 +1,29 @@ +/* + * Copyright 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 android.os; +/* + * Supported field types. + * + * @hide + */ +union StatsBootstrapAtomValue { + boolean boolValue; + int intValue; + long longValue; + float floatValue; + String stringValue; + byte[] bytesValue; +}
\ No newline at end of file diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 94375c0e949f..cf4ce9b43cf2 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -70,6 +70,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Set; /** @@ -1661,6 +1662,14 @@ public class UserManager { public static final int USER_OPERATION_ERROR_MAX_USERS = 6; /** + * Indicates user operation failed because a user with that account already exists. + * + * @hide + */ + @SystemApi + public static final int USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS = 7; + + /** * Result returned from various user operations. * * @hide @@ -1673,7 +1682,8 @@ public class UserManager { USER_OPERATION_ERROR_MAX_RUNNING_USERS, USER_OPERATION_ERROR_CURRENT_USER, USER_OPERATION_ERROR_LOW_STORAGE, - USER_OPERATION_ERROR_MAX_USERS + USER_OPERATION_ERROR_MAX_USERS, + USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS }) public @interface UserOperationResult {} @@ -3159,26 +3169,24 @@ public class UserManager { @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS, Manifest.permission.CREATE_USERS}) public @NonNull NewUserResponse createUser(@NonNull NewUserRequest newUserRequest) { - UserInfo user = null; - int operationResult = USER_OPERATION_ERROR_UNKNOWN; try { - user = createUser(newUserRequest.getName(), newUserRequest.getUserType(), - determineFlagsForUserCreation(newUserRequest)); - } catch (UserOperationException e) { + final UserHandle userHandle = mService.createUserWithAttributes( + newUserRequest.getName(), + newUserRequest.getUserType(), + newUserRequest.getFlags(), + newUserRequest.getUserIcon(), + newUserRequest.getAccountName(), + newUserRequest.getAccountType(), + newUserRequest.getAccountOptions()); + + return new NewUserResponse(userHandle, USER_OPERATION_SUCCESS); + + } catch (ServiceSpecificException e) { Log.w(TAG, "Exception while creating user " + newUserRequest, e); - operationResult = e.getUserOperationResult(); - } - if (user == null) { - return new NewUserResponse(null, operationResult); + return new NewUserResponse(null, e.errorCode); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); } - return new NewUserResponse(user.getUserHandle(), USER_OPERATION_SUCCESS); - } - - private int determineFlagsForUserCreation(NewUserRequest newUserRequest) { - int flags = 0; - if (newUserRequest.isAdmin()) flags |= UserInfo.FLAG_ADMIN; - if (newUserRequest.isEphemeral()) flags |= UserInfo.FLAG_EPHEMERAL; - return flags; } /** @@ -4913,12 +4921,12 @@ public class UserManager { } /** - * @hide * Checks if any uninitialized user has the specific seed account name and type. * * @param accountName The account name to check for * @param accountType The account type of the account to check for * @return whether the seed account was found + * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean someUserHasSeedAccount(String accountName, String accountType) { @@ -4930,6 +4938,29 @@ public class UserManager { } /** + * Checks if any initialized or uninitialized user has the specific account name and type. + * + * @param accountName The account name to check for + * @param accountType The account type of the account to check for + * @return whether the account was found + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS, + Manifest.permission.CREATE_USERS}) + public boolean someUserHasAccount( + @NonNull String accountName, @NonNull String accountType) { + Objects.requireNonNull(accountName, "accountName must not be null"); + Objects.requireNonNull(accountType, "accountType must not be null"); + + try { + return mService.someUserHasAccount(accountName, accountType); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** * @hide * User that enforces a restriction. * diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 31ca37af9d00..cc95c1f6c60b 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -379,6 +379,21 @@ public final class Settings { "android.settings.REDUCE_BRIGHT_COLORS_SETTINGS"; /** + * Activity Action: Show settings to allow configuration of Color inversion. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_COLOR_INVERSION_SETTINGS = + "android.settings.COLOR_INVERSION_SETTINGS"; + + /** * Activity Action: Show settings to control access to usage information. * <p> * In some cases, a matching Activity may not exist, so ensure you @@ -16694,12 +16709,6 @@ public final class Settings { public static final String AMBIENT_FORCE_WHEN_DOCKED = "ambient_force_when_docked"; /** - * The id of the gesture sensor. - * @hide - */ - public static final String AMBIENT_GESTURE_SENSOR_ID = "ambient_gesture_sensor_id"; - - /** * Whether the ambient low bit mode is enabled. * @hide */ diff --git a/core/java/android/service/wallpaper/EngineWindowPage.java b/core/java/android/service/wallpaper/EngineWindowPage.java index 5ed0ad6f2aeb..006e3cdf03f8 100644 --- a/core/java/android/service/wallpaper/EngineWindowPage.java +++ b/core/java/android/service/wallpaper/EngineWindowPage.java @@ -24,7 +24,6 @@ import android.util.ArraySet; import java.util.Map; import java.util.Set; -import java.util.function.Consumer; /** * This class represents a page of a launcher page used by the wallpaper @@ -84,11 +83,6 @@ public class EngineWindowPage { return mCallbackAreas; } - /** run operations on this page */ - public synchronized void execSync(Consumer<EngineWindowPage> run) { - run.accept(this); - } - /** nullify the area color */ public void removeColor(RectF colorArea) { mRectFColors.remove(colorArea); diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index c77399f692f0..7b8410bba6ec 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -1490,7 +1490,7 @@ public abstract class WallpaperService extends Service { //below is the default implementation if (xOffset % xOffsetStep > MIN_PAGE_ALLOWED_MARGIN || !mSurfaceHolder.getSurface().isValid()) return; - int xPage; + int xCurrentPage; int xPages; if (!validStep(xOffsetStep)) { if (DEBUG) { @@ -1498,30 +1498,34 @@ public abstract class WallpaperService extends Service { } xOffset = 0; xOffsetStep = 1; - xPage = 0; + xCurrentPage = 0; xPages = 1; } else { xPages = Math.round(1 / xOffsetStep) + 1; xOffsetStep = (float) 1 / (float) xPages; float shrink = (float) (xPages - 1) / (float) xPages; xOffset *= shrink; - xPage = Math.round(xOffset / xOffsetStep); + xCurrentPage = Math.round(xOffset / xOffsetStep); } if (DEBUG) { - Log.d(TAG, "xPages " + xPages + " xPage " + xPage); + Log.d(TAG, "xPages " + xPages + " xPage " + xCurrentPage); Log.d(TAG, "xOffsetStep " + xOffsetStep + " xOffset " + xOffset); } - EngineWindowPage current; - synchronized (mLock) { + + float finalXOffsetStep = xOffsetStep; + float finalXOffset = xOffset; + mHandler.post(() -> { + int xPage = xCurrentPage; + EngineWindowPage current; if (mWindowPages.length == 0 || (mWindowPages.length != xPages)) { mWindowPages = new EngineWindowPage[xPages]; - initWindowPages(mWindowPages, xOffsetStep); + initWindowPages(mWindowPages, finalXOffsetStep); } if (mLocalColorsToAdd.size() != 0) { for (RectF colorArea : mLocalColorsToAdd) { if (!isValid(colorArea)) continue; mLocalColorAreas.add(colorArea); - int colorPage = getRectFPage(colorArea, xOffsetStep); + int colorPage = getRectFPage(colorArea, finalXOffsetStep); EngineWindowPage currentPage = mWindowPages[colorPage]; if (currentPage == null) { currentPage = new EngineWindowPage(); @@ -1539,7 +1543,8 @@ public abstract class WallpaperService extends Service { Log.e(TAG, "error xPage >= mWindowPages.length page: " + xPage); Log.e(TAG, "error on page " + xPage + " out of " + xPages); Log.e(TAG, - "error on xOffsetStep " + xOffsetStep + " xOffset " + xOffset); + "error on xOffsetStep " + finalXOffsetStep + + " xOffset " + finalXOffset); } xPage = mWindowPages.length - 1; } @@ -1547,13 +1552,14 @@ public abstract class WallpaperService extends Service { if (current == null) { if (DEBUG) Log.d(TAG, "making page " + xPage + " out of " + xPages); if (DEBUG) { - Log.d(TAG, "xOffsetStep " + xOffsetStep + " xOffset " + xOffset); + Log.d(TAG, "xOffsetStep " + finalXOffsetStep + " xOffset " + + finalXOffset); } current = new EngineWindowPage(); mWindowPages[xPage] = current; } - } - updatePage(current, xPage, xPages, xOffsetStep); + updatePage(current, xPage, xPages, finalXOffsetStep); + }); } private void initWindowPages(EngineWindowPage[] windowPages, float step) { @@ -1603,10 +1609,8 @@ public abstract class WallpaperService extends Service { if (DEBUG) Log.d(TAG, "result of pixel copy is " + res); if (res != PixelCopy.SUCCESS) { Bitmap lastBitmap = currentPage.getBitmap(); - currentPage.execSync((p) -> { - // assign the last bitmap taken for now - p.setBitmap(mLastScreenshot); - }); + // assign the last bitmap taken for now + currentPage.setBitmap(mLastScreenshot); Bitmap lastScreenshot = mLastScreenshot; if (lastScreenshot != null && !lastScreenshot.isRecycled() && !Objects.equals(lastBitmap, lastScreenshot)) { @@ -1615,10 +1619,8 @@ public abstract class WallpaperService extends Service { } else { mLastScreenshot = finalScreenShot; // going to hold this lock for a while - currentPage.execSync((p) -> { - p.setBitmap(finalScreenShot); - p.setLastUpdateTime(current); - }); + currentPage.setBitmap(finalScreenShot); + currentPage.setLastUpdateTime(current); updatePageColors(currentPage, pageIndx, numPages, xOffsetStep); } }, mHandler); @@ -1698,16 +1700,14 @@ public abstract class WallpaperService extends Service { private void resetWindowPages() { if (supportsLocalColorExtraction()) return; mLastWindowPage = -1; - synchronized (mLock) { + mHandler.post(() -> { for (int i = 0; i < mWindowPages.length; i++) { EngineWindowPage page = mWindowPages[i]; if (page != null) { - page.execSync((p) -> { - p.setLastUpdateTime(0L); - }); + page.setLastUpdateTime(0L); } } - } + }); } private int getRectFPage(RectF area, float step) { @@ -1730,10 +1730,10 @@ public abstract class WallpaperService extends Service { if (DEBUG) { Log.d(TAG, "addLocalColorsAreas adding local color areas " + regions); } - float step = mPendingXOffsetStep; List<WallpaperColors> colors = getLocalWallpaperColors(regions); - synchronized (mLock) { + mHandler.post(() -> { + float step = mPendingXOffsetStep; if (!validStep(step)) { step = 0; } @@ -1749,26 +1749,25 @@ public abstract class WallpaperService extends Service { page.addArea(area); WallpaperColors color = colors.get(i); if (color != null && !color.equals(page.getColors(area))) { - page.execSync(p -> { - p.addWallpaperColors(area, color); - }); + page.addWallpaperColors(area, color); } } else { mLocalColorsToAdd.add(area); } } - } - - for (int i = 0; i < colors.size() && colors.get(i) != null; i++) { - try { - mConnection.onLocalWallpaperColorsChanged(regions.get(i), colors.get(i), - mDisplayContext.getDisplayId()); - } catch (RemoteException e) { - Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e); - return; + for (int i = 0; i < colors.size() && colors.get(i) != null; i++) { + try { + mConnection.onLocalWallpaperColorsChanged(regions.get(i), colors.get(i), + mDisplayContext.getDisplayId()); + } catch (RemoteException e) { + Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e); + return; + } } - } - processLocalColors(mPendingXOffset, mPendingYOffset); + processLocalColors(mPendingXOffset, mPendingYOffset); + }); + + } /** @@ -1778,7 +1777,7 @@ public abstract class WallpaperService extends Service { */ public void removeLocalColorsAreas(@NonNull List<RectF> regions) { if (supportsLocalColorExtraction()) return; - synchronized (mLock) { + mHandler.post(() -> { float step = mPendingXOffsetStep; mLocalColorsToAdd.removeAll(regions); mLocalColorAreas.removeAll(regions); @@ -1792,12 +1791,10 @@ public abstract class WallpaperService extends Service { // no page should be null EngineWindowPage page = mWindowPages[pageInx]; if (page != null) { - page.execSync(p -> { - p.removeArea(area); - }); + page.removeArea(area); } } - } + }); } private @NonNull List<WallpaperColors> getLocalWallpaperColors(@NonNull List<RectF> areas) { diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 505f400c60d2..da3e9b6d509c 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -82,7 +82,9 @@ public abstract class Layout { /** @hide */ @IntDef(prefix = { "HYPHENATION_FREQUENCY_" }, value = { HYPHENATION_FREQUENCY_NORMAL, + HYPHENATION_FREQUENCY_NORMAL_FAST, HYPHENATION_FREQUENCY_FULL, + HYPHENATION_FREQUENCY_FULL_FAST, HYPHENATION_FREQUENCY_NONE }) @Retention(RetentionPolicy.SOURCE) @@ -95,21 +97,40 @@ public abstract class Layout { * layout and there is otherwise no valid break. Soft hyphens are ignored and will not be used * as suggestions for potential line breaks. */ - public static final int HYPHENATION_FREQUENCY_NONE = LineBreaker.HYPHENATION_FREQUENCY_NONE; + public static final int HYPHENATION_FREQUENCY_NONE = 0; /** * Value for hyphenation frequency indicating a light amount of automatic hyphenation, which * is a conservative default. Useful for informal cases, such as short sentences or chat * messages. */ - public static final int HYPHENATION_FREQUENCY_NORMAL = LineBreaker.HYPHENATION_FREQUENCY_NORMAL; + public static final int HYPHENATION_FREQUENCY_NORMAL = 1; /** * Value for hyphenation frequency indicating the full amount of automatic hyphenation, typical * in typography. Useful for running text and where it's important to put the maximum amount of * text in a screen with limited space. */ - public static final int HYPHENATION_FREQUENCY_FULL = LineBreaker.HYPHENATION_FREQUENCY_FULL; + public static final int HYPHENATION_FREQUENCY_FULL = 2; + + /** + * Value for hyphenation frequency indicating a light amount of automatic hyphenation with + * using faster algorithm. + * + * This option is useful for informal cases, such as short sentences or chat messages. To make + * text rendering faster with hyphenation, this algorithm ignores some hyphen character related + * typographic features, e.g. kerning. + */ + public static final int HYPHENATION_FREQUENCY_NORMAL_FAST = 3; + /** + * Value for hyphenation frequency indicating the full amount of automatic hyphenation with + * using faster algorithm. + * + * This option is useful for running text and where it's important to put the maximum amount of + * text in a screen with limited space. To make text rendering faster with hyphenation, this + * algorithm ignores some hyphen character related typographic features, e.g. kerning. + */ + public static final int HYPHENATION_FREQUENCY_FULL_FAST = 4; private static final ParagraphStyle[] NO_PARA_SPANS = ArrayUtils.emptyArray(ParagraphStyle.class); diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java index 7e41878b3d4e..6a3c6182b96d 100644 --- a/core/java/android/text/MeasuredParagraph.java +++ b/core/java/android/text/MeasuredParagraph.java @@ -377,7 +377,7 @@ public class MeasuredParagraph { * @param start the inclusive start offset of the target region in the text * @param end the exclusive end offset of the target region in the text * @param textDir the text direction - * @param computeHyphenation true if need to compute hyphenation, otherwise false + * @param hyphenationMode a hyphenation mode * @param computeLayout true if need to compute full layout, otherwise false. * @param hint pass if you already have measured paragraph. * @param recycle pass existing MeasuredParagraph if you want to recycle it. @@ -390,7 +390,7 @@ public class MeasuredParagraph { @IntRange(from = 0) int start, @IntRange(from = 0) int end, @NonNull TextDirectionHeuristic textDir, - boolean computeHyphenation, + int hyphenationMode, boolean computeLayout, @Nullable MeasuredParagraph hint, @Nullable MeasuredParagraph recycle) { @@ -399,7 +399,7 @@ public class MeasuredParagraph { final MeasuredText.Builder builder; if (hint == null) { builder = new MeasuredText.Builder(mt.mCopiedBuffer) - .setComputeHyphenation(computeHyphenation) + .setComputeHyphenation(hyphenationMode) .setComputeLayout(computeLayout); } else { builder = new MeasuredText.Builder(hint.mMeasuredText); diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java index 08741d6a7d88..152570ffd1c7 100644 --- a/core/java/android/text/PrecomputedText.java +++ b/core/java/android/text/PrecomputedText.java @@ -22,6 +22,7 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Rect; +import android.graphics.text.MeasuredText; import android.text.style.MetricAffectingSpan; import com.android.internal.util.Preconditions; @@ -395,17 +396,30 @@ public class PrecomputedText implements Spannable { return new PrecomputedText(text, 0, text.length(), params, paraInfo); } + private static boolean isFastHyphenation(int frequency) { + return frequency == Layout.HYPHENATION_FREQUENCY_FULL_FAST + || frequency == Layout.HYPHENATION_FREQUENCY_NORMAL_FAST; + } + private static ParagraphInfo[] createMeasuredParagraphsFromPrecomputedText( @NonNull PrecomputedText pct, @NonNull Params params, boolean computeLayout) { final boolean needHyphenation = params.getBreakStrategy() != Layout.BREAK_STRATEGY_SIMPLE && params.getHyphenationFrequency() != Layout.HYPHENATION_FREQUENCY_NONE; + final int hyphenationMode; + if (needHyphenation) { + hyphenationMode = isFastHyphenation(params.getHyphenationFrequency()) + ? MeasuredText.Builder.HYPHENATION_MODE_FAST : + MeasuredText.Builder.HYPHENATION_MODE_NORMAL; + } else { + hyphenationMode = MeasuredText.Builder.HYPHENATION_MODE_NONE; + } ArrayList<ParagraphInfo> result = new ArrayList<>(); for (int i = 0; i < pct.getParagraphCount(); ++i) { final int paraStart = pct.getParagraphStart(i); final int paraEnd = pct.getParagraphEnd(i); result.add(new ParagraphInfo(paraEnd, MeasuredParagraph.buildForStaticLayout( params.getTextPaint(), pct, paraStart, paraEnd, params.getTextDirection(), - needHyphenation, computeLayout, pct.getMeasuredParagraph(i), + hyphenationMode, computeLayout, pct.getMeasuredParagraph(i), null /* no recycle */))); } return result.toArray(new ParagraphInfo[result.size()]); @@ -421,6 +435,14 @@ public class PrecomputedText implements Spannable { Preconditions.checkNotNull(params); final boolean needHyphenation = params.getBreakStrategy() != Layout.BREAK_STRATEGY_SIMPLE && params.getHyphenationFrequency() != Layout.HYPHENATION_FREQUENCY_NONE; + final int hyphenationMode; + if (needHyphenation) { + hyphenationMode = isFastHyphenation(params.getHyphenationFrequency()) + ? MeasuredText.Builder.HYPHENATION_MODE_FAST : + MeasuredText.Builder.HYPHENATION_MODE_NORMAL; + } else { + hyphenationMode = MeasuredText.Builder.HYPHENATION_MODE_NONE; + } int paraEnd = 0; for (int paraStart = start; paraStart < end; paraStart = paraEnd) { @@ -435,8 +457,7 @@ public class PrecomputedText implements Spannable { result.add(new ParagraphInfo(paraEnd, MeasuredParagraph.buildForStaticLayout( params.getTextPaint(), text, paraStart, paraEnd, params.getTextDirection(), - needHyphenation, computeLayout, null /* no hint */, - null /* no recycle */))); + hyphenationMode, computeLayout, null /* no hint */, null /* no recycle */))); } return result.toArray(new ParagraphInfo[result.size()]); } diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index f99d4300a848..6984e4dfccc4 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -591,6 +591,20 @@ public class StaticLayout extends Layout { generate(b, b.mIncludePad, b.mIncludePad); } + private static int getBaseHyphenationFrequency(int frequency) { + switch (frequency) { + case Layout.HYPHENATION_FREQUENCY_FULL: + case Layout.HYPHENATION_FREQUENCY_FULL_FAST: + return LineBreaker.HYPHENATION_FREQUENCY_FULL; + case Layout.HYPHENATION_FREQUENCY_NORMAL: + case Layout.HYPHENATION_FREQUENCY_NORMAL_FAST: + return LineBreaker.HYPHENATION_FREQUENCY_NORMAL; + case Layout.HYPHENATION_FREQUENCY_NONE: + default: + return LineBreaker.HYPHENATION_FREQUENCY_NONE; + } + } + /* package */ void generate(Builder b, boolean includepad, boolean trackpad) { final CharSequence source = b.mText; final int bufStart = b.mStart; @@ -641,7 +655,7 @@ public class StaticLayout extends Layout { final LineBreaker lineBreaker = new LineBreaker.Builder() .setBreakStrategy(b.mBreakStrategy) - .setHyphenationFrequency(b.mHyphenationFrequency) + .setHyphenationFrequency(getBaseHyphenationFrequency(b.mHyphenationFrequency)) // TODO: Support more justification mode, e.g. letter spacing, stretching. .setJustificationMode(b.mJustificationMode) .setIndents(indents) diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index fceda20ba62b..12421ed61b33 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -94,12 +94,6 @@ oneway interface IWindow { void dispatchAppVisibility(boolean visible); void dispatchGetNewSurface(); - /** - * Tell the window that it is either gaining or losing focus. Keep it up - * to date on the current state showing navigational focus too. - */ - void windowFocusChanged(boolean hasFocus); - void closeSystemDialogs(String reason); /** diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 1460cb251c72..c3a638c4c36a 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -295,7 +295,8 @@ public class KeyEvent extends InputEvent implements Parcelable { /** Key code constant: Fast Forward media key. */ public static final int KEYCODE_MEDIA_FAST_FORWARD = 90; /** Key code constant: Mute key. - * Mutes the microphone, unlike {@link #KEYCODE_VOLUME_MUTE}. */ + * Mute key for the microphone (unlike {@link #KEYCODE_VOLUME_MUTE}, which is the speaker mute + * key). */ public static final int KEYCODE_MUTE = 91; /** Key code constant: Page Up key. */ public static final int KEYCODE_PAGE_UP = 92; @@ -482,9 +483,10 @@ public class KeyEvent extends InputEvent implements Parcelable { /** Key code constant: Numeric keypad ')' key. */ public static final int KEYCODE_NUMPAD_RIGHT_PAREN = 163; /** Key code constant: Volume Mute key. - * Mutes the speaker, unlike {@link #KEYCODE_MUTE}. - * This key should normally be implemented as a toggle such that the first press - * mutes the speaker and the second press restores the original volume. */ + * Mute key for speaker (unlike {@link #KEYCODE_MUTE}, which is the mute key for the + * microphone). This key should normally be implemented as a toggle such that the first press + * mutes the speaker and the second press restores the original volume. + */ public static final int KEYCODE_VOLUME_MUTE = 164; /** Key code constant: Info key. * Common on TV remotes to show additional information related to what is diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 765d30ee2e1b..0c30cbb3e149 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -9740,14 +9740,6 @@ public final class ViewRootImpl implements ViewParent, } } - @Override - public void windowFocusChanged(boolean hasFocus) { - final ViewRootImpl viewAncestor = mViewAncestor.get(); - if (viewAncestor != null) { - viewAncestor.windowFocusChanged(hasFocus); - } - } - private static int checkCallingPermission(String permission) { try { return ActivityManager.getService().checkPermission( diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java index efffa2b05a1e..9793f8cfc83b 100644 --- a/core/java/android/view/ViewRootInsetsControllerHost.java +++ b/core/java/android/view/ViewRootInsetsControllerHost.java @@ -133,7 +133,7 @@ public class ViewRootInsetsControllerHost implements InsetsController.Host { // frame instead. final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); mApplier.applyParams(t, params); - mApplier.applyTransaction(t, -1); + t.apply(); } } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 3b4fcc0adccb..7fe810acd6f3 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -129,17 +129,15 @@ import java.util.function.Consumer; /** * The interface that apps use to talk to the window manager. - * </p><p> - * Each window manager instance is bound to a particular {@link Display}. - * To obtain a {@link WindowManager} for a different display, use - * {@link Context#createDisplayContext} to obtain a {@link Context} for that - * display, then use <code>Context.getSystemService(Context.WINDOW_SERVICE)</code> - * to get the WindowManager. - * </p><p> - * The simplest way to show a window on another display is to create a - * {@link Presentation}. The presentation will automatically obtain a - * {@link WindowManager} and {@link Context} for that display. - * </p> + * <p> + * Each window manager instance is bound to a {@link Display}. To obtain the + * <code>WindowManager</code> associated with a display, + * call {@link Context#createWindowContext(Display, int, Bundle)} to get the display's UI context, + * then call {@link Context#getSystemService(String)} or {@link Context#getSystemService(Class)} on + * the UI context. + * <p> + * The simplest way to show a window on a particular display is to create a {@link Presentation}, + * which automatically obtains a <code>WindowManager</code> and context for the display. */ @SystemService(Context.WINDOW_SERVICE) public interface WindowManager extends ViewManager { diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java index 6b3a698f118d..c5325572291a 100644 --- a/core/java/android/widget/SpellChecker.java +++ b/core/java/android/widget/SpellChecker.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.text.Editable; import android.text.Selection; import android.text.Spanned; +import android.text.SpannedString; import android.text.method.WordIterator; import android.text.style.SpellCheckSpan; import android.text.style.SuggestionSpan; @@ -416,7 +417,15 @@ public class SpellChecker implements SpellCheckerSessionListener { } if (spellCheckSpanStart >= 0 && spellCheckSpanEnd > spellCheckSpanStart && end > start) { - removeErrorSuggestionSpan(editable, start, end, RemoveReason.OBSOLETE); + boolean visibleToAccessibility = mTextView.isVisibleToAccessibility(); + CharSequence beforeText = + visibleToAccessibility ? new SpannedString(editable) : null; + boolean spanRemoved = removeErrorSuggestionSpan( + editable, start, end, RemoveReason.OBSOLETE); + if (visibleToAccessibility && spanRemoved) { + mTextView.sendAccessibilityEventTypeViewTextChanged( + beforeText, start, end); + } } } return spellCheckSpan; @@ -437,8 +446,9 @@ public class SpellChecker implements SpellCheckerSessionListener { OBSOLETE, } - private static void removeErrorSuggestionSpan( + private static boolean removeErrorSuggestionSpan( Editable editable, int start, int end, RemoveReason reason) { + boolean spanRemoved = false; SuggestionSpan[] spans = editable.getSpans(start, end, SuggestionSpan.class); for (SuggestionSpan span : spans) { if (editable.getSpanStart(span) == start @@ -450,8 +460,10 @@ public class SpellChecker implements SpellCheckerSessionListener { + editable.subSequence(start, end) + ", reason: " + reason); } editable.removeSpan(span); + spanRemoved = true; } } + return spanRemoved; } @Override @@ -568,8 +580,13 @@ public class SpellChecker implements SpellCheckerSessionListener { } SuggestionSpan suggestionSpan = new SuggestionSpan(mTextView.getContext(), suggestions, flags); - removeErrorSuggestionSpan(editable, start, end, RemoveReason.REPLACE); + boolean spanRemoved = removeErrorSuggestionSpan(editable, start, end, RemoveReason.REPLACE); + boolean sendAccessibilityEvent = !spanRemoved && mTextView.isVisibleToAccessibility(); + CharSequence beforeText = sendAccessibilityEvent ? new SpannedString(editable) : null; editable.setSpan(suggestionSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (sendAccessibilityEvent) { + mTextView.sendAccessibilityEventTypeViewTextChanged(beforeText, start, end); + } mTextView.invalidateRegion(start, end, false /* No cursor involved */); } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 8fba58364c94..496fa67498eb 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -12501,6 +12501,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return TextUtils.trimToParcelableSize(mTransformed); } + boolean isVisibleToAccessibility() { + return AccessibilityManager.getInstance(mContext).isEnabled() + && (isFocused() || (isSelected() && isShown())); + } + void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText, int fromIndex, int removedCount, int addedCount) { AccessibilityEvent event = @@ -12512,6 +12517,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener sendAccessibilityEventUnchecked(event); } + void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText, + int fromIndex, int toIndex) { + AccessibilityEvent event = + AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); + event.setFromIndex(fromIndex); + event.setToIndex(toIndex); + event.setBeforeText(beforeText); + sendAccessibilityEventUnchecked(event); + } + private InputMethodManager getInputMethodManager() { return getContext().getSystemService(InputMethodManager.class); } @@ -13826,10 +13841,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } TextView.this.handleTextChanged(buffer, start, before, after); - if (AccessibilityManager.getInstance(mContext).isEnabled() - && (isFocused() || (isSelected() && isShown()))) { + if (isVisibleToAccessibility()) { sendAccessibilityEventTypeViewTextChanged(mBeforeText, start, before, after); - mBeforeText = TextUtils.stringOrSpannedString(mTransformed); + mBeforeText = null; } } @@ -13857,54 +13871,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Log.v(LOG_TAG, "onSpanAdded s=" + s + " e=" + e + " what=" + what + ": " + buf); } TextView.this.spanChange(buf, what, -1, s, -1, e); - // Note we don't update mBeforeText here. We look for SuggestionSpans added after the - // text content changes. - if (AccessibilityManager.getInstance(mContext).isEnabled() - && (isFocused() || (isSelected() && isShown())) - && (what instanceof SuggestionSpan)) { - // When the user types a new word, and SuggestionSpans on the existing words will be - // removed and added again. We don't need to send out events for existing - // SuggestionSpans. Multiple spans can be placed on the range. - if (mBeforeText instanceof SpannedString) { - final SpannedString beforeSpannedString = (SpannedString) mBeforeText; - if ((beforeSpannedString.getSpanStart(what) == s) - && (beforeSpannedString.getSpanEnd(what) == e)) { - // Exactly same span is found. - return; - } - // Suggestion span couldn't be found. Try to find a suggestion span that has the - // same contents. - SuggestionSpan[] suggestionSpans = beforeSpannedString.getSpans(s, e, - SuggestionSpan.class); - for (final SuggestionSpan suggestionSpan : suggestionSpans) { - final int start = beforeSpannedString.getSpanStart(suggestionSpan); - if (start != s) { - continue; - } - final int end = beforeSpannedString.getSpanEnd(suggestionSpan); - if (end != e) { - continue; - } - if (equalSuggestionSpan(suggestionSpan, (SuggestionSpan) what)) { - return; - } - } - } - AccessibilityEvent event = - AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); - event.setFromIndex(s); - event.setToIndex(e); - event.setBeforeText(mBeforeText); - sendAccessibilityEventUnchecked(event); - } - } - - private boolean equalSuggestionSpan(SuggestionSpan span1, SuggestionSpan span2) { - // We compare flags because flags will determine the underline color. - return Arrays.equals(span1.getSuggestions(), span2.getSuggestions()) - && Objects.equals(span1.getLocaleObject(), span2.getLocaleObject()) - && span1.getLocale().equals(span2.getLocale()) - && (span1.getFlags() == span2.getFlags()); } public void onSpanRemoved(Spannable buf, Object what, int s, int e) { diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 9b1bef067cec..359c382f51bc 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -28,6 +28,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; +import android.app.ActivityTaskManager; import android.app.SharedElementCallback; import android.app.prediction.AppPredictionContext; import android.app.prediction.AppPredictionManager; @@ -70,9 +71,11 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.os.Handler; +import android.os.IBinder; import android.os.Message; import android.os.Parcelable; import android.os.PatternMatcher; +import android.os.RemoteException; import android.os.ResultReceiver; import android.os.UserHandle; import android.os.UserManager; @@ -151,6 +154,19 @@ public class ChooserActivity extends ResolverActivity implements ChooserListAdapter.ChooserListCommunicator, SelectableTargetInfoCommunicator { private static final String TAG = "ChooserActivity"; + + /** + * Whether this chooser is operating in "headless springboard" mode (as determined during + * onCreate). In this mode, our activity sits in the background and waits for the new + * "unbundled" chooser to handle the Sharesheet experience; the system ChooserActivity is + * responsible only for providing the startActivityAsCaller permission token and keeping it + * valid for the life of the unbundled delegate activity. + * + * TODO: when the unbundled chooser is fully launched, the system-side "springboard" can use a + * simpler implementation that doesn't inherit from ResolverActivity. + */ + private boolean mIsHeadlessSpringboardActivity; + private AppPredictor mPersonalAppPredictor; private AppPredictor mWorkAppPredictor; private boolean mShouldDisplayLandscape; @@ -170,6 +186,17 @@ public class ChooserActivity extends ResolverActivity implements = "com.android.internal.app.ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP"; /** + * Boolean extra added to "unbundled Sharesheet" delegation intents to signal whether the app + * prediction service is available. Our query of the service <em>availability</em> depends on + * privileges that are only available in the system, even though the service itself would then + * be available to the unbundled component. For now, we just include the query result as part of + * the handover intent. + * TODO: investigate whether the privileged query is necessary to determine the availability. + */ + protected static final String EXTRA_IS_APP_PREDICTION_SERVICE_AVAILABLE = + "com.android.internal.app.ChooserActivity.EXTRA_IS_APP_PREDICTION_SERVICE_AVAILABLE"; + + /** * Transition name for the first image preview. * To be used for shared element transition into this activity. * @hide @@ -235,6 +262,11 @@ public class ChooserActivity extends ResolverActivity implements private static final float DIRECT_SHARE_EXPANSION_RATE = 0.78f; + private boolean mEnableChooserDelegate = + DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, + SystemUiDeviceConfigFlags.USE_DELEGATE_CHOOSER, + false); + private static final int DEFAULT_SALT_EXPIRATION_DAYS = 7; private int mMaxHashSaltDays = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI, SystemUiDeviceConfigFlags.HASH_SALT_MAX_DAYS, @@ -500,6 +532,12 @@ public class ChooserActivity extends ResolverActivity implements @Override protected void onCreate(Bundle savedInstanceState) { + if (handOverToDelegateChooser()) { + super_onCreate(savedInstanceState); + mIsHeadlessSpringboardActivity = true; + return; + } + final long intentReceivedTime = System.currentTimeMillis(); getChooserActivityLogger().logSharesheetTriggered(); // This is the only place this value is being set. Effectively final. @@ -714,6 +752,69 @@ public class ChooserActivity extends ResolverActivity implements postponeEnterTransition(); } + private boolean handOverToDelegateChooser() { + // Check the explicit classname so that we don't interfere with the flow of any subclasses. + if (!this.getClass().getName().equals("com.android.internal.app.ChooserActivity") + || !mEnableChooserDelegate) { + return false; + } + + try { + IBinder permissionToken = ActivityTaskManager.getService() + .requestStartActivityPermissionToken(getActivityToken()); + Intent delegationIntent = new Intent(); + final ComponentName delegateActivity = ComponentName.unflattenFromString( + Resources.getSystem().getString(R.string.config_chooserActivity)); + delegationIntent.setComponent(delegateActivity); + delegationIntent.putExtra(Intent.EXTRA_INTENT, getIntent()); + delegationIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken); + + // Query prediction availability; mIsAppPredictorComponentAvailable isn't initialized. + delegationIntent.putExtra( + EXTRA_IS_APP_PREDICTION_SERVICE_AVAILABLE, isAppPredictionServiceAvailable()); + + delegationIntent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); + + // Don't close until the delegate finishes, or the token will be invalidated. + mAwaitingDelegateResponse = true; + startActivityForResult(delegationIntent, REQUEST_CODE_RETURN_FROM_DELEGATE_CHOOSER); + return true; + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + return false; + } + + @Override + protected void onRestart() { + if (mIsHeadlessSpringboardActivity) { + super_onRestart(); + return; + } + + super.onRestart(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + if (mIsHeadlessSpringboardActivity) { + super_onSaveInstanceState(outState); + return; + } + + super.onSaveInstanceState(outState); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + if (mIsHeadlessSpringboardActivity) { + super_onRestoreInstanceState(savedInstanceState); + return; + } + + super.onRestoreInstanceState(savedInstanceState); + } + @Override protected int appliedThemeResId() { return R.style.Theme_DeviceDefault_Chooser; @@ -886,7 +987,8 @@ public class ChooserActivity extends ResolverActivity implements return false; } - // Check if the app prediction component actually exists on the device. + // Check if the app prediction component actually exists on the device. The component is + // only visible when this is running in a system activity; otherwise this check will fail. Intent intent = new Intent(); intent.setComponent(appPredictionComponentName); if (getPackageManager().resolveService(intent, PackageManager.MATCH_ALL) == null) { @@ -998,6 +1100,11 @@ public class ChooserActivity extends ResolverActivity implements @Override public void onConfigurationChanged(Configuration newConfig) { + if (mIsHeadlessSpringboardActivity) { + super_onConfigurationChanged(newConfig); + return; + } + super.onConfigurationChanged(newConfig); ViewPager viewPager = findViewById(R.id.profile_pager); if (viewPager.isLayoutRtl()) { @@ -1543,6 +1650,11 @@ public class ChooserActivity extends ResolverActivity implements @Override protected void onDestroy() { super.onDestroy(); + + if (mIsHeadlessSpringboardActivity) { + return; + } + if (mRefinementResultReceiver != null) { mRefinementResultReceiver.destroy(); mRefinementResultReceiver = null; diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 9af4f9124bc8..fd8637abfc6b 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -152,7 +152,7 @@ public class ResolverActivity extends Activity implements /** See {@link #setRetainInOnStop}. */ private boolean mRetainInOnStop; - private static final int REQUEST_CODE_RETURN_FROM_DELEGATE_CHOOSER = 20; + protected static final int REQUEST_CODE_RETURN_FROM_DELEGATE_CHOOSER = 20; private static final String EXTRA_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args"; private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key"; @@ -323,6 +323,86 @@ public class ResolverActivity extends Activity implements super.onCreate(savedInstanceState); } + /** + * Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode + * where we hand over to the unbundled chooser (while violating many of the invariants of a + * typical ResolverActivity implementation). Subclasses running in this mode need to be able + * to opt-out of the normal ResolverActivity behavior. + * + * TODO: this should be removed later on in the unbundling migration, when the springboard + * activity no longer needs to derive from ResolverActivity. The hold-over design here is + * <em>not</em> good practice (e.g. there could be other events that weren't anticipated as + * requiring this kind of "pass-through" override, and so might fall back on ResolverActivity + * implementations that depend on the invariants that are violated in the headless mode). If + * necessary, we could instead consider using a springboard-only activity on the system side + * immediately, which would delegate either to the unbundled chooser, or to a + * (properly-inheriting) system ChooserActivity. This would have performance implications even + * when the unbundling experiment is disabled. + */ + protected void super_onRestart() { + super.onRestart(); + } + + /** + * Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode + * where we hand over to the unbundled chooser (while violating many of the invariants of a + * typical ResolverActivity implementation). Subclasses running in this mode need to be able + * to opt-out of the normal ResolverActivity behavior. + * + * TODO: this should be removed later on in the unbundling migration, when the springboard + * activity no longer needs to derive from ResolverActivity. The hold-over design here is + * <em>not</em> good practice (e.g. there could be other events that weren't anticipated as + * requiring this kind of "pass-through" override, and so might fall back on ResolverActivity + * implementations that depend on the invariants that are violated in the headless mode). If + * necessary, we could instead consider using a springboard-only activity on the system side + * immediately, which would delegate either to the unbundled chooser, or to a + * (properly-inheriting) system ChooserActivity. This would have performance implications even + * when the unbundling experiment is disabled. + */ + protected void super_onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } + + /** + * Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode + * where we hand over to the unbundled chooser (while violating many of the invariants of a + * typical ResolverActivity implementation). Subclasses running in this mode need to be able + * to opt-out of the normal ResolverActivity behavior. + * + * TODO: this should be removed later on in the unbundling migration, when the springboard + * activity no longer needs to derive from ResolverActivity. The hold-over design here is + * <em>not</em> good practice (e.g. there could be other events that weren't anticipated as + * requiring this kind of "pass-through" override, and so might fall back on ResolverActivity + * implementations that depend on the invariants that are violated in the headless mode). If + * necessary, we could instead consider using a springboard-only activity on the system side + * immediately, which would delegate either to the unbundled chooser, or to a + * (properly-inheriting) system ChooserActivity. This would have performance implications even + * when the unbundling experiment is disabled. + */ + protected void super_onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + } + + /** + * Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode + * where we hand over to the unbundled chooser (while violating many of the invariants of a + * typical ResolverActivity implementation). Subclasses running in this mode need to be able + * to opt-out of the normal ResolverActivity behavior. + * + * TODO: this should be removed later on in the unbundling migration, when the springboard + * activity no longer needs to derive from ResolverActivity. The hold-over design here is + * <em>not</em> good practice (e.g. there could be other events that weren't anticipated as + * requiring this kind of "pass-through" override, and so might fall back on ResolverActivity + * implementations that depend on the invariants that are violated in the headless mode). If + * necessary, we could instead consider using a springboard-only activity on the system side + * immediately, which would delegate either to the unbundled chooser, or to a + * (properly-inheriting) system ChooserActivity. This would have performance implications even + * when the unbundling experiment is disabled. + */ + public void super_onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + } + @Override protected void onCreate(Bundle savedInstanceState) { // Use a specialized prompt when we're handling the 'Home' app startActivity() @@ -877,7 +957,7 @@ public class ResolverActivity extends Activity implements } final Intent intent = getIntent(); if ((intent.getFlags() & FLAG_ACTIVITY_NEW_TASK) != 0 && !isVoiceInteraction() - && !mResolvingHome && !mRetainInOnStop) { + && !mResolvingHome && !mRetainInOnStop && !mAwaitingDelegateResponse) { // This resolver is in the unusual situation where it has been // launched at the top of a new task. We don't let it be added // to the recent tasks shown to the user, and we need to make sure diff --git a/core/java/com/android/internal/os/ClassLoaderFactory.java b/core/java/com/android/internal/os/ClassLoaderFactory.java index 8b0411de5477..8f5e97d40530 100644 --- a/core/java/com/android/internal/os/ClassLoaderFactory.java +++ b/core/java/com/android/internal/os/ClassLoaderFactory.java @@ -24,6 +24,7 @@ import dalvik.system.DelegateLastClassLoader; import dalvik.system.DexClassLoader; import dalvik.system.PathClassLoader; +import java.util.ArrayList; import java.util.List; /** @@ -100,14 +101,25 @@ public class ClassLoaderFactory { } /** - * Same as {@code createClassLoader} below, but passes a null list of shared - * libraries. + * Same as {@code createClassLoader} below, but passes a null list of shared libraries. This + * method is used only to load platform classes (i.e. those in framework.jar or services.jar), + * and MUST NOT be used for loading untrusted classes, especially the app classes. For the + * latter case, use the below method which accepts list of shared libraries so that the classes + * don't have unlimited access to all shared libraries. */ public static ClassLoader createClassLoader(String dexPath, String librarySearchPath, String libraryPermittedPath, ClassLoader parent, int targetSdkVersion, boolean isNamespaceShared, String classLoaderName) { + // b/205164833: allow framework classes to have access to all public vendor libraries. + // This is because those classes are part of the platform and don't have an app manifest + // where required libraries can be specified using the <uses-native-library> tag. + // Note that this still does not give access to "private" vendor libraries. + List<String> nativeSharedLibraries = new ArrayList<>(); + nativeSharedLibraries.add("ALL"); + return createClassLoader(dexPath, librarySearchPath, libraryPermittedPath, - parent, targetSdkVersion, isNamespaceShared, classLoaderName, null, null, null); + parent, targetSdkVersion, isNamespaceShared, classLoaderName, null, + nativeSharedLibraries, null); } /** diff --git a/core/java/com/android/internal/protolog/ProtoLogGroup.java b/core/java/com/android/internal/protolog/ProtoLogGroup.java index 954204fe781c..5ac493637822 100644 --- a/core/java/com/android/internal/protolog/ProtoLogGroup.java +++ b/core/java/com/android/internal/protolog/ProtoLogGroup.java @@ -84,7 +84,7 @@ public enum ProtoLogGroup implements IProtoLogGroup { Consts.TAG_WM), WM_DEBUG_LAYER_MIRRORING(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true, Consts.TAG_WM), - WM_DEBUG_WALLPAPER(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true, Consts.TAG_WM), + WM_DEBUG_WALLPAPER(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM), TEST_GROUP(true, true, false, "WindowManagerProtoLogTest"); private final boolean mEnabled; diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index f93e32fd0b55..6673f6781ef8 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -90,10 +90,6 @@ public class BaseIWindow extends IWindow.Stub { } @Override - public void windowFocusChanged(boolean hasFocus) { - } - - @Override public void executeCommand(String command, String parameters, ParcelFileDescriptor out) { if (out != null) { try { diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp index cdfd08971905..e7b3fba961e6 100644 --- a/core/jni/android_graphics_BLASTBufferQueue.cpp +++ b/core/jni/android_graphics_BLASTBufferQueue.cpp @@ -79,7 +79,7 @@ static void nativeMergeWithNextTransaction(JNIEnv*, jclass clazz, jlong ptr, jlo jlong framenumber) { sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionPtr); - queue->mergeWithNextTransaction(transaction, framenumber); + queue->mergeWithNextTransaction(transaction, CC_UNLIKELY(framenumber < 0) ? 0 : framenumber); } static jlong nativeGetLastAcquiredFrameNum(JNIEnv* env, jclass clazz, jlong ptr) { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index d3ee98a01951..601280a25873 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -6395,6 +6395,10 @@ android:permission="android.permission.BIND_JOB_SERVICE"> </service> + <service android:name="com.android.server.compos.IsolatedCompilationJobService" + android:permission="android.permission.BIND_JOB_SERVICE"> + </service> + <service android:name="com.android.server.PruneInstantAppsJobService" android:permission="android.permission.BIND_JOB_SERVICE" > </service> diff --git a/core/res/res/anim/task_fragment_close_enter.xml b/core/res/res/anim/task_fragment_close_enter.xml new file mode 100644 index 000000000000..c940552d53ad --- /dev/null +++ b/core/res/res/anim/task_fragment_close_enter.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:shareInterpolator="false"> + <scale + android:fromXScale="1.1" + android:toXScale="1" + android:fromYScale="1.1" + android:toYScale="1" + android:pivotX="50%" + android:pivotY="50%" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:duration="400"/> +</set>
\ No newline at end of file diff --git a/core/res/res/anim/task_fragment_close_exit.xml b/core/res/res/anim/task_fragment_close_exit.xml new file mode 100644 index 000000000000..8998f764ff9b --- /dev/null +++ b/core/res/res/anim/task_fragment_close_exit.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:shareInterpolator="false" + android:zAdjustment="top"> + <alpha + android:fromAlpha="1" + android:toAlpha="0.0" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/linear" + android:startOffset="33" + android:duration="50"/> + <scale + android:fromXScale="1" + android:toXScale="0.9" + android:fromYScale="1" + android:toYScale="0.9" + android:pivotX="50%" + android:pivotY="50%" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:duration="400"/> +</set> diff --git a/core/res/res/anim/task_fragment_open_enter.xml b/core/res/res/anim/task_fragment_open_enter.xml new file mode 100644 index 000000000000..6bc47deb2de4 --- /dev/null +++ b/core/res/res/anim/task_fragment_open_enter.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:shareInterpolator="false"> + <alpha + android:fromAlpha="0" + android:toAlpha="1.0" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/linear" + android:startOffset="50" + android:duration="50"/> + <scale + android:fromXScale="0.85" + android:toXScale="1" + android:fromYScale="0.85" + android:toYScale="1" + android:pivotX="50%" + android:pivotY="50%" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:duration="400"/> +</set> diff --git a/core/res/res/anim/task_fragment_open_exit.xml b/core/res/res/anim/task_fragment_open_exit.xml new file mode 100644 index 000000000000..160eb84223da --- /dev/null +++ b/core/res/res/anim/task_fragment_open_exit.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:shareInterpolator="false"> + <scale + android:fromXScale="1" + android:toXScale="1.05" + android:fromYScale="1" + android:toYScale="1.05" + android:pivotX="50%" + android:pivotY="50%" + android:fillEnabled="true" + android:fillBefore="true" + android:fillAfter="true" + android:interpolator="@interpolator/fast_out_extra_slow_in" + android:duration="400"/> +</set>
\ No newline at end of file diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index b06dbd984bfd..0f4746594bc5 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -2180,7 +2180,7 @@ <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Апавяшчэнне з інфармацыяй пра ўсталяваны рэжым"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Акумулятар можа разрадзіцца хутчэй, чым прыйдзе час звычайнай зарадкі"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Каб павялічыць тэрмін работы акумулятара, уключаны рэжым эканоміі зараду"</string> - <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Эканомія зараду"</string> + <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Рэжым энергазберажэння"</string> <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Рэжым эканоміі зараду выключаны"</string> <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"У тэлефона дастатковы ўзровень зараду. Функцыі больш не абмежаваны."</string> <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"У планшэта дастатковы ўзровень зараду. Функцыі больш не абмежаваны."</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index e0a53637e2ee..88d6cd3e7e57 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -1732,7 +1732,7 @@ <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Réduction supplémentaire de la luminosité"</string> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume maintenues enfoncées. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume maintenues enfoncées. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string> - <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Maintenez enfoncées les deux touches de volume pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string> + <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Maintenez les deux touches de volume enfoncées pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string> <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Choisissez une fonctionnalité à utiliser lorsque vous touchez le bouton d\'accessibilité :"</string> <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Choisissez une fonctionnalité à utiliser lorsque vous utilisez le geste d\'accessibilité (balayer l\'écran de bas en haut avec deux doigts) :"</string> <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Choisissez une fonctionnalité à utiliser lorsque vous utilisez le geste d\'accessibilité (balayer l\'écran de bas en haut avec trois doigts) :"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 3dfbd066a905..3387fa02cd4a 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -35,7 +35,7 @@ <string name="mmiError" msgid="2862759606579822246">"Problem s vezom ili nevažeći MMI kôd."</string> <string name="mmiFdnError" msgid="3975490266767565852">"Operacija je ograničena samo na brojeve s fiksnim biranjem."</string> <string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Nije moguće promijeniti postavke preusmjeravanja poziva na telefonu dok ste u roamingu."</string> - <string name="serviceEnabled" msgid="7549025003394765639">"Usluga nije omogućena."</string> + <string name="serviceEnabled" msgid="7549025003394765639">"Usluga je omogućena."</string> <string name="serviceEnabledFor" msgid="1463104778656711613">"Usluga je omogućena za korisnika:"</string> <string name="serviceDisabled" msgid="641878791205871379">"Usluga je onemogućena."</string> <string name="serviceRegistered" msgid="3856192211729577482">"Registracija je uspješna."</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 71cda82a7ece..548d4ad22939 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -51,8 +51,8 @@ <string name="needPuk2" msgid="7032612093451537186">"Digita il PUK2 per sbloccare la SIM."</string> <string name="enablePin" msgid="2543771964137091212">"Operazione non riuscita; attiva blocco SIM/RUIM."</string> <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584"> + <item quantity="one">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item> <item quantity="other">Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM venga bloccata.</item> - <item quantity="one">Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM venga bloccata.</item> </plurals> <string name="imei" msgid="2157082351232630390">"IMEI"</string> <string name="meid" msgid="3291227361605924674">"MEID"</string> @@ -181,8 +181,8 @@ <string name="low_memory" product="tv" msgid="6663680413790323318">"Lo spazio di archiviazione del dispositivo Android TV è pieno. Elimina alcuni file per liberare spazio."</string> <string name="low_memory" product="default" msgid="2539532364144025569">"Spazio di archiviazione del telefono esaurito. Elimina alcuni file per liberare spazio."</string> <plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029"> + <item quantity="one">Certificate authorities installed</item> <item quantity="other">Autorità di certificazione installate</item> - <item quantity="one">Autorità di certificazione installata</item> </plurals> <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Da una terza parte sconosciuta"</string> <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Dall\'amministratore del tuo profilo di lavoro"</string> @@ -257,8 +257,8 @@ <string name="bugreport_option_full_title" msgid="7681035745950045690">"Report completo"</string> <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilizza questa opzione per ridurre al minimo l\'interferenza di sistema quando il dispositivo non risponde, è troppo lento oppure quando ti servono tutte le sezioni della segnalazione. Non puoi inserire altri dettagli o acquisire altri screenshot."</string> <plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206"> + <item quantity="one">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item> <item quantity="other">Lo screenshot per la segnalazione di bug verrà acquisito tra <xliff:g id="NUMBER_1">%d</xliff:g> secondi.</item> - <item quantity="one">Lo screenshot per la segnalazione di bug verrà acquisito tra <xliff:g id="NUMBER_0">%d</xliff:g> secondo.</item> </plurals> <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Screenshot con segnalazione di bug effettuato correttamente"</string> <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"Impossibile acquisire screenshot con segnalazione di bug"</string> @@ -1061,8 +1061,8 @@ <string name="oneMonthDurationPast" msgid="4538030857114635777">"1 mese fa"</string> <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Oltre 1 mese fa"</string> <plurals name="last_num_days" formatted="false" msgid="687443109145393632"> + <item quantity="one">Last <xliff:g id="COUNT_1">%d</xliff:g> days</item> <item quantity="other">Ultimi <xliff:g id="COUNT_1">%d</xliff:g> giorni</item> - <item quantity="one">Ultimo giorno (<xliff:g id="COUNT_0">%d</xliff:g>)</item> </plurals> <string name="last_month" msgid="1528906781083518683">"Ultimo mese"</string> <string name="older" msgid="1645159827884647400">"Precedente"</string> @@ -1083,68 +1083,68 @@ <string name="years" msgid="5797714729103773425">"anni"</string> <string name="now_string_shortest" msgid="3684914126941650330">"ora"</string> <plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135"> + <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>m</item> <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item> - <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> m</item> </plurals> <plurals name="duration_hours_shortest" formatted="false" msgid="2838655994500499651"> + <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>h</item> <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item> - <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> h</item> </plurals> <plurals name="duration_days_shortest" formatted="false" msgid="3686058472983158496"> + <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>d</item> <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> g</item> - <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> g</item> </plurals> <plurals name="duration_years_shortest" formatted="false" msgid="8299112348723640338"> + <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>y</item> <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item> - <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> a</item> </plurals> <plurals name="duration_minutes_shortest_future" formatted="false" msgid="849196137176399440"> + <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>m</item> <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> m</item> - <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> m</item> </plurals> <plurals name="duration_hours_shortest_future" formatted="false" msgid="5386373597343170388"> + <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>h</item> <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> h</item> - <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> h</item> </plurals> <plurals name="duration_days_shortest_future" formatted="false" msgid="814754627092787227"> + <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>d</item> <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> g</item> - <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> g</item> </plurals> <plurals name="duration_years_shortest_future" formatted="false" msgid="7683731800140202145"> + <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>y</item> <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> a</item> - <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> a</item> </plurals> <plurals name="duration_minutes_relative" formatted="false" msgid="6569851308583028344"> + <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> minutes ago</item> <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> minuti fa</item> - <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> minuto fa</item> </plurals> <plurals name="duration_hours_relative" formatted="false" msgid="420434788589102019"> + <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> hours ago</item> <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ore fa</item> - <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ora fa</item> </plurals> <plurals name="duration_days_relative" formatted="false" msgid="6056425878237482431"> + <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> days ago</item> <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> giorni fa</item> - <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> giorno fa</item> </plurals> <plurals name="duration_years_relative" formatted="false" msgid="2179998228861172159"> + <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> years ago</item> <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> anni fa</item> - <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> anno fa</item> </plurals> <plurals name="duration_minutes_relative_future" formatted="false" msgid="5759885720917567723"> + <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> minutes</item> <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> minuti</item> - <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> minuto</item> </plurals> <plurals name="duration_hours_relative_future" formatted="false" msgid="8963511608507707959"> + <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> hours</item> <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> ore</item> - <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> ora</item> </plurals> <plurals name="duration_days_relative_future" formatted="false" msgid="1964709470979250702"> + <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> days</item> <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> giorni</item> - <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> giorno</item> </plurals> <plurals name="duration_years_relative_future" formatted="false" msgid="3985129025134896371"> + <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> years</item> <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> anni</item> - <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> anno</item> </plurals> <string name="VideoView_error_title" msgid="5750686717225068016">"Problemi video"</string> <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"Questo video non è valido per lo streaming su questo dispositivo."</string> @@ -1526,8 +1526,8 @@ <string name="no_matches" msgid="6472699895759164599">"Nessuna corrispondenza"</string> <string name="find_on_page" msgid="5400537367077438198">"Trova nella pagina"</string> <plurals name="matches_found" formatted="false" msgid="1101758718194295554"> + <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g></item> <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> di <xliff:g id="TOTAL">%d</xliff:g></item> - <item quantity="one">1 partita</item> </plurals> <string name="action_mode_done" msgid="2536182504764803222">"Fine"</string> <string name="progress_erasing" msgid="6891435992721028004">"Cancellazione archivio condiviso…"</string> @@ -1659,8 +1659,8 @@ <string name="kg_wrong_password" msgid="2384677900494439426">"Password sbagliata"</string> <string name="kg_wrong_pin" msgid="3680925703673166482">"PIN errato"</string> <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="236717428673283568"> + <item quantity="one">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item> <item quantity="other">Riprova fra <xliff:g id="NUMBER">%d</xliff:g> secondi.</item> - <item quantity="one">Riprova fra 1 secondo.</item> </plurals> <string name="kg_pattern_instructions" msgid="8366024510502517748">"Inserisci la sequenza"</string> <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Inserisci il PIN della SIM"</string> @@ -1859,8 +1859,8 @@ <string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"I PIN non corrispondono. Riprova."</string> <string name="restr_pin_error_too_short" msgid="1547007808237941065">"Il PIN è troppo corto. Deve avere almeno quattro cifre."</string> <plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153"> + <item quantity="one">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item> <item quantity="other">Riprova tra <xliff:g id="COUNT">%d</xliff:g> secondi</item> - <item quantity="one">Riprova tra 1 secondo</item> </plurals> <string name="restr_pin_try_later" msgid="5897719962541636727">"Riprova più tardi"</string> <string name="immersive_cling_title" msgid="2307034298721541791">"Visualizzazione a schermo intero"</string> @@ -1890,36 +1890,36 @@ <string name="data_saver_enable_title" msgid="7080620065745260137">"Attivare Risparmio dati?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Attiva"</string> <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273"> + <item quantity="one">For %1$d minutes (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> <item quantity="other">Per %1$d minuti (fino alle ore <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> - <item quantity="one">Per un minuto (fino alle ore <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item> </plurals> <plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="4230730310318858312"> + <item quantity="one">For %1$d min (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> <item quantity="other">Per %1$d minuti (fino alle ore <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> - <item quantity="one">Per 1 minuto (fino alle ore <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item> </plurals> <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="7725354244196466758"> + <item quantity="one">For %1$d hours (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> <item quantity="other">Per %1$d ore (fino alle ore <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> - <item quantity="one">Per 1 ora (fino alle ore <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item> </plurals> <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="588719069121765642"> + <item quantity="one">For %1$d hr (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> <item quantity="other">Per %1$d ore (fino alle ore <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> - <item quantity="one">Per 1 ora (fino alle ore <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item> </plurals> <plurals name="zen_mode_duration_minutes" formatted="false" msgid="1148568456958944998"> + <item quantity="one">For %d minutes</item> <item quantity="other">Per %d minuti</item> - <item quantity="one">Per un minuto</item> </plurals> <plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2742377799995454859"> + <item quantity="one">For %d min</item> <item quantity="other">Per %d minuti</item> - <item quantity="one">Per 1 minuto</item> </plurals> <plurals name="zen_mode_duration_hours" formatted="false" msgid="525401855645490022"> + <item quantity="one">For %d hours</item> <item quantity="other">Per %d ore</item> - <item quantity="one">Per 1 ora</item> </plurals> <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="7644653189680911640"> + <item quantity="one">For %d hr</item> <item quantity="other">Per %d ore</item> - <item quantity="one">Per 1 ora</item> </plurals> <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Fino a: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_until" msgid="2250286190237669079">"Fino a <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> @@ -1968,8 +1968,8 @@ <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Chiamata in corso"</string> <string name="call_notification_screening_text" msgid="8396931408268940208">"Applicazione filtro a chiamata in arrivo"</string> <plurals name="selected_count" formatted="false" msgid="3946212171128200491"> + <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item> <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> file selezionati</item> - <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> file selezionato</item> </plurals> <string name="default_notification_channel_label" msgid="3697928973567217330">"Senza categoria"</string> <string name="importance_from_user" msgid="2782756722448800447">"Stabilisci tu l\'importanza di queste notifiche."</string> @@ -2036,8 +2036,8 @@ <string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"Impossibile compilare automaticamente i contenuti"</string> <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Nessun suggerimento di Compilazione automatica"</string> <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="6651883186966959978"> + <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> autofill suggestions</item> <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggerimenti di Compilazione automatica</item> - <item quantity="one">Un suggerimento di Compilazione automatica</item> </plurals> <string name="autofill_save_title" msgid="7719802414283739775">"Vuoi salvare su "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Vuoi salvare la <xliff:g id="TYPE">%1$s</xliff:g> su "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string> @@ -2140,8 +2140,8 @@ <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Il Bluetooth rimane attivo durante l\'uso della modalità aereo"</string> <string name="car_loading_profile" msgid="8219978381196748070">"Caricamento"</string> <plurals name="file_count" formatted="false" msgid="7063513834724389247"> + <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> file</item> <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> file</item> - <item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> file</item> </plurals> <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Nessuna persona consigliata per la condivisione"</string> <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Elenco di app"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index d5b92b7c6fa3..a4e012394bc8 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -219,7 +219,7 @@ <string name="turn_on_radio" msgid="2961717788170634233">"უსადენო კავშირის ჩართვა"</string> <string name="turn_off_radio" msgid="7222573978109933360">"უსადენო ინტერნეტის გამორთვა"</string> <string name="screen_lock" msgid="2072642720826409809">"ეკრანის დაბლოკვა"</string> - <string name="power_off" msgid="4111692782492232778">"გამორთვ."</string> + <string name="power_off" msgid="4111692782492232778">"გამორთვა"</string> <string name="silent_mode_silent" msgid="5079789070221150912">"მრეკავი გათიშულია"</string> <string name="silent_mode_vibrate" msgid="8821830448369552678">"ვიბრაციის რეჟიმი"</string> <string name="silent_mode_ring" msgid="6039011004781526678">"ზარი ჩართულია"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 7006273e88d5..98ac85ee725c 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -51,8 +51,8 @@ <string name="needPuk2" msgid="7032612093451537186">"Introduza o PUK2 para desbloquear o cartão SIM."</string> <string name="enablePin" msgid="2543771964137091212">"Ação sem êxito. Ative o bloqueio do SIM/RUIM."</string> <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584"> - <item quantity="other">Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar bloqueado.</item> <item quantity="one">Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar bloqueado.</item> + <item quantity="other">Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar bloqueado.</item> </plurals> <string name="imei" msgid="2157082351232630390">"IMEI"</string> <string name="meid" msgid="3291227361605924674">"MEID"</string> @@ -181,8 +181,8 @@ <string name="low_memory" product="tv" msgid="6663680413790323318">"O armazenamento do dispositivo Android TV está cheio. Elimine alguns ficheiros para libertar espaço."</string> <string name="low_memory" product="default" msgid="2539532364144025569">"O armazenamento do telemóvel está cheio. Elimine alguns ficheiros para libertar espaço."</string> <plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029"> - <item quantity="other">Autoridades de certificação instaladas</item> <item quantity="one">Autoridade de certificação instalada</item> + <item quantity="other">Autoridades de certificação instaladas</item> </plurals> <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Por um terceiro desconhecido"</string> <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Pelo gestor do seu perfil de trabalho"</string> @@ -257,8 +257,8 @@ <string name="bugreport_option_full_title" msgid="7681035745950045690">"Relatório completo"</string> <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilize esta opção para uma interferência mínima do sistema quando o dispositivo não responder ou estiver demasiado lento, ou quando precisar de todas as secções de relatório. Não permite introduzir mais detalhes ou tirar capturas de ecrã adicionais."</string> <plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206"> - <item quantity="other">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item> <item quantity="one">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_0">%d</xliff:g> segundo…</item> + <item quantity="other">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item> </plurals> <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Captura de ecrã tirada com o relatório de erro."</string> <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"Falha ao fazer captura de ecrã com o relatório de erro."</string> @@ -1061,8 +1061,8 @@ <string name="oneMonthDurationPast" msgid="4538030857114635777">"Há 1 mês"</string> <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Há mais de 1 mês"</string> <plurals name="last_num_days" formatted="false" msgid="687443109145393632"> - <item quantity="other">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dias</item> <item quantity="one">Último <xliff:g id="COUNT_0">%d</xliff:g> dia</item> + <item quantity="other">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dias</item> </plurals> <string name="last_month" msgid="1528906781083518683">"Último mês"</string> <string name="older" msgid="1645159827884647400">"Mais antiga"</string> @@ -1083,68 +1083,68 @@ <string name="years" msgid="5797714729103773425">"anos"</string> <string name="now_string_shortest" msgid="3684914126941650330">"agora"</string> <plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135"> - <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item> <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> m</item> + <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item> </plurals> <plurals name="duration_hours_shortest" formatted="false" msgid="2838655994500499651"> - <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item> <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> h</item> + <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item> </plurals> <plurals name="duration_days_shortest" formatted="false" msgid="3686058472983158496"> - <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> d</item> <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> d</item> + <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> d</item> </plurals> <plurals name="duration_years_shortest" formatted="false" msgid="8299112348723640338"> - <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item> <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> a</item> + <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item> </plurals> <plurals name="duration_minutes_shortest_future" formatted="false" msgid="849196137176399440"> - <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> min</item> <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> min</item> + <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> min</item> </plurals> <plurals name="duration_hours_shortest_future" formatted="false" msgid="5386373597343170388"> - <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> h</item> <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> h</item> + <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> h</item> </plurals> <plurals name="duration_days_shortest_future" formatted="false" msgid="814754627092787227"> - <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> d</item> <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> d</item> + <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> d</item> </plurals> <plurals name="duration_years_shortest_future" formatted="false" msgid="7683731800140202145"> - <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> a</item> <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> a</item> + <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> a</item> </plurals> <plurals name="duration_minutes_relative" formatted="false" msgid="6569851308583028344"> - <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> minutos</item> <item quantity="one">há <xliff:g id="COUNT_0">%d</xliff:g> minuto</item> + <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> minutos</item> </plurals> <plurals name="duration_hours_relative" formatted="false" msgid="420434788589102019"> - <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> horas</item> <item quantity="one">há <xliff:g id="COUNT_0">%d</xliff:g> hora</item> + <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> horas</item> </plurals> <plurals name="duration_days_relative" formatted="false" msgid="6056425878237482431"> - <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> dias</item> <item quantity="one">há <xliff:g id="COUNT_0">%d</xliff:g> dia</item> + <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> dias</item> </plurals> <plurals name="duration_years_relative" formatted="false" msgid="2179998228861172159"> - <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> anos</item> <item quantity="one">há <xliff:g id="COUNT_0">%d</xliff:g> ano</item> + <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> anos</item> </plurals> <plurals name="duration_minutes_relative_future" formatted="false" msgid="5759885720917567723"> - <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> minutos</item> <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> minuto</item> + <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> minutos</item> </plurals> <plurals name="duration_hours_relative_future" formatted="false" msgid="8963511608507707959"> - <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> horas</item> <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> hora</item> + <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> horas</item> </plurals> <plurals name="duration_days_relative_future" formatted="false" msgid="1964709470979250702"> - <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> dias</item> <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> dia</item> + <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> dias</item> </plurals> <plurals name="duration_years_relative_future" formatted="false" msgid="3985129025134896371"> - <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> anos</item> <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> ano</item> + <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> anos</item> </plurals> <string name="VideoView_error_title" msgid="5750686717225068016">"Problema com o vídeo"</string> <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"Este vídeo não é válido para transmissão neste aparelho."</string> @@ -1526,8 +1526,8 @@ <string name="no_matches" msgid="6472699895759164599">"Sem correspondências"</string> <string name="find_on_page" msgid="5400537367077438198">"Localizar na página"</string> <plurals name="matches_found" formatted="false" msgid="1101758718194295554"> - <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item> <item quantity="one">1 correspondência</item> + <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item> </plurals> <string name="action_mode_done" msgid="2536182504764803222">"Concluído"</string> <string name="progress_erasing" msgid="6891435992721028004">"A apagar o armazenamento partilhado…"</string> @@ -1659,8 +1659,8 @@ <string name="kg_wrong_password" msgid="2384677900494439426">"Palavra-passe Incorreta"</string> <string name="kg_wrong_pin" msgid="3680925703673166482">"PIN Incorreto"</string> <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="236717428673283568"> - <item quantity="other">Tente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos.</item> <item quantity="one">Tente novamente dentro de 1 segundo.</item> + <item quantity="other">Tente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos.</item> </plurals> <string name="kg_pattern_instructions" msgid="8366024510502517748">"Desenhe a sua sequência"</string> <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Introduzir PIN do cartão SIM"</string> @@ -1859,8 +1859,8 @@ <string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"Os PINs não correspondem. Tente novamente."</string> <string name="restr_pin_error_too_short" msgid="1547007808237941065">"O PIN é demasiado pequeno. Deve ter, no mínimo, 4 dígitos."</string> <plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153"> - <item quantity="other">Tente novamente dentro de <xliff:g id="COUNT">%d</xliff:g> segundos</item> <item quantity="one">Tente novamente dentro de 1 segundo</item> + <item quantity="other">Tente novamente dentro de <xliff:g id="COUNT">%d</xliff:g> segundos</item> </plurals> <string name="restr_pin_try_later" msgid="5897719962541636727">"Tente novamente mais tarde"</string> <string name="immersive_cling_title" msgid="2307034298721541791">"Visualização de ecrã inteiro"</string> @@ -1890,36 +1890,36 @@ <string name="data_saver_enable_title" msgid="7080620065745260137">"Pretende ativar a Poupança de dados?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Ativar"</string> <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273"> - <item quantity="other">Durante %1$d minutos (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> <item quantity="one">Durante um minuto (até à(s) <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item> + <item quantity="other">Durante %1$d minutos (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> </plurals> <plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="4230730310318858312"> - <item quantity="other">Durante %1$d min (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> <item quantity="one">Durante 1 min (até à(s) <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item> + <item quantity="other">Durante %1$d min (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> </plurals> <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="7725354244196466758"> - <item quantity="other">Durante %1$d horas (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> <item quantity="one">Durante 1 hora (até à(s) <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item> + <item quantity="other">Durante %1$d horas (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> </plurals> <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="588719069121765642"> - <item quantity="other">Durante %1$d h (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> <item quantity="one">Durante 1 h (até à(s) <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item> + <item quantity="other">Durante %1$d h (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> </plurals> <plurals name="zen_mode_duration_minutes" formatted="false" msgid="1148568456958944998"> - <item quantity="other">Durante %d minutos</item> <item quantity="one">Durante um minuto</item> + <item quantity="other">Durante %d minutos</item> </plurals> <plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2742377799995454859"> - <item quantity="other">Durante %d min</item> <item quantity="one">Durante 1 min</item> + <item quantity="other">Durante %d min</item> </plurals> <plurals name="zen_mode_duration_hours" formatted="false" msgid="525401855645490022"> - <item quantity="other">Durante %d horas</item> <item quantity="one">Durante 1 hora</item> + <item quantity="other">Durante %d horas</item> </plurals> <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="7644653189680911640"> - <item quantity="other">Durante %d h</item> <item quantity="one">Durante 1 h</item> + <item quantity="other">Durante %d h</item> </plurals> <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_until" msgid="2250286190237669079">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> @@ -1968,8 +1968,8 @@ <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Chamada em curso"</string> <string name="call_notification_screening_text" msgid="8396931408268940208">"A filtrar uma chamada recebida…"</string> <plurals name="selected_count" formatted="false" msgid="3946212171128200491"> - <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item> <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selecionado</item> + <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item> </plurals> <string name="default_notification_channel_label" msgid="3697928973567217330">"Sem categoria"</string> <string name="importance_from_user" msgid="2782756722448800447">"Definiu a importância destas notificações."</string> @@ -2036,8 +2036,8 @@ <string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"Não é possível preencher automaticamente o conteúdo"</string> <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Sem sugestões do preenchimento automático"</string> <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="6651883186966959978"> - <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugestões do preenchimento automático</item> <item quantity="one">Uma sugestão do preenchimento automático</item> + <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugestões do preenchimento automático</item> </plurals> <string name="autofill_save_title" msgid="7719802414283739775">"Pretende guardar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Pretende guardar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string> @@ -2140,8 +2140,8 @@ <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"O Bluetooth continuará ativado durante o modo de avião."</string> <string name="car_loading_profile" msgid="8219978381196748070">"A carregar…"</string> <plurals name="file_count" formatted="false" msgid="7063513834724389247"> - <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ficheiros</item> <item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ficheiro</item> + <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ficheiros</item> </plurals> <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Não existem pessoas recomendadas com quem partilhar"</string> <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Lista de aplicações"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index a6f82572733c..c14dd450f473 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -223,7 +223,7 @@ <string name="turn_on_radio" msgid="2961717788170634233">"Vklopi brezžično omrežje"</string> <string name="turn_off_radio" msgid="7222573978109933360">"Izklopi brezžično omrežje"</string> <string name="screen_lock" msgid="2072642720826409809">"Zaklep zaslona"</string> - <string name="power_off" msgid="4111692782492232778">"Izklopi"</string> + <string name="power_off" msgid="4111692782492232778">"Izklop"</string> <string name="silent_mode_silent" msgid="5079789070221150912">"Izklopi zvonjenje"</string> <string name="silent_mode_vibrate" msgid="8821830448369552678">"Zvonjenje z vibriranjem"</string> <string name="silent_mode_ring" msgid="6039011004781526678">"Vklopi zvonjenje"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index c3e5a66fc4bf..e8dbf3ccd66d 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -90,12 +90,12 @@ <string name="notification_channel_network_alert" msgid="4788053066033851841">"అలర్ట్లు"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"కాల్ ఫార్వార్డింగ్"</string> <string name="notification_channel_emergency_callback" msgid="54074839059123159">"అత్యవసర కాల్బ్యాక్ మోడ్"</string> - <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"మొబైల్ డేటా స్థితి"</string> + <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"మొబైల్ డేటా స్టేటస్"</string> <string name="notification_channel_sms" msgid="1243384981025535724">"SMS మెసేజ్లు"</string> <string name="notification_channel_voice_mail" msgid="8457433203106654172">"వాయిస్ మెయిల్ మెసేజ్లు"</string> <string name="notification_channel_wfc" msgid="9048240466765169038">"Wi-Fi కాలింగ్"</string> <string name="notification_channel_sim" msgid="5098802350325677490">"SIM స్టేటస్"</string> - <string name="notification_channel_sim_high_prio" msgid="642361929452850928">"అధిక ప్రాధాన్యత గల SIM స్థితి"</string> + <string name="notification_channel_sim_high_prio" msgid="642361929452850928">"అధిక ప్రాధాన్యత గల SIM స్టేటస్"</string> <string name="peerTtyModeFull" msgid="337553730440832160">"అవతలి వారు FULL TTY మోడ్ని అభ్యర్థించారు"</string> <string name="peerTtyModeHco" msgid="5626377160840915617">"అవతలి వారు HCO TTY మోడ్ని అభ్యర్థించారు"</string> <string name="peerTtyModeVco" msgid="572208600818270944">"అవతలి వారు VCO TTY మోడ్ని అభ్యర్థించారు"</string> @@ -278,14 +278,14 @@ <string name="notification_channel_physical_keyboard" msgid="5417306456125988096">"భౌతిక కీబోర్డ్"</string> <string name="notification_channel_security" msgid="8516754650348238057">"సెక్యూరిటీ"</string> <string name="notification_channel_car_mode" msgid="2123919247040988436">"కార్ మోడ్"</string> - <string name="notification_channel_account" msgid="6436294521740148173">"ఖాతా స్థితి"</string> + <string name="notification_channel_account" msgid="6436294521740148173">"ఖాతా స్టేటస్"</string> <string name="notification_channel_developer" msgid="1691059964407549150">"డెవలపర్ మెసేజ్లు"</string> <string name="notification_channel_developer_important" msgid="7197281908918789589">"ముఖ్యమైన డెవలపర్ మెసేజ్లు"</string> <string name="notification_channel_updates" msgid="7907863984825495278">"అప్డేట్లు"</string> - <string name="notification_channel_network_status" msgid="2127687368725272809">"నెట్వర్క్ స్థితి"</string> + <string name="notification_channel_network_status" msgid="2127687368725272809">"నెట్వర్క్ స్టేటస్"</string> <string name="notification_channel_network_alerts" msgid="6312366315654526528">"నెట్వర్క్ హెచ్చరికలు"</string> <string name="notification_channel_network_available" msgid="6083697929214165169">"నెట్వర్క్ అందుబాటులో ఉంది"</string> - <string name="notification_channel_vpn" msgid="1628529026203808999">"VPN స్థితి"</string> + <string name="notification_channel_vpn" msgid="1628529026203808999">"VPN స్టేటస్"</string> <string name="notification_channel_device_admin" msgid="6384932669406095506">"మీ IT నిర్వాహకుల నుండి వచ్చే హెచ్చరికలు"</string> <string name="notification_channel_alerts" msgid="5070241039583668427">"అలర్ట్లు"</string> <string name="notification_channel_retail_mode" msgid="3732239154256431213">"రిటైల్ డెమో"</string> @@ -342,12 +342,12 @@ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"పరికర వేలిముద్ర సెన్సార్లో ఉపయోగించిన సంజ్ఞలను క్యాప్చర్ చేయవచ్చు."</string> <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"స్క్రీన్షాట్ను తీయండి"</string> <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"డిస్ప్లే యొక్క స్క్రీన్షాట్ తీసుకోవచ్చు."</string> - <string name="permlab_statusBar" msgid="8798267849526214017">"స్థితి బార్ను నిలిపివేయడం లేదా సవరించడం"</string> - <string name="permdesc_statusBar" msgid="5809162768651019642">"స్థితి బార్ను నిలిపివేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి యాప్ను అనుమతిస్తుంది."</string> - <string name="permlab_statusBarService" msgid="2523421018081437981">"స్థితి పట్టీగా ఉండటం"</string> - <string name="permdesc_statusBarService" msgid="6652917399085712557">"స్థితి బార్ ఉండేలా చేయడానికి యాప్ను అనుమతిస్తుంది."</string> - <string name="permlab_expandStatusBar" msgid="1184232794782141698">"స్థితి పట్టీని విస్తరింపజేయడం/కుదించడం"</string> - <string name="permdesc_expandStatusBar" msgid="7180756900448498536">"స్థితి బార్ను విస్తరింపజేయడానికి లేదా కుదించడానికి యాప్ను అనుమతిస్తుంది."</string> + <string name="permlab_statusBar" msgid="8798267849526214017">"స్టేటస్ బార్ను డిజేబుల్ చేయడం లేదా మార్చడం"</string> + <string name="permdesc_statusBar" msgid="5809162768651019642">"స్టేటస్ బార్ను డిజేబుల్ చేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి యాప్ను అనుమతిస్తుంది."</string> + <string name="permlab_statusBarService" msgid="2523421018081437981">"స్టేటస్ పట్టీగా ఉండటం"</string> + <string name="permdesc_statusBarService" msgid="6652917399085712557">"స్టేటస్ బార్ ఉండేలా చేయడానికి యాప్ను అనుమతిస్తుంది."</string> + <string name="permlab_expandStatusBar" msgid="1184232794782141698">"స్టేటస్ పట్టీని విస్తరింపజేయడం/కుదించడం"</string> + <string name="permdesc_expandStatusBar" msgid="7180756900448498536">"స్టేటస్ బార్ను విస్తరింపజేయడానికి లేదా కుదించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_fullScreenIntent" msgid="4310888199502509104">"లాక్ చేసి ఉన్న పరికరంలో నోటిఫికేషన్లను ఫుల్ స్క్రీన్ యాక్టివిటీలుగా డిస్ప్లే చేస్తుంది"</string> <string name="permdesc_fullScreenIntent" msgid="1100721419406643997">"లాక్ చేసి ఉన్న పరికరంలో నోటిఫికేషన్లను ఫుల్ స్క్రీన్ యాక్టివిటీలుగా డిస్ప్లే చేయడానికి యాప్ను అనుమతిస్తుంది"</string> <string name="permlab_install_shortcut" msgid="7451554307502256221">"షార్ట్కట్లను ఇన్స్టాల్ చేయడం"</string> @@ -469,7 +469,7 @@ <string name="permdesc_callPhone" msgid="5439809516131609109">"మీ ప్రమేయం లేకుండా ఫోన్ నంబర్లకు కాల్ చేయడానికి యాప్ను అనుమతిస్తుంది. దీని వలన అనుకోని ఛార్జీలు విధించబడవచ్చు లేదా కాల్స్ రావచ్చు. ఇది అత్యవసర నంబర్లకు కాల్ చేయడానికి యాప్ను అనుమతించదని గుర్తుంచుకోండి. హానికరమైన యాప్లు మీ నిర్ధారణ లేకుండానే కాల్స్ చేయడం ద్వారా మీకు డబ్బు ఖర్చయ్యేలా చేయవచ్చు."</string> <string name="permlab_accessImsCallService" msgid="442192920714863782">"IMS కాల్ సేవ యాక్సెస్ అనుమతి"</string> <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"మీ ప్రమేయం లేకుండా కాల్స్ చేయడం కోసం IMS సేవను ఉపయోగించడానికి యాప్ను అనుమతిస్తుంది."</string> - <string name="permlab_readPhoneState" msgid="8138526903259297969">"ఫోన్ స్థితి మరియు గుర్తింపుని చదవడం"</string> + <string name="permlab_readPhoneState" msgid="8138526903259297969">"ఫోన్ స్టేటస్ మరియు గుర్తింపుని చదవడం"</string> <string name="permdesc_readPhoneState" msgid="7229063553502788058">"పరికరం యొక్క ఫోన్ ఫీచర్లను యాక్సెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి ఫోన్ నంబర్ మరియు పరికరం IDలను, కాల్ సక్రియంగా ఉందా లేదా అనే విషయాన్ని మరియు కాల్ ద్వారా కనెక్ట్ చేయబడిన రిమోట్ నంబర్ను కనుగొనడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_manageOwnCalls" msgid="9033349060307561370">"కాల్స్ను సిస్టమ్ ద్వారా వెళ్లేలా చేయి"</string> <string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"కాలింగ్ అనుభవాన్ని మెరుగుపరచడం కోసం తన కాల్స్ను సిస్టమ్ ద్వారా వెళ్లేలా చేయడానికి యాప్ను అనుమతిస్తుంది."</string> @@ -716,7 +716,7 @@ <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"టచ్ స్క్రీన్ యొక్క క్రమాంకన పరామితులను సవరించడానికి యాప్ను అనుమతిస్తుంది. సాధారణ యాప్లకు ఎప్పటికీ అవసరం ఉండదు."</string> <string name="permlab_accessDrmCertificates" msgid="6473765454472436597">"DRM ప్రమాణపత్రాలను యాక్సెస్ చేయడం"</string> <string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"DRM ప్రమాణపత్రాలను కేటాయించడానికి మరియు ఉపయోగించడానికి యాప్ను అనుమతిస్తుంది. సాధారణ యాప్లకు ఎప్పటికీ అవసరం ఉండదు."</string> - <string name="permlab_handoverStatus" msgid="7620438488137057281">"Android Beam బదిలీ స్థితిని స్వీకరించడం"</string> + <string name="permlab_handoverStatus" msgid="7620438488137057281">"Android Beam బదిలీ స్టేటస్ని స్వీకరించడం"</string> <string name="permdesc_handoverStatus" msgid="3842269451732571070">"ప్రస్తుత Android Beam బదిలీలకు సంబంధించిన సమాచారాన్ని స్వీకరించడానికి ఈ యాప్ను అనుమతిస్తుంది"</string> <string name="permlab_removeDrmCertificates" msgid="710576248717404416">"DRM ప్రమాణపత్రాలను తీసివేయడం"</string> <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"DRM ప్రమాణపత్రాలను తీసివేయడానికి యాప్ను అనుమతిస్తుంది. సాధారణ యాప్లకు ఎప్పటికీ అవసరం ఉండదు."</string> @@ -959,7 +959,7 @@ <string name="keyguard_accessibility_unlock_area_collapsed" msgid="4729922043778400434">"అన్లాక్ ప్రాంతం కుదించబడింది."</string> <string name="keyguard_accessibility_widget" msgid="6776892679715699875">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> విడ్జెట్."</string> <string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"వినియోగదారు ఎంపికకర్త"</string> - <string name="keyguard_accessibility_status" msgid="6792745049712397237">"స్థితి"</string> + <string name="keyguard_accessibility_status" msgid="6792745049712397237">"స్టేటస్"</string> <string name="keyguard_accessibility_camera" msgid="7862557559464986528">"కెమెరా"</string> <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"మీడియా నియంత్రణలు"</string> <string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"విడ్జెట్ పునఃక్రమం ప్రారంభించబడింది."</string> @@ -1204,9 +1204,9 @@ <string name="whichOpenLinksWithApp" msgid="6917864367861910086">"<xliff:g id="APPLICATION">%1$s</xliff:g>తో లింక్లను తెరవండి"</string> <string name="whichOpenHostLinksWithApp" msgid="2401668560768463004">"<xliff:g id="HOST">%1$s</xliff:g> లింక్లను <xliff:g id="APPLICATION">%2$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="whichEditApplicationLabel" msgid="1463288652070140285">"సవరించు"</string> + <string name="whichEditApplication" msgid="6191568491456092812">"దీనితో ఎడిట్ చేయండి"</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> <string name="whichSendApplicationLabel" msgid="7467813004769188515">"షేర్ చేయి"</string> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 1380165d88a2..697ec204d745 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -5383,6 +5383,16 @@ <!-- Standard amount of hyphenation, useful for running text and for screens with limited space for text. --> <enum name="full" value="2" /> + + <!-- Same to hyphenationFrequency="normal" but using faster algorithm for measuring + hyphenation break points. To make text rendering faster with hyphenation, this algorithm + ignores some hyphen character related typographic features, e.g. kerning. --> + <enum name="normalFast" value="3" /> + + <!-- Same to hyphenationFrequency="full" but using faster algorithm for measuring + hyphenation break points. To make text rendering faster with hyphenation, this algorithm + ignores some hyphen character related typographic features, e.g. kerning. --> + <enum name="fullFast" value="4" /> </attr> <!-- Specify the type of auto-size. Note that this feature is not supported by EditText, works only for TextView. --> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 7805d46188e9..94717b11deb2 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1991,6 +1991,12 @@ <!-- Whether attributions provided are meant to be user-visible. --> <attr name="attributionsAreUserVisible" format="boolean" /> + + <!-- Specifies whether enabled settings of components in the application should be + reset to {@link android.content.pm.PackageManager#COMPONENT_ENABLED_STATE_DEFAULT} + when the application's user data is cleared. The default value is false. + --> + <attr name="resetEnabledSettingsOnAppDataCleared" format="boolean" /> </declare-styleable> <!-- An attribution is a logical part of an app and is identified by a tag. diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index a2dadb999924..dc548b9299b0 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3305,6 +3305,7 @@ <public name="splitTypes" /> <public name="canDisplayOnRemoteDevices" /> <public name="supportedTypes" /> + <public name="resetEnabledSettingsOnAppDataCleared" /> </staging-public-group> <staging-public-group type="id" first-id="0x01de0000"> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 192f5c0cf96f..f6a0e615e247 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -2027,6 +2027,10 @@ typed when unlocking the screen, and lock your Android TV device or erase all your Android TV device\'s data if too many incorrect passwords are typed.</string> <!-- Description of policy access to watch user login attempts --> + <string name="policydesc_watchLogin" product="automotive">Monitor the number of incorrect passwords + typed. when unlocking the screen, and lock the infotainment system or erase all the infotainment system\'s + data if too many incorrect passwords are typed.</string> + <!-- Description of policy access to watch user login attempts --> <string name="policydesc_watchLogin" product="default">Monitor the number of incorrect passwords typed. when unlocking the screen, and lock the phone or erase all the phone\'s data if too many incorrect passwords are typed.</string> @@ -2036,6 +2040,9 @@ <string name="policydesc_watchLogin_secondaryUser" product="tv">Monitor the number of incorrect passwords typed when unlocking the screen, and lock your Android TV device or erase all this user\'s data if too many incorrect passwords are typed.</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive">Monitor the number of incorrect passwords + typed when unlocking the screen, and lock the infotainment system or erase all this profile\'s data + if too many incorrect passwords are typed.</string> <string name="policydesc_watchLogin_secondaryUser" product="default">Monitor the number of incorrect passwords typed when unlocking the screen, and lock the phone or erase all this user\'s data if too many incorrect passwords are typed.</string> @@ -2054,14 +2061,20 @@ <!-- Description of policy access to wipe the user's data --> <string name="policydesc_wipeData" product="tv">Erase your Android TV device\'s data without warning by performing a factory data reset.</string> <!-- Description of policy access to wipe the user's data --> + <string name="policydesc_wipeData" product="automotive">Erase the infotainment system\'s data without warning by performing a factory data reset.</string> + <!-- Description of policy access to wipe the user's data --> <string name="policydesc_wipeData" product="default">Erase the phone\'s data without warning by performing a factory data reset.</string> <!-- Title of policy access to wipe secondary user's data --> - <string name="policylab_wipeData_secondaryUser">Erase user data</string> + <string name="policylab_wipeData_secondaryUser" product="automotive">Erase profile data</string> + <!-- Title of policy access to wipe secondary user's data --> + <string name="policylab_wipeData_secondaryUser" product="default">Erase user data</string> <!-- Description of policy access to wipe the user's data --> <string name="policydesc_wipeData_secondaryUser" product="tablet">Erase this user\'s data on this tablet without warning.</string> <!-- Description of policy access to wipe the user's data --> <string name="policydesc_wipeData_secondaryUser" product="tv">Erase this user\'s data on this Android TV device without warning.</string> <!-- Description of policy access to wipe the user's data --> + <string name="policydesc_wipeData_secondaryUser" product="automotive">Erase this profile\'s data on this infotainment system without warning.</string> + <!-- Description of policy access to wipe the user's data --> <string name="policydesc_wipeData_secondaryUser" product="default">Erase this user\'s data on this phone without warning.</string> <!-- Title of policy access to set global proxy --> <string name="policylab_setGlobalProxy">Set the device global proxy</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 0144b5ad90bf..faa99027d9ad 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1701,6 +1701,10 @@ <java-symbol type="anim" name="activity_translucent_close_exit" /> <java-symbol type="anim" name="activity_open_enter" /> <java-symbol type="anim" name="activity_close_exit" /> + <java-symbol type="anim" name="task_fragment_close_enter" /> + <java-symbol type="anim" name="task_fragment_close_exit" /> + <java-symbol type="anim" name="task_fragment_open_enter" /> + <java-symbol type="anim" name="task_fragment_open_exit" /> <java-symbol type="array" name="config_autoRotationTiltTolerance" /> <java-symbol type="array" name="config_longPressVibePattern" /> diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java index 34c1763b3286..37cf514e92ea 100644 --- a/core/tests/coretests/src/android/app/NotificationTest.java +++ b/core/tests/coretests/src/android/app/NotificationTest.java @@ -43,6 +43,7 @@ import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.drawable.Icon; import android.os.Build; +import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.text.Spannable; @@ -545,6 +546,29 @@ public class NotificationTest { validateColorizedPaletteForColor(Color.BLACK); } + @Test + public void testIsMediaNotification_nullSession_returnsFalse() { + // Null media session + Notification.MediaStyle mediaStyle = new Notification.MediaStyle(); + Notification notification = new Notification.Builder(mContext, "test id") + .setStyle(mediaStyle) + .build(); + assertFalse(notification.isMediaNotification()); + } + + @Test + public void testIsMediaNotification_invalidSession_returnsFalse() { + // Extra was set manually to an invalid type + Bundle extras = new Bundle(); + extras.putParcelable(Notification.EXTRA_MEDIA_SESSION, new Intent()); + Notification.MediaStyle mediaStyle = new Notification.MediaStyle(); + Notification notification = new Notification.Builder(mContext, "test id") + .setStyle(mediaStyle) + .addExtras(extras) + .build(); + assertFalse(notification.isMediaNotification()); + } + public void validateColorizedPaletteForColor(int rawColor) { Notification.Colors cDay = new Notification.Colors(); Notification.Colors cNight = new Notification.Colors(); diff --git a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java index 57bb4349c4fd..d6a7682475f2 100644 --- a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java +++ b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertNull; import android.content.Context; import android.graphics.Typeface; +import android.graphics.text.MeasuredText; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -135,7 +136,8 @@ public class MeasuredParagraphTest { MeasuredParagraph mt = null; mt = MeasuredParagraph.buildForStaticLayout( - PAINT, "XXX", 0, 3, LTR, false, false, null /* no hint */, null); + PAINT, "XXX", 0, 3, LTR, MeasuredText.Builder.HYPHENATION_MODE_NONE, false, + null /* no hint */, null); assertNotNull(mt); assertNotNull(mt.getChars()); assertEquals("XXX", charsToString(mt.getChars())); @@ -150,7 +152,8 @@ public class MeasuredParagraphTest { // Recycle it MeasuredParagraph mt2 = MeasuredParagraph.buildForStaticLayout( - PAINT, "_VVV_", 1, 4, RTL, false, false, null /* no hint */, mt); + PAINT, "_VVV_", 1, 4, RTL, MeasuredText.Builder.HYPHENATION_MODE_NONE, false, + null /* no hint */, mt); assertEquals(mt2, mt); assertNotNull(mt2.getChars()); assertEquals("VVV", charsToString(mt.getChars())); diff --git a/data/etc/com.android.intentresolver.xml b/data/etc/com.android.intentresolver.xml index 0f1c4673562e..f4e94ad0e04b 100644 --- a/data/etc/com.android.intentresolver.xml +++ b/data/etc/com.android.intentresolver.xml @@ -18,5 +18,6 @@ <privapp-permissions package="com.android.intentresolver"> <permission name="android.permission.INTERACT_ACROSS_USERS"/> <permission name="android.permission.MANAGE_USERS"/> + <permission name="android.permission.PACKAGE_USAGE_STATS"/> </privapp-permissions> </permissions> diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 8b3780590d44..8ccf02caf8c0 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -961,6 +961,12 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, + "-1101551167": { + "message": "Auto-PIP allowed, entering PIP mode directly: %s, didAutoPip: %b", + "level": "DEBUG", + "group": "WM_DEBUG_STATES", + "at": "com\/android\/server\/wm\/TaskFragment.java" + }, "-1089874824": { "message": "SURFACE SHOW (performLayout): %s", "level": "INFO", @@ -2629,12 +2635,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "660908897": { - "message": "Auto-PIP allowed, entering PIP mode directly: %s", - "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskFragment.java" - }, "662572728": { "message": "Attempted to add a toast window with bad token %s. Aborting.", "level": "WARN", diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java index 31c3d09ed5b1..df5b3f582d8c 100644 --- a/graphics/java/android/graphics/text/MeasuredText.java +++ b/graphics/java/android/graphics/text/MeasuredText.java @@ -17,12 +17,14 @@ package android.graphics.text; import android.annotation.FloatRange; +import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Px; import android.graphics.Paint; import android.graphics.Rect; +import android.util.Log; import com.android.internal.util.Preconditions; @@ -30,6 +32,9 @@ import dalvik.annotation.optimization.CriticalNative; import libcore.util.NativeAllocationRegistry; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Result of text shaping of the single paragraph string. * @@ -49,6 +54,8 @@ import libcore.util.NativeAllocationRegistry; * </p> */ public class MeasuredText { + private static final String TAG = "MeasuredText"; + private long mNativePtr; private boolean mComputeHyphenation; private boolean mComputeLayout; @@ -179,6 +186,7 @@ public class MeasuredText { private final @NonNull char[] mText; private boolean mComputeHyphenation = false; private boolean mComputeLayout = true; + private boolean mFastHyphenation = false; private int mCurrentOffset = 0; private @Nullable MeasuredText mHintMt = null; @@ -275,10 +283,78 @@ public class MeasuredText { * Even if you pass false to this method, you can still enable automatic hyphenation of * LineBreaker but line break computation becomes slower. * + * @deprecated use setComputeHyphenation(int) instead. + * * @param computeHyphenation true if you want to use automatic hyphenations. */ public @NonNull Builder setComputeHyphenation(boolean computeHyphenation) { - mComputeHyphenation = computeHyphenation; + setComputeHyphenation( + computeHyphenation ? HYPHENATION_MODE_NORMAL : HYPHENATION_MODE_NONE); + return this; + } + + /** @hide */ + @IntDef(prefix = { "HYPHENATION_MODE_" }, value = { + HYPHENATION_MODE_NONE, + HYPHENATION_MODE_NORMAL, + HYPHENATION_MODE_FAST + }) + @Retention(RetentionPolicy.SOURCE) + public @interface HyphenationMode {} + + /** + * A value for hyphenation calculation mode. + * + * This value indicates that no hyphenation points are calculated. + */ + public static final int HYPHENATION_MODE_NONE = 0; + + /** + * A value for hyphenation calculation mode. + * + * This value indicates that hyphenation points are calculated. + */ + public static final int HYPHENATION_MODE_NORMAL = 1; + + /** + * A value for hyphenation calculation mode. + * + * This value indicates that hyphenation points are calculated with faster algorithm. This + * algorithm measures text width with ignoring the context of hyphen character shaping, e.g. + * kerning. + */ + public static final int HYPHENATION_MODE_FAST = 2; + + /** + * By passing true to this method, the build method will calculate hyphenation break + * points faster with ignoring some typographic features, e.g. kerning. + * + * {@link #HYPHENATION_MODE_NONE} is by default. + * + * @see #setComputeHyphenation(boolean) + * + * @param mode a hyphenation mode. + */ + public @NonNull Builder setComputeHyphenation(@HyphenationMode int mode) { + switch (mode) { + case HYPHENATION_MODE_NONE: + mComputeHyphenation = false; + mFastHyphenation = false; + break; + case HYPHENATION_MODE_NORMAL: + mComputeHyphenation = true; + mFastHyphenation = false; + break; + case HYPHENATION_MODE_FAST: + mComputeHyphenation = true; + mFastHyphenation = true; + break; + default: + Log.e(TAG, "Unknown hyphenation mode: " + mode); + mComputeHyphenation = false; + mFastHyphenation = false; + break; + } return this; } @@ -319,7 +395,7 @@ public class MeasuredText { try { long hintPtr = (mHintMt == null) ? 0 : mHintMt.getNativePtr(); long ptr = nBuildMeasuredText(mNativePtr, hintPtr, mText, mComputeHyphenation, - mComputeLayout); + mComputeLayout, mFastHyphenation); final MeasuredText res = new MeasuredText(ptr, mText, mComputeHyphenation, mComputeLayout); sRegistry.registerNativeAllocation(res, ptr); @@ -378,7 +454,8 @@ public class MeasuredText { long hintMtPtr, @NonNull char[] text, boolean computeHyphenation, - boolean computeLayout); + boolean computeLayout, + boolean fastHyphenationMode); private static native void nFreeBuilder(/* Non Zero */ long nativeBuilderPtr); } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java index 535dac1a5101..3c7d2de6165f 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java @@ -16,9 +16,13 @@ package androidx.window.extensions.embedding; +import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE; +import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN; +import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN; +import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN; import android.util.Log; import android.view.RemoteAnimationAdapter; @@ -45,8 +49,12 @@ class TaskFragmentAnimationController { final RemoteAnimationDefinition definition = new RemoteAnimationDefinition(); final RemoteAnimationAdapter animationAdapter = new RemoteAnimationAdapter(mRemoteRunner, 0, 0, true /* changeNeedsSnapshot */); + definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, animationAdapter); definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, animationAdapter); + definition.addRemoteAnimation(TRANSIT_OLD_TASK_OPEN, animationAdapter); + definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_CLOSE, animationAdapter); definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, animationAdapter); + definition.addRemoteAnimation(TRANSIT_OLD_TASK_CLOSE, animationAdapter); definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, animationAdapter); mOrganizer.registerRemoteAnimations(definition); } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java index 412559e34070..8c8ef92b80dc 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java @@ -17,9 +17,13 @@ package androidx.window.extensions.embedding; import static android.view.RemoteAnimationTarget.MODE_CLOSING; +import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE; +import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN; +import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN; +import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN; import android.animation.Animator; import android.animation.ValueAnimator; @@ -155,9 +159,13 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub { @WindowManager.TransitionOldType int transit, @NonNull RemoteAnimationTarget[] targets) { switch (transit) { + case TRANSIT_OLD_ACTIVITY_OPEN: case TRANSIT_OLD_TASK_FRAGMENT_OPEN: + case TRANSIT_OLD_TASK_OPEN: return createOpenAnimationAdapters(targets); + case TRANSIT_OLD_ACTIVITY_CLOSE: case TRANSIT_OLD_TASK_FRAGMENT_CLOSE: + case TRANSIT_OLD_TASK_CLOSE: return createCloseAnimationAdapters(targets); case TRANSIT_OLD_TASK_FRAGMENT_CHANGE: return createChangeAnimationAdapters(targets); diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java index c0908a548501..586ac1f212a1 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java @@ -43,6 +43,7 @@ import com.android.internal.policy.AttributeCache; import com.android.internal.policy.TransitionAnimation; /** Animation spec for TaskFragment transition. */ +// TODO(b/206557124): provide an easier way to customize animation class TaskFragmentAnimationSpec { private static final String TAG = "TaskFragAnimationSpec"; @@ -179,9 +180,9 @@ class TaskFragmentAnimationSpec { Animation loadOpenAnimation(@NonNull RemoteAnimationTarget target, @NonNull Rect wholeAnimationBounds) { final boolean isEnter = target.mode != MODE_CLOSING; - final Animation animation = mTransitionAnimation.loadDefaultAnimationAttr(isEnter - ? R.styleable.WindowAnimation_activityOpenEnterAnimation - : R.styleable.WindowAnimation_activityOpenExitAnimation); + final Animation animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter + ? com.android.internal.R.anim.task_fragment_open_enter + : com.android.internal.R.anim.task_fragment_open_exit); animation.initialize(target.localBounds.width(), target.localBounds.height(), wholeAnimationBounds.width(), wholeAnimationBounds.height()); animation.scaleCurrentDuration(mTransitionAnimationScaleSetting); @@ -191,9 +192,9 @@ class TaskFragmentAnimationSpec { Animation loadCloseAnimation(@NonNull RemoteAnimationTarget target, @NonNull Rect wholeAnimationBounds) { final boolean isEnter = target.mode != MODE_CLOSING; - final Animation animation = mTransitionAnimation.loadDefaultAnimationAttr(isEnter - ? R.styleable.WindowAnimation_activityCloseEnterAnimation - : R.styleable.WindowAnimation_activityCloseExitAnimation); + final Animation animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter + ? com.android.internal.R.anim.task_fragment_close_enter + : com.android.internal.R.anim.task_fragment_close_exit); animation.initialize(target.localBounds.width(), target.localBounds.height(), wholeAnimationBounds.width(), wholeAnimationBounds.height()); animation.scaleCurrentDuration(mTransitionAnimationScaleSetting); diff --git a/libs/WindowManager/Shell/res/color/size_compat_background_ripple.xml b/libs/WindowManager/Shell/res/color/size_compat_background_ripple.xml new file mode 100644 index 000000000000..329e5b9b31a0 --- /dev/null +++ b/libs/WindowManager/Shell/res/color/size_compat_background_ripple.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:color="@android:color/system_neutral1_500" android:lStar="35" /> +</selector>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/drawable/size_compat_hint_bubble.xml b/libs/WindowManager/Shell/res/drawable/size_compat_hint_bubble.xml index 94165a11eccb..22cd384e1be0 100644 --- a/libs/WindowManager/Shell/res/drawable/size_compat_hint_bubble.xml +++ b/libs/WindowManager/Shell/res/drawable/size_compat_hint_bubble.xml @@ -16,6 +16,6 @@ --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> - <solid android:color="@color/size_compat_hint_bubble"/> + <solid android:color="@color/size_compat_background"/> <corners android:radius="@dimen/size_compat_hint_corner_radius"/> </shape>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/drawable/size_compat_hint_point.xml b/libs/WindowManager/Shell/res/drawable/size_compat_hint_point.xml index a8f0f76ef27f..af9063a94afb 100644 --- a/libs/WindowManager/Shell/res/drawable/size_compat_hint_point.xml +++ b/libs/WindowManager/Shell/res/drawable/size_compat_hint_point.xml @@ -20,6 +20,6 @@ android:viewportWidth="10" android:viewportHeight="8"> <path - android:fillColor="@color/size_compat_hint_bubble" + android:fillColor="@color/size_compat_background" android:pathData="M10,0 l-4.1875,6.6875 a1,1 0 0,1 -1.625,0 l-4.1875,-6.6875z"/> </vector> diff --git a/libs/WindowManager/Shell/res/drawable/size_compat_restart_button.xml b/libs/WindowManager/Shell/res/drawable/size_compat_restart_button.xml index 3e486df71f91..18caa3582537 100644 --- a/libs/WindowManager/Shell/res/drawable/size_compat_restart_button.xml +++ b/libs/WindowManager/Shell/res/drawable/size_compat_restart_button.xml @@ -20,16 +20,16 @@ android:viewportWidth="48" android:viewportHeight="48"> <path - android:fillColor="#53534D" + android:fillColor="@color/size_compat_background" android:pathData="M0,24 a24,24 0 1,0 48,0 a24,24 0 1,0 -48,0" /> <group android:translateX="12" android:translateY="12"> <path - android:fillColor="#E4E3DA" + android:fillColor="@color/size_compat_text" android:pathData="M6,13c0,-1.65 0.67,-3.15 1.76,-4.24L6.34,7.34C4.9,8.79 4,10.79 4,13c0,4.08 3.05,7.44 7,7.93v-2.02C8.17,18.43 6,15.97 6,13z"/> <path - android:fillColor="#E4E3DA" + android:fillColor="@color/size_compat_text" android:pathData="M20,13c0,-4.42 -3.58,-8 -8,-8c-0.06,0 -0.12,0.01 -0.18,0.01v0l1.09,-1.09L11.5,2.5L8,6l3.5,3.5l1.41,-1.41l-1.08,-1.08C11.89,7.01 11.95,7 12,7c3.31,0 6,2.69 6,6c0,2.97 -2.17,5.43 -5,5.91v2.02C16.95,20.44 20,17.08 20,13z"/> </group> </vector> diff --git a/libs/WindowManager/Shell/res/drawable/size_compat_restart_button_ripple.xml b/libs/WindowManager/Shell/res/drawable/size_compat_restart_button_ripple.xml new file mode 100644 index 000000000000..95decff24ac4 --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/size_compat_restart_button_ripple.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="@color/size_compat_background_ripple"> + <item android:drawable="@drawable/size_compat_restart_button"/> +</ripple>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml b/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml index 17347f627049..d0e7c42dbf8b 100644 --- a/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml +++ b/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml @@ -40,7 +40,7 @@ android:padding="16dp" android:text="@string/restart_button_description" android:textAlignment="viewStart" - android:textColor="#E4E3DA" + android:textColor="@color/size_compat_text" android:textSize="14sp"/> <ImageView diff --git a/libs/WindowManager/Shell/res/layout/size_compat_ui.xml b/libs/WindowManager/Shell/res/layout/size_compat_ui.xml index 47e76f061877..82ebee263a64 100644 --- a/libs/WindowManager/Shell/res/layout/size_compat_ui.xml +++ b/libs/WindowManager/Shell/res/layout/size_compat_ui.xml @@ -30,7 +30,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - android:src="@drawable/size_compat_restart_button" + android:src="@drawable/size_compat_restart_button_ripple" android:background="@android:color/transparent" android:contentDescription="@string/restart_button_description"/> diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml index 34b2667689b8..107da8149e5b 100644 --- a/libs/WindowManager/Shell/res/values-af/strings.xml +++ b/libs/WindowManager/Shell/res/values-af/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Maak toe"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Vou uit"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Instellings"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Gaan by verdeelde skerm in"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Kieslys"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in beeld-in-beeld"</string> <string name="pip_notification_message" msgid="8854051911700302620">"As jy nie wil hê dat <xliff:g id="NAME">%s</xliff:g> hierdie kenmerk moet gebruik nie, tik om instellings oop te maak en skakel dit af."</string> diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml index 73c3cc85be3d..d724372c3da3 100644 --- a/libs/WindowManager/Shell/res/values-am/strings.xml +++ b/libs/WindowManager/Shell/res/values-am/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"ዝጋ"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"ዘርጋ"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"ቅንብሮች"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"የተከፈለ ማያ ገጽን አስገባ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"ምናሌ"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> በስዕል-ላይ-ስዕል ውስጥ ነው"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ይህን ባህሪ እንዲጠቀም ካልፈለጉ ቅንብሮችን ለመክፈት መታ ያድርጉና ያጥፉት።"</string> diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml index 25bad80cd4d5..7dd1f8151a72 100644 --- a/libs/WindowManager/Shell/res/values-ar/strings.xml +++ b/libs/WindowManager/Shell/res/values-ar/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"إغلاق"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"توسيع"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"الإعدادات"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"الدخول في وضع تقسيم الشاشة"</string> <string name="pip_menu_title" msgid="5393619322111827096">"القائمة"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> يظهر في صورة داخل صورة"</string> <string name="pip_notification_message" msgid="8854051911700302620">"إذا كنت لا تريد أن يستخدم <xliff:g id="NAME">%s</xliff:g> هذه الميزة، فانقر لفتح الإعدادات، ثم أوقِف تفعيل هذه الميزة."</string> diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml index 69113da0d22e..190f7ca9b96c 100644 --- a/libs/WindowManager/Shell/res/values-as/strings.xml +++ b/libs/WindowManager/Shell/res/values-as/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"বন্ধ কৰক"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"বিস্তাৰ কৰক"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"ছেটিং"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"বিভাজিত স্ক্ৰীন ম’ডলৈ যাওক"</string> <string name="pip_menu_title" msgid="5393619322111827096">"মেনু"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> চিত্ৰৰ ভিতৰৰ চিত্ৰত আছে"</string> <string name="pip_notification_message" msgid="8854051911700302620">"আপুনি যদি <xliff:g id="NAME">%s</xliff:g> সুবিধাটো ব্যৱহাৰ কৰিব নোখোজে, তেন্তে ছেটিং খুলিবলৈ টিপক আৰু তালৈ গৈ ইয়াক অফ কৰক।"</string> diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml index 2551063a5628..e33a35f975ad 100644 --- a/libs/WindowManager/Shell/res/values-az/strings.xml +++ b/libs/WindowManager/Shell/res/values-az/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Bağlayın"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Genişləndirin"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Ayarlar"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Bölünmüş ekrana daxil olun"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menyu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> şəkil içində şəkildədir"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> tətbiqinin bu funksiyadan istifadə etməyini istəmirsinizsə, ayarları açmaq və deaktiv etmək üçün klikləyin."</string> diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml index 9c18e735e234..f59e9320c645 100644 --- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml +++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Zatvori"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Proširi"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Podešavanja"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Uđi na podeljeni ekran"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meni"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> je slika u slici"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da biste otvorili podešavanja i isključili je."</string> diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml index 66d2a8c12a7c..3b478f2ab6cb 100644 --- a/libs/WindowManager/Shell/res/values-be/strings.xml +++ b/libs/WindowManager/Shell/res/values-be/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Закрыць"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Разгарнуць"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Налады"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Падзяліць экран"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> з’яўляецца відарысам у відарысе"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Калі вы не хочаце, каб праграма <xliff:g id="NAME">%s</xliff:g> выкарыстоўвала гэту функцыю, дакраніцеся, каб адкрыць налады і адключыць яе."</string> diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml index 6df231c1cd4c..3a77a1c7be28 100644 --- a/libs/WindowManager/Shell/res/values-bg/strings.xml +++ b/libs/WindowManager/Shell/res/values-bg/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Затваряне"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Разгъване"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Настройки"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Преминаване към разделен екран"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> е в режима „Картина в картината“"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ако не искате <xliff:g id="NAME">%s</xliff:g> да използва тази функция, докоснете, за да отворите настройките, и я изключете."</string> diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml index ce87f21e3059..8bfd775704dd 100644 --- a/libs/WindowManager/Shell/res/values-bn/strings.xml +++ b/libs/WindowManager/Shell/res/values-bn/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"বন্ধ করুন"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"বড় করুন"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"সেটিংস"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"\'স্প্লিট স্ক্রিন\' মোড চালু করুন"</string> <string name="pip_menu_title" msgid="5393619322111827096">"মেনু"</string> <string name="pip_notification_title" msgid="1347104727641353453">"ছবির-মধ্যে-ছবি তে <xliff:g id="NAME">%s</xliff:g> আছেন"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> কে এই বৈশিষ্ট্যটি ব্যবহার করতে দিতে না চাইলে ট্যাপ করে সেটিংসে গিয়ে সেটি বন্ধ করে দিন।"</string> diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml index 5b454c5d2767..d23cc61b52f1 100644 --- a/libs/WindowManager/Shell/res/values-bs/strings.xml +++ b/libs/WindowManager/Shell/res/values-bs/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Zatvori"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Proširi"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Postavke"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Otvori podijeljeni ekran"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meni"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> je u načinu priakza Slika u slici"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da otvorite postavke i isključite je."</string> diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml index 0b3d8bc0b97a..6434e315503d 100644 --- a/libs/WindowManager/Shell/res/values-ca/strings.xml +++ b/libs/WindowManager/Shell/res/values-ca/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Tanca"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Desplega"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Configuració"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Entra al mode de pantalla dividida"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menú"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> està en pantalla en pantalla"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Si no vols que <xliff:g id="NAME">%s</xliff:g> utilitzi aquesta funció, toca per obrir la configuració i desactiva-la."</string> diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml index d474b7b7d041..3530a7c8b835 100644 --- a/libs/WindowManager/Shell/res/values-cs/strings.xml +++ b/libs/WindowManager/Shell/res/values-cs/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Zavřít"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Rozbalit"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Nastavení"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Aktivovat rozdělenou obrazovku"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Nabídka"</string> <string name="pip_notification_title" msgid="1347104727641353453">"Aplikace <xliff:g id="NAME">%s</xliff:g> je v režimu obraz v obraze"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Pokud nechcete, aby aplikace <xliff:g id="NAME">%s</xliff:g> tuto funkci používala, klepnutím otevřete nastavení a funkci vypněte."</string> diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml index 80043b5d0fa2..89b66e5309e9 100644 --- a/libs/WindowManager/Shell/res/values-da/strings.xml +++ b/libs/WindowManager/Shell/res/values-da/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Luk"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Udvid"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Indstillinger"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Åbn opdelt skærm"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> vises som integreret billede"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Hvis du ikke ønsker, at <xliff:g id="NAME">%s</xliff:g> skal benytte denne funktion, kan du åbne indstillingerne og deaktivere den."</string> diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index a5dd1893af7f..b49b4462e476 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Schließen"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Maximieren"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Einstellungen"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"„Bildschirm teilen“ aktivieren"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menü"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ist in Bild im Bild"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Wenn du nicht möchtest, dass <xliff:g id="NAME">%s</xliff:g> diese Funktion verwendet, tippe, um die Einstellungen zu öffnen und die Funktion zu deaktivieren."</string> diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml index 76cdb28e4907..ed1d9133eb92 100644 --- a/libs/WindowManager/Shell/res/values-el/strings.xml +++ b/libs/WindowManager/Shell/res/values-el/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Κλείσιμο"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Ανάπτυξη"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Ρυθμίσεις"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Μετάβαση σε διαχωρισμό οθόνης"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Μενού"</string> <string name="pip_notification_title" msgid="1347104727641353453">"Η λειτουργία picture-in-picture είναι ενεργή σε <xliff:g id="NAME">%s</xliff:g>."</string> <string name="pip_notification_message" msgid="8854051911700302620">"Εάν δεν θέλετε να χρησιμοποιείται αυτή η λειτουργία από την εφαρμογή <xliff:g id="NAME">%s</xliff:g>, πατήστε για να ανοίξετε τις ρυθμίσεις και απενεργοποιήστε την."</string> diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml index 8973c2ce73a9..067e998ff396 100644 --- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Close"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Expand"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml index 8973c2ce73a9..067e998ff396 100644 --- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Close"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Expand"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml index 8973c2ce73a9..067e998ff396 100644 --- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Close"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Expand"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml index 8973c2ce73a9..067e998ff396 100644 --- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Close"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Expand"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml index 68e060047bc3..95c0d0175413 100644 --- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Close"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Expand"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml index ca5312eb6536..6e5347d1102c 100644 --- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml +++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Cerrar"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Expandir"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Configuración"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Introducir pantalla dividida"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menú"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está en modo de Pantalla en pantalla"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Si no quieres que <xliff:g id="NAME">%s</xliff:g> use esta función, presiona para abrir la configuración y desactivarla."</string> diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml index 8ea06c642084..4820a0f1d75b 100644 --- a/libs/WindowManager/Shell/res/values-es/strings.xml +++ b/libs/WindowManager/Shell/res/values-es/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Cerrar"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Mostrar"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Ajustes"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Introducir pantalla dividida"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menú"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está en imagen en imagen"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Si no quieres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca la notificación para abrir los ajustes y desactivarla."</string> diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml index 4e7013af0680..4c946948fd26 100644 --- a/libs/WindowManager/Shell/res/values-et/strings.xml +++ b/libs/WindowManager/Shell/res/values-et/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Sule"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Laiendamine"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Seaded"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Ava jagatud ekraanikuva"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menüü"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> on režiimis Pilt pildis"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Kui te ei soovi, et rakendus <xliff:g id="NAME">%s</xliff:g> seda funktsiooni kasutaks, puudutage seadete avamiseks ja lülitage see välja."</string> diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml index 810d113fcf79..afc4292b7548 100644 --- a/libs/WindowManager/Shell/res/values-eu/strings.xml +++ b/libs/WindowManager/Shell/res/values-eu/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Itxi"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Zabaldu"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Ezarpenak"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Sartu pantaila zatituan"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menua"</string> <string name="pip_notification_title" msgid="1347104727641353453">"Pantaila txiki gainjarrian dago <xliff:g id="NAME">%s</xliff:g>"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ez baduzu nahi <xliff:g id="NAME">%s</xliff:g> zerbitzuak eginbide hori erabiltzea, sakatu hau ezarpenak ireki eta aukera desaktibatzeko."</string> diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml index cd9aaf1e4d6d..e8a0682b3418 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"بستن"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"بزرگ کردن"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"تنظیمات"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"ورود به حالت «صفحهٔ دونیمه»"</string> <string name="pip_menu_title" msgid="5393619322111827096">"منو"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> درحالت تصویر در تصویر است"</string> <string name="pip_notification_message" msgid="8854051911700302620">"اگر نمیخواهید <xliff:g id="NAME">%s</xliff:g> از این قابلیت استفاده کند، با ضربه زدن، تنظیمات را باز کنید و آن را خاموش کنید."</string> diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml index 1ce0c86715a7..f6711055e4d9 100644 --- a/libs/WindowManager/Shell/res/values-fi/strings.xml +++ b/libs/WindowManager/Shell/res/values-fi/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Sulje"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Laajenna"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Asetukset"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Avaa jaettu näyttö"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Valikko"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> on kuva kuvassa ‑tilassa"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Jos et halua, että <xliff:g id="NAME">%s</xliff:g> voi käyttää tätä ominaisuutta, avaa asetukset napauttamalla ja poista se käytöstä."</string> diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml index 7565b7aa61ed..0d0b71868170 100644 --- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Fermer"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Développer"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Paramètres"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Entrer dans l\'écran partagé"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> est en mode d\'incrustation d\'image"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Si vous ne voulez pas que <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalité, touchez l\'écran pour ouvrir les paramètres, puis désactivez-la."</string> diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml index c69f2a15555c..5652d7ee5398 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Fermer"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Développer"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Paramètres"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Accéder à l\'écran partagé"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> est en mode Picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Si vous ne voulez pas que l\'application <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalité, appuyez ici pour ouvrir les paramètres et la désactiver."</string> diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml index 03573002f1bf..81bd9167d0e6 100644 --- a/libs/WindowManager/Shell/res/values-gl/strings.xml +++ b/libs/WindowManager/Shell/res/values-gl/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Pechar"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Despregar"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Configuración"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Inserir pantalla dividida"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menú"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está na pantalla superposta"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Se non queres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca a configuración para abrir as opcións e desactivar a función."</string> diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml index a55a52b8b75d..3d408cf2f698 100644 --- a/libs/WindowManager/Shell/res/values-gu/strings.xml +++ b/libs/WindowManager/Shell/res/values-gu/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"બંધ કરો"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"વિસ્તૃત કરો"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"સેટિંગ"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"વિભાજિત સ્ક્રીન મોડમાં દાખલ થાઓ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"મેનૂ"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ચિત્રમાં-ચિત્રની અંદર છે"</string> <string name="pip_notification_message" msgid="8854051911700302620">"જો તમે નથી ઇચ્છતા કે <xliff:g id="NAME">%s</xliff:g> આ સુવિધાનો ઉપયોગ કરે, તો સેટિંગ ખોલવા માટે ટૅપ કરો અને તેને બંધ કરો."</string> diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml index 1352695896ec..8c93e0a68da3 100644 --- a/libs/WindowManager/Shell/res/values-hi/strings.xml +++ b/libs/WindowManager/Shell/res/values-hi/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"बंद करें"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"विस्तार करें"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"सेटिंग"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"स्प्लिट स्क्रीन मोड में जाएं"</string> <string name="pip_menu_title" msgid="5393619322111827096">"मेन्यू"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> \"पिक्चर में पिक्चर\" के अंदर है"</string> <string name="pip_notification_message" msgid="8854051911700302620">"अगर आप नहीं चाहते कि <xliff:g id="NAME">%s</xliff:g> इस सुविधा का उपयोग करे, तो सेटिंग खोलने के लिए टैप करें और उसे बंद करें ."</string> diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml index 1660dc22e38d..1f8f982fca69 100644 --- a/libs/WindowManager/Shell/res/values-hr/strings.xml +++ b/libs/WindowManager/Shell/res/values-hr/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Zatvori"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Proširivanje"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Postavke"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Otvorite podijeljeni zaslon"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Izbornik"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> jest na slici u slici"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ako ne želite da aplikacija <xliff:g id="NAME">%s</xliff:g> upotrebljava tu značajku, dodirnite da biste otvorili postavke i isključili je."</string> diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml index a0eeceb7fa62..ebd02e59a101 100644 --- a/libs/WindowManager/Shell/res/values-hu/strings.xml +++ b/libs/WindowManager/Shell/res/values-hu/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Bezárás"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Kibontás"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Beállítások"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Váltás osztott képernyőre"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menü"</string> <string name="pip_notification_title" msgid="1347104727641353453">"A(z) <xliff:g id="NAME">%s</xliff:g> kép a képben funkciót használ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ha nem szeretné, hogy a(z) <xliff:g id="NAME">%s</xliff:g> használja ezt a funkciót, koppintson a beállítások megnyitásához, és kapcsolja ki."</string> diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml index 3dce9f784a1b..29b20521829e 100644 --- a/libs/WindowManager/Shell/res/values-hy/strings.xml +++ b/libs/WindowManager/Shell/res/values-hy/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Փակել"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Ընդարձակել"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Կարգավորումներ"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Մտնել տրոհված էկրանի ռեժիմ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Ընտրացանկ"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>-ը «Նկար նկարի մեջ» ռեժիմում է"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Եթե չեք ցանկանում, որ <xliff:g id="NAME">%s</xliff:g>-ն օգտագործի այս գործառույթը, հպեք՝ կարգավորումները բացելու և այն անջատելու համար։"</string> diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml index b1924c45150b..e48885573282 100644 --- a/libs/WindowManager/Shell/res/values-in/strings.xml +++ b/libs/WindowManager/Shell/res/values-in/strings.xml @@ -20,6 +20,8 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Tutup"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Luaskan"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Setelan"</string> + <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> + <skip /> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> adalah picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, ketuk untuk membuka setelan dan menonaktifkannya."</string> diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml index 4c1b653f07b1..126d1f13ba03 100644 --- a/libs/WindowManager/Shell/res/values-is/strings.xml +++ b/libs/WindowManager/Shell/res/values-is/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Loka"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Stækka"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Stillingar"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Opna skjáskiptingu"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Valmynd"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> er með mynd í mynd"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ef þú vilt ekki að <xliff:g id="NAME">%s</xliff:g> noti þennan eiginleika skaltu ýta til að opna stillingarnar og slökkva á því."</string> diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index 8321d8386b45..ec221b188563 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Chiudi"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Espandi"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Impostazioni"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Accedi a schermo diviso"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> è in Picture in picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Se non desideri che l\'app <xliff:g id="NAME">%s</xliff:g> utilizzi questa funzione, tocca per aprire le impostazioni e disattivarla."</string> diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml index 721b22277ef5..b87d10c22965 100644 --- a/libs/WindowManager/Shell/res/values-iw/strings.xml +++ b/libs/WindowManager/Shell/res/values-iw/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"סגירה"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"הרחבה"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"הגדרות"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"כניסה למסך המפוצל"</string> <string name="pip_menu_title" msgid="5393619322111827096">"תפריט"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> במצב תמונה בתוך תמונה"</string> <string name="pip_notification_message" msgid="8854051911700302620">"אם אינך רוצה שהתכונה הזו תשמש את <xliff:g id="NAME">%s</xliff:g>, יש להקיש כדי לפתוח את ההגדרות ולהשבית את התכונה."</string> diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml index 80c54f71968a..51ffca6c0d2a 100644 --- a/libs/WindowManager/Shell/res/values-ja/strings.xml +++ b/libs/WindowManager/Shell/res/values-ja/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"閉じる"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"展開"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"設定"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"分割画面に切り替え"</string> <string name="pip_menu_title" msgid="5393619322111827096">"メニュー"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>はピクチャー イン ピクチャーで表示中です"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g>でこの機能を使用しない場合は、タップして設定を開いて OFF にしてください。"</string> diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml index c7b3b682cd46..fc91d72179d3 100644 --- a/libs/WindowManager/Shell/res/values-ka/strings.xml +++ b/libs/WindowManager/Shell/res/values-ka/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"დახურვა"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"გაშლა"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"პარამეტრები"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"გაყოფილ ეკრანში შესვლა"</string> <string name="pip_menu_title" msgid="5393619322111827096">"მენიუ"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> იყენებს რეჟიმს „ეკრანი ეკრანში“"</string> <string name="pip_notification_message" msgid="8854051911700302620">"თუ არ გსურთ, რომ <xliff:g id="NAME">%s</xliff:g> ამ ფუნქციას იყენებდეს, აქ შეხებით შეგიძლიათ გახსნათ პარამეტრები და გამორთოთ ის."</string> diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml index ca9bffc2e7d5..05a905dac69f 100644 --- a/libs/WindowManager/Shell/res/values-kk/strings.xml +++ b/libs/WindowManager/Shell/res/values-kk/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Жабу"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Жаю"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Параметрлер"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Бөлінген экранға кіру"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Mәзір"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> \"суреттегі сурет\" режимінде"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> деген пайдаланушының бұл мүмкіндікті пайдалануын қаламасаңыз, параметрлерді түртіп ашыңыз да, оларды өшіріңіз."</string> diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml index 55d4e466921c..6a1cb2b2ca5d 100644 --- a/libs/WindowManager/Shell/res/values-km/strings.xml +++ b/libs/WindowManager/Shell/res/values-km/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"បិទ"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"ពង្រីក"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"ការកំណត់"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"ចូលមុខងារបំបែកអេក្រង់"</string> <string name="pip_menu_title" msgid="5393619322111827096">"ម៉ឺនុយ"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ស្ថិតក្នុងមុខងាររូបក្នុងរូប"</string> <string name="pip_notification_message" msgid="8854051911700302620">"ប្រសិនបើអ្នកមិនចង់ឲ្យ <xliff:g id="NAME">%s</xliff:g> ប្រើមុខងារនេះ សូមចុចបើកការកំណត់ រួចបិទវា។"</string> diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml index 86c128e59e49..aecb54b96839 100644 --- a/libs/WindowManager/Shell/res/values-kn/strings.xml +++ b/libs/WindowManager/Shell/res/values-kn/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"ಮುಚ್ಚಿ"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"ವಿಸ್ತೃತಗೊಳಿಸು"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"ಸ್ಪ್ಲಿಟ್-ಸ್ಕ್ರೀನ್ಗೆ ಪ್ರವೇಶಿಸಿ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"ಮೆನು"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರವಾಗಿದೆ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ಈ ವೈಶಿಷ್ಟ್ಯ ಬಳಸುವುದನ್ನು ನೀವು ಬಯಸದಿದ್ದರೆ, ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆಯಲು ಮತ್ತು ಅದನ್ನು ಆಫ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml index ae360e1d02e3..5af9ca2a0221 100644 --- a/libs/WindowManager/Shell/res/values-ko/strings.xml +++ b/libs/WindowManager/Shell/res/values-ko/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"닫기"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"펼치기"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"설정"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"화면 분할 모드로 전환"</string> <string name="pip_menu_title" msgid="5393619322111827096">"메뉴"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>에서 PIP 사용 중"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g>에서 이 기능이 사용되는 것을 원하지 않는 경우 탭하여 설정을 열고 기능을 사용 중지하세요."</string> diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml index 7e56359fb4bb..76f192ed0414 100644 --- a/libs/WindowManager/Shell/res/values-ky/strings.xml +++ b/libs/WindowManager/Shell/res/values-ky/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Жабуу"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Жайып көрсөтүү"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Жөндөөлөр"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Экранды бөлүү режимине өтүү"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> – сүрөт ичиндеги сүрөт"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Эгер <xliff:g id="NAME">%s</xliff:g> колдонмосу бул функцияны пайдаланбасын десеңиз, жөндөөлөрдү ачып туруп, аны өчүрүп коюңуз."</string> diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml index e64dc3a9ce6f..4ec6313f8c8c 100644 --- a/libs/WindowManager/Shell/res/values-lo/strings.xml +++ b/libs/WindowManager/Shell/res/values-lo/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"ປິດ"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"ຂະຫຍາຍ"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"ການຕັ້ງຄ່າ"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"ເຂົ້າການແບ່ງໜ້າຈໍ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"ເມນູ"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ແມ່ນເປັນການສະແດງຜົນຫຼາຍຢ່າງພ້ອມກັນ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"ຫາກທ່ານບໍ່ຕ້ອງການ <xliff:g id="NAME">%s</xliff:g> ໃຫ້ໃຊ້ຄຸນສົມບັດນີ້, ໃຫ້ແຕະເພື່ອເປີດການຕັ້ງຄ່າ ແລ້ວປິດມັນໄວ້."</string> diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml index b80ed48c3928..8630e915aa09 100644 --- a/libs/WindowManager/Shell/res/values-lt/strings.xml +++ b/libs/WindowManager/Shell/res/values-lt/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Uždaryti"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Išskleisti"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Nustatymai"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Įjungti išskaidyto ekrano režimą"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meniu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> rodom. vaizdo vaizde"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Jei nenorite, kad „<xliff:g id="NAME">%s</xliff:g>“ naudotų šią funkciją, palietę atidarykite nustatymus ir išjunkite ją."</string> diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml index fb260b9ba73e..b095b88bfa0c 100644 --- a/libs/WindowManager/Shell/res/values-lv/strings.xml +++ b/libs/WindowManager/Shell/res/values-lv/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Aizvērt"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Izvērst"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Iestatījumi"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Piekļūt ekrāna sadalīšanas režīmam"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Izvēlne"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ir attēlā attēlā"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ja nevēlaties lietotnē <xliff:g id="NAME">%s</xliff:g> izmantot šo funkciju, pieskarieties, lai atvērtu iestatījumus un izslēgtu funkciju."</string> diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml index 944d5c7e495b..184fe9d52283 100644 --- a/libs/WindowManager/Shell/res/values-mk/strings.xml +++ b/libs/WindowManager/Shell/res/values-mk/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Затвори"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Проширете"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Поставки"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Влези во поделен екран"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Мени"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> е во слика во слика"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ако не сакате <xliff:g id="NAME">%s</xliff:g> да ја користи функцијава, допрете за да ги отворите поставките и да ја исклучите."</string> diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml index 63b47a840b11..f1bfe9aa055e 100644 --- a/libs/WindowManager/Shell/res/values-ml/strings.xml +++ b/libs/WindowManager/Shell/res/values-ml/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"അവസാനിപ്പിക്കുക"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"വികസിപ്പിക്കുക"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"ക്രമീകരണം"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"സ്ക്രീൻ വിഭജന മോഡിൽ പ്രവേശിക്കുക"</string> <string name="pip_menu_title" msgid="5393619322111827096">"മെനു"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ചിത്രത്തിനുള്ളിൽ ചിത്രം രീതിയിലാണ്"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ഈ ഫീച്ചർ ഉപയോഗിക്കേണ്ടെങ്കിൽ, ടാപ്പ് ചെയ്ത് ക്രമീകരണം തുറന്ന് അത് ഓഫാക്കുക."</string> diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml index 2de7b50c25fa..afe8584955e9 100644 --- a/libs/WindowManager/Shell/res/values-mn/strings.xml +++ b/libs/WindowManager/Shell/res/values-mn/strings.xml @@ -20,6 +20,8 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Хаах"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Дэлгэх"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Тохиргоо"</string> + <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> + <skip /> <string name="pip_menu_title" msgid="5393619322111827096">"Цэс"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> дэлгэцэн доторх дэлгэцэд байна"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Та <xliff:g id="NAME">%s</xliff:g>-д энэ онцлогийг ашиглуулахыг хүсэхгүй байвал тохиргоог нээгээд, үүнийг унтраана уу."</string> diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml index 12506d866ecb..c11af7bf9f2c 100644 --- a/libs/WindowManager/Shell/res/values-mr/strings.xml +++ b/libs/WindowManager/Shell/res/values-mr/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"बंद करा"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"विस्तृत करा"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"सेटिंग्ज"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"स्प्लिट स्क्रीन एंटर करा"</string> <string name="pip_menu_title" msgid="5393619322111827096">"मेनू"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> चित्रामध्ये चित्र मध्ये आहे"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g>ने हे वैशिष्ट्य वापरू नये असे तुम्हाला वाटत असल्यास, सेटिंग्ज उघडण्यासाठी टॅप करा आणि ते बंद करा."</string> diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml index 5cd1ca5a48f2..b495fef54710 100644 --- a/libs/WindowManager/Shell/res/values-ms/strings.xml +++ b/libs/WindowManager/Shell/res/values-ms/strings.xml @@ -20,6 +20,8 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Tutup"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Kembangkan"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Tetapan"</string> + <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> + <skip /> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> terdapat dalam gambar dalam gambar"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Jika anda tidak mahu <xliff:g id="NAME">%s</xliff:g> menggunakan ciri ini, ketik untuk membuka tetapan dan matikan ciri."</string> diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml index 4b3334dfb079..2849137b0151 100644 --- a/libs/WindowManager/Shell/res/values-my/strings.xml +++ b/libs/WindowManager/Shell/res/values-my/strings.xml @@ -20,6 +20,8 @@ <string name="pip_phone_close" msgid="5783752637260411309">"ပိတ်ရန်"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"ချဲ့ရန်"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"ဆက်တင်များ"</string> + <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> + <skip /> <string name="pip_menu_title" msgid="5393619322111827096">"မီနူး"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> သည် နှစ်ခုထပ်၍ကြည့်ခြင်း ဖွင့်ထားသည်"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> အား ဤဝန်ဆောင်မှုကို အသုံးမပြုစေလိုလျှင် ဆက်တင်ကိုဖွင့်ရန် တို့ပြီး ၎င်းဝန်ဆောင်မှုကို ပိတ်လိုက်ပါ။"</string> diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml index f9cf0aa198f4..87bc7dafe902 100644 --- a/libs/WindowManager/Shell/res/values-nb/strings.xml +++ b/libs/WindowManager/Shell/res/values-nb/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Lukk"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Vis"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Innstillinger"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Aktivér delt skjerm"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meny"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> er i bilde-i-bilde"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Hvis du ikke vil at <xliff:g id="NAME">%s</xliff:g> skal bruke denne funksjonen, kan du trykke for å åpne innstillingene og slå den av."</string> diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml index 803f4c4f741b..12df158f0903 100644 --- a/libs/WindowManager/Shell/res/values-ne/strings.xml +++ b/libs/WindowManager/Shell/res/values-ne/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"बन्द गर्नुहोस्"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"विस्तृत गर्नुहोस्"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"सेटिङहरू"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"स्प्लिट स्क्रिन मोड प्रयोग गर्नुहोस्"</string> <string name="pip_menu_title" msgid="5393619322111827096">"मेनु"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> Picture-in-picture मा छ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"तपाईं <xliff:g id="NAME">%s</xliff:g> ले सुविधा प्रयोग नगरोस् भन्ने चाहनुहुन्छ भने ट्याप गरेर सेटिङहरू खोल्नुहोस् र यसलाई निष्क्रिय पार्नुहोस्।"</string> diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml index 658cf6a37b3f..f83ad22dfea7 100644 --- a/libs/WindowManager/Shell/res/values-nl/strings.xml +++ b/libs/WindowManager/Shell/res/values-nl/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Sluiten"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Uitvouwen"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Instellingen"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Gesplitst scherm openen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in scherm-in-scherm"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Als je niet wilt dat <xliff:g id="NAME">%s</xliff:g> deze functie gebruikt, tik je om de instellingen te openen en zet je de functie uit."</string> diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml index 06f53e513ff7..14f92c8f1d1c 100644 --- a/libs/WindowManager/Shell/res/values-or/strings.xml +++ b/libs/WindowManager/Shell/res/values-or/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"ବନ୍ଦ କରନ୍ତୁ"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"ବଢ଼ାନ୍ତୁ"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"ସେଟିଂସ୍"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ମୋଡ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"ମେନୁ"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> \"ଛବି-ଭିତରେ-ଛବି\"ରେ ଅଛି"</string> <string name="pip_notification_message" msgid="8854051911700302620">"ଏହି ବୈଶିଷ୍ଟ୍ୟ <xliff:g id="NAME">%s</xliff:g> ବ୍ୟବହାର ନକରିବାକୁ ଯଦି ଆପଣ ଚାହାଁନ୍ତି, ସେଟିଙ୍ଗ ଖୋଲିବାକୁ ଟାପ୍ କରନ୍ତୁ ଏବଂ ଏହା ଅଫ୍ କରିଦିଅନ୍ତୁ।"</string> diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml index 93bdfe9ce9fb..e09f53adba43 100644 --- a/libs/WindowManager/Shell/res/values-pa/strings.xml +++ b/libs/WindowManager/Shell/res/values-pa/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"ਬੰਦ ਕਰੋ"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"ਵਿਸਤਾਰ ਕਰੋ"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"ਸੈਟਿੰਗਾਂ"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"ਮੀਨੂ"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ਤਸਵੀਰ-ਅੰਦਰ-ਤਸਵੀਰ ਵਿੱਚ ਹੈ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"ਜੇਕਰ ਤੁਸੀਂ ਨਹੀਂ ਚਾਹੁੰਦੇ ਕਿ <xliff:g id="NAME">%s</xliff:g> ਐਪ ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਦੀ ਵਰਤੋਂ ਕਰੇ, ਤਾਂ ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ ਅਤੇ ਇਸਨੂੰ ਬੰਦ ਕਰੋ।"</string> diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml index f704b015501a..a2ef9975e487 100644 --- a/libs/WindowManager/Shell/res/values-pl/strings.xml +++ b/libs/WindowManager/Shell/res/values-pl/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Zamknij"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Rozwiń"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Ustawienia"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Włącz podzielony ekran"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"Aplikacja <xliff:g id="NAME">%s</xliff:g> działa w trybie obraz w obrazie"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Jeśli nie chcesz, by aplikacja <xliff:g id="NAME">%s</xliff:g> korzystała z tej funkcji, otwórz ustawienia i wyłącz ją."</string> diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml index 111d78c1852b..1300e530c0a6 100644 --- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Fechar"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Abrir"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Configurações"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Dividir tela"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Se você não quer que o app <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string> diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml index bb5d30c5869d..f3314f80cdfe 100644 --- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Fechar"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Expandir"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Definições"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Aceder ao ecrã dividido"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"A app <xliff:g id="NAME">%s</xliff:g> está no modo de ecrã no ecrã"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Se não pretende que a app <xliff:g id="NAME">%s</xliff:g> utilize esta funcionalidade, toque para abrir as definições e desative-a."</string> diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml index 111d78c1852b..1300e530c0a6 100644 --- a/libs/WindowManager/Shell/res/values-pt/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Fechar"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Abrir"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Configurações"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Dividir tela"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Se você não quer que o app <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string> diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml index d5e6284ba6c5..01f96c881b7e 100644 --- a/libs/WindowManager/Shell/res/values-ro/strings.xml +++ b/libs/WindowManager/Shell/res/values-ro/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Închideți"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Extindeți"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Setări"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Accesați ecranul împărțit"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meniu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> este în modul picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Dacă nu doriți ca <xliff:g id="NAME">%s</xliff:g> să utilizeze această funcție, atingeți pentru a deschide setările și dezactivați-o."</string> diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml index ec3f3c35c979..6a0e9c12fe7f 100644 --- a/libs/WindowManager/Shell/res/values-ru/strings.xml +++ b/libs/WindowManager/Shell/res/values-ru/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Закрыть"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Развернуть"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Настройки"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Включить разделение экрана"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> находится в режиме \"Картинка в картинке\""</string> <string name="pip_notification_message" msgid="8854051911700302620">"Чтобы отключить эту функцию для приложения \"<xliff:g id="NAME">%s</xliff:g>\", перейдите в настройки."</string> diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml index a2afa0de0444..d7ed24606f08 100644 --- a/libs/WindowManager/Shell/res/values-si/strings.xml +++ b/libs/WindowManager/Shell/res/values-si/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"වසන්න"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"දිග හරින්න"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"සැකසීම්"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"බෙදුම් තිරයට ඇතුළු වන්න"</string> <string name="pip_menu_title" msgid="5393619322111827096">"මෙනුව"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> පින්තූරය-තුළ-පින්තූරය තුළ වේ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"ඔබට <xliff:g id="NAME">%s</xliff:g> මෙම විශේෂාංගය භාවිත කිරීමට අවශ්ය නැති නම්, සැකසීම් විවෘත කිරීමට තට්ටු කර එය ක්රියාවිරහිත කරන්න."</string> diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml index dc163298a997..13fd58f801ea 100644 --- a/libs/WindowManager/Shell/res/values-sk/strings.xml +++ b/libs/WindowManager/Shell/res/values-sk/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Zavrieť"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Rozbaliť"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Nastavenia"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Prejsť na rozdelenú obrazovku"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Ponuka"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> je v režime obraz v obraze"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ak nechcete, aby aplikácia <xliff:g id="NAME">%s</xliff:g> používala túto funkciu, klepnutím otvorte nastavenia a vypnite ju."</string> diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml index 2feac00a4b36..6a6806921c18 100644 --- a/libs/WindowManager/Shell/res/values-sl/strings.xml +++ b/libs/WindowManager/Shell/res/values-sl/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Zapri"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Razširi"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Nastavitve"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Vklopi razdeljen zaslon"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meni"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> je v načinu slika v sliki"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Če ne želite, da aplikacija <xliff:g id="NAME">%s</xliff:g> uporablja to funkcijo, se dotaknite, da odprete nastavitve, in funkcijo izklopite."</string> diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml index cae9306c0d9a..2b0b551c65c9 100644 --- a/libs/WindowManager/Shell/res/values-sq/strings.xml +++ b/libs/WindowManager/Shell/res/values-sq/strings.xml @@ -20,6 +20,8 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Mbyll"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Zgjero"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Cilësimet"</string> + <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> + <skip /> <string name="pip_menu_title" msgid="5393619322111827096">"Menyja"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> është në figurë brenda figurës"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Nëse nuk dëshiron që <xliff:g id="NAME">%s</xliff:g> ta përdorë këtë funksion, trokit për të hapur cilësimet dhe për ta çaktivizuar."</string> diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml index 3fe844b8f7f9..c0c1e3f2849e 100644 --- a/libs/WindowManager/Shell/res/values-sr/strings.xml +++ b/libs/WindowManager/Shell/res/values-sr/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Затвори"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Прошири"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Подешавања"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Уђи на подељени екран"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Мени"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> је слика у слици"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ако не желите да <xliff:g id="NAME">%s</xliff:g> користи ову функцију, додирните да бисте отворили подешавања и искључили је."</string> diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml index b3b80ad2553e..34254d90a93d 100644 --- a/libs/WindowManager/Shell/res/values-sv/strings.xml +++ b/libs/WindowManager/Shell/res/values-sv/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Stäng"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Utöka"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Inställningar"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Starta delad skärm"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Meny"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> visas i bild-i-bild"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Om du inte vill att den här funktionen används i <xliff:g id="NAME">%s</xliff:g> öppnar du inställningarna genom att trycka. Sedan inaktiverar du funktionen."</string> diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml index 0643669bc550..82a9f146c449 100644 --- a/libs/WindowManager/Shell/res/values-sw/strings.xml +++ b/libs/WindowManager/Shell/res/values-sw/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Funga"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Panua"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Mipangilio"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Weka skrini iliyogawanywa"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menyu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> iko katika hali ya picha ndani ya picha nyingine"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Ikiwa hutaki <xliff:g id="NAME">%s</xliff:g> itumie kipengele hiki, gusa ili ufungue mipangilio na uizime."</string> diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml index fa0efe6d4624..0ed778a273af 100644 --- a/libs/WindowManager/Shell/res/values-ta/strings.xml +++ b/libs/WindowManager/Shell/res/values-ta/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"மூடு"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"விரி"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"அமைப்புகள்"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"திரைப் பிரிப்பு பயன்முறைக்குச் செல்"</string> <string name="pip_menu_title" msgid="5393619322111827096">"மெனு"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> தற்போது பிக்ச்சர்-இன்-பிக்ச்சரில் உள்ளது"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> இந்த அம்சத்தைப் பயன்படுத்த வேண்டாம் என நினைத்தால் இங்கு தட்டி அமைப்புகளைத் திறந்து இதை முடக்கவும்."</string> diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml index 3d1f3c0d66b8..8fef67b69747 100644 --- a/libs/WindowManager/Shell/res/values-te/strings.xml +++ b/libs/WindowManager/Shell/res/values-te/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"మూసివేయి"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"విస్తరింపజేయి"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"సెట్టింగ్లు"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"స్ప్లిట్ స్క్రీన్ను ఎంటర్ చేయండి"</string> <string name="pip_menu_title" msgid="5393619322111827096">"మెనూ"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> చిత్రంలో చిత్రం రూపంలో ఉంది"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ఈ లక్షణాన్ని ఉపయోగించకూడదు అని మీరు అనుకుంటే, సెట్టింగ్లను తెరవడానికి ట్యాప్ చేసి, దీన్ని ఆఫ్ చేయండి."</string> diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml index 3eb40fee0807..563ec2ffa2be 100644 --- a/libs/WindowManager/Shell/res/values-th/strings.xml +++ b/libs/WindowManager/Shell/res/values-th/strings.xml @@ -20,6 +20,8 @@ <string name="pip_phone_close" msgid="5783752637260411309">"ปิด"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"ขยาย"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"การตั้งค่า"</string> + <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> + <skip /> <string name="pip_menu_title" msgid="5393619322111827096">"เมนู"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ใช้การแสดงภาพซ้อนภาพ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"หากคุณไม่ต้องการให้ <xliff:g id="NAME">%s</xliff:g> ใช้ฟีเจอร์นี้ ให้แตะเพื่อเปิดการตั้งค่าแล้วปิดฟีเจอร์"</string> diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml index 6908cb8da4fa..a9a36bbb6a49 100644 --- a/libs/WindowManager/Shell/res/values-tl/strings.xml +++ b/libs/WindowManager/Shell/res/values-tl/strings.xml @@ -20,6 +20,8 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Isara"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Palawakin"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Mga Setting"</string> + <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> + <skip /> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"Nasa picture-in-picture ang <xliff:g id="NAME">%s</xliff:g>"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Kung ayaw mong magamit ni <xliff:g id="NAME">%s</xliff:g> ang feature na ito, i-tap upang buksan ang mga setting at i-off ito."</string> diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml index 61deb566e7f3..971520a0f229 100644 --- a/libs/WindowManager/Shell/res/values-tr/strings.xml +++ b/libs/WindowManager/Shell/res/values-tr/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Kapat"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Genişlet"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Ayarlar"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Bölünmüş ekrana geç"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menü"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>, pencere içinde pencere özelliğini kullanıyor"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> uygulamasının bu özelliği kullanmasını istemiyorsanız dokunarak ayarları açın ve söz konusu özelliği kapatın."</string> diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml index 00f5dd1fc606..30147353e3f6 100644 --- a/libs/WindowManager/Shell/res/values-uk/strings.xml +++ b/libs/WindowManager/Shell/res/values-uk/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Закрити"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Розгорнути"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Налаштування"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Розділити екран"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string> <string name="pip_notification_title" msgid="1347104727641353453">"У додатку <xliff:g id="NAME">%s</xliff:g> є функція \"Картинка в картинці\""</string> <string name="pip_notification_message" msgid="8854051911700302620">"Щоб додаток <xliff:g id="NAME">%s</xliff:g> не використовував цю функцію, вимкніть її в налаштуваннях."</string> diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml index 7a12c9135e2b..07319efdc52c 100644 --- a/libs/WindowManager/Shell/res/values-ur/strings.xml +++ b/libs/WindowManager/Shell/res/values-ur/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"بند کریں"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"پھیلائیں"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"ترتیبات"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"اسپلٹ اسکرین تک رسائی"</string> <string name="pip_menu_title" msgid="5393619322111827096">"مینو"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> تصویر میں تصویر میں ہے"</string> <string name="pip_notification_message" msgid="8854051911700302620">"اگر آپ نہیں چاہتے ہیں کہ <xliff:g id="NAME">%s</xliff:g> اس خصوصیت کا استعمال کرے تو ترتیبات کھولنے کے لیے تھپتھپا کر اسے آف کرے۔"</string> diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml index c640744d6d4b..4c79d64fb8e1 100644 --- a/libs/WindowManager/Shell/res/values-uz/strings.xml +++ b/libs/WindowManager/Shell/res/values-uz/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Yopish"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Yoyish"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Sozlamalar"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Ajratilgan ekranga kirish"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menyu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> tasvir ustida tasvir rejimida"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ilovasi uchun bu funksiyani sozlamalar orqali faolsizlantirish mumkin."</string> diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml index ebf0bf60c306..b9f23cd4672d 100644 --- a/libs/WindowManager/Shell/res/values-vi/strings.xml +++ b/libs/WindowManager/Shell/res/values-vi/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Đóng"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Mở rộng"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Cài đặt"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Truy cập chế độ chia đôi màn hình"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> đang ở chế độ ảnh trong ảnh"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Nếu bạn không muốn <xliff:g id="NAME">%s</xliff:g> sử dụng tính năng này, hãy nhấn để mở cài đặt và tắt tính năng này."</string> diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml index f134e2ecd57d..c0072582ec88 100644 --- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"关闭"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"展开"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"设置"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"进入分屏模式"</string> <string name="pip_menu_title" msgid="5393619322111827096">"菜单"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>目前位于“画中画”中"</string> <string name="pip_notification_message" msgid="8854051911700302620">"如果您不想让“<xliff:g id="NAME">%s</xliff:g>”使用此功能,请点按以打开设置,然后关闭此功能。"</string> diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml index 01b861d7b5f7..5e336770e83a 100644 --- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"關閉"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"展開"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"設定"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"進入分割螢幕"</string> <string name="pip_menu_title" msgid="5393619322111827096">"選單"</string> <string name="pip_notification_title" msgid="1347104727641353453">"「<xliff:g id="NAME">%s</xliff:g>」目前在畫中畫模式"</string> <string name="pip_notification_message" msgid="8854051911700302620">"如果您不想「<xliff:g id="NAME">%s</xliff:g>」使用此功能,請輕按以開啟設定,然後停用此功能。"</string> diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml index bd7ec93a550f..2439a975daa8 100644 --- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"關閉"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"展開"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"設定"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"進入分割畫面"</string> <string name="pip_menu_title" msgid="5393619322111827096">"選單"</string> <string name="pip_notification_title" msgid="1347104727641353453">"「<xliff:g id="NAME">%s</xliff:g>」目前在子母畫面中"</string> <string name="pip_notification_message" msgid="8854051911700302620">"如果你不想讓「<xliff:g id="NAME">%s</xliff:g>」使用這項功能,請輕觸開啟設定頁面,然後停用此功能。"</string> diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml index 6d0858cc615c..20128f602abf 100644 --- a/libs/WindowManager/Shell/res/values-zu/strings.xml +++ b/libs/WindowManager/Shell/res/values-zu/strings.xml @@ -20,6 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Vala"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Nweba"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Izilungiselelo"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Faka ukuhlukanisa isikrini"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Imenyu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"U-<xliff:g id="NAME">%s</xliff:g> ungaphakathi kwesithombe esiphakathi kwesithombe"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Uma ungafuni i-<xliff:g id="NAME">%s</xliff:g> ukuthi isebenzise lesi sici, thepha ukuze uvule izilungiselelo uphinde uyivale."</string> diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml index b25a2189cd4d..23a21724e43d 100644 --- a/libs/WindowManager/Shell/res/values/colors.xml +++ b/libs/WindowManager/Shell/res/values/colors.xml @@ -29,7 +29,10 @@ <color name="bubbles_light">#FFFFFF</color> <color name="bubbles_dark">@color/GM2_grey_800</color> <color name="bubbles_icon_tint">@color/GM2_grey_700</color> - <color name="size_compat_hint_bubble">#30312B</color> + + <!-- Size Compat Restart Button --> + <color name="size_compat_background">@android:color/system_neutral1_800</color> + <color name="size_compat_text">@android:color/system_neutral1_50</color> <!-- GM2 colors --> <color name="GM2_grey_200">#E8EAED</color> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java index 7784665b3031..6f4e22fa8a04 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java @@ -93,6 +93,19 @@ public class DisplayLayout { private boolean mReverseDefaultRotation = false; private InsetsState mInsetsState = new InsetsState(); + /** + * Different from {@link #equals(Object)}, this method compares the basic geometry properties + * of two {@link DisplayLayout} objects including width, height, rotation, density and cutout. + * @return {@code true} if the given {@link DisplayLayout} is identical geometry wise. + */ + public boolean isSameGeometry(@NonNull DisplayLayout other) { + return mWidth == other.mWidth + && mHeight == other.mHeight + && mRotation == other.mRotation + && mDensityDpi == other.mDensityDpi + && Objects.equals(mCutout, other.mCutout); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java index c5713b452097..1039e2ac4fd9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java @@ -356,9 +356,6 @@ public class SystemWindows { public void dispatchGetNewSurface() {} @Override - public void windowFocusChanged(boolean hasFocus) {} - - @Override public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {} @Override 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 625bcee673b5..d07fff3cce79 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 @@ -34,6 +34,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.IntDef; +import android.annotation.NonNull; import android.app.ActivityManager; import android.content.Context; import android.content.res.Configuration; @@ -61,6 +62,8 @@ import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; +import java.io.PrintWriter; + /** * Records and handles layout of splits. Helps to calculate proper bounds when configuration or * divide position changes. @@ -415,6 +418,19 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange return bounds.width() > bounds.height(); } + /** Reverse the split position. */ + @SplitPosition + public static int reversePosition(@SplitPosition int position) { + switch (position) { + case SPLIT_POSITION_TOP_OR_LEFT: + return SPLIT_POSITION_BOTTOM_OR_RIGHT; + case SPLIT_POSITION_BOTTOM_OR_RIGHT: + return SPLIT_POSITION_TOP_OR_LEFT; + default: + return SPLIT_POSITION_UNDEFINED; + } + } + /** * Return if this layout is landscape. */ @@ -502,6 +518,13 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } } + /** Dumps the current split bounds recorded in this layout. */ + public void dump(@NonNull PrintWriter pw, String prefix) { + pw.println(prefix + "bounds1=" + mBounds1.toShortString()); + pw.println(prefix + "dividerBounds=" + mDividerBounds.toShortString()); + pw.println(prefix + "bounds2=" + mBounds2.toShortString()); + } + /** Handles layout change event. */ public interface SplitLayoutHandler { 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 3f5b70bac6e1..287d0fb66aa9 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 @@ -74,6 +74,7 @@ import com.android.wm.shell.pip.phone.PipAppOpsListener; import com.android.wm.shell.pip.phone.PipTouchHandler; import com.android.wm.shell.recents.RecentTasks; import com.android.wm.shell.recents.RecentTasksController; +import com.android.wm.shell.sizecompatui.SizeCompatUI; import com.android.wm.shell.sizecompatui.SizeCompatUIController; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreenController; @@ -171,11 +172,18 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides + static SizeCompatUI provideSizeCompatUI(SizeCompatUIController sizeCompatUIController) { + return sizeCompatUIController.asSizeCompatUI(); + } + + @WMSingleton + @Provides static SizeCompatUIController provideSizeCompatUIController(Context context, DisplayController displayController, DisplayInsetsController displayInsetsController, - DisplayImeController imeController, SyncTransactionQueue syncQueue) { + DisplayImeController imeController, SyncTransactionQueue syncQueue, + @ShellMainThread ShellExecutor mainExecutor) { return new SizeCompatUIController(context, displayController, displayInsetsController, - imeController, syncQueue); + imeController, syncQueue, mainExecutor); } @WMSingleton @@ -236,15 +244,24 @@ public abstract class WMShellBaseModule { // Fullscreen // + // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride} + @BindsOptionalOf + @DynamicOverride + abstract FullscreenTaskListener optionalFullscreenTaskListener(); + @WMSingleton @Provides static FullscreenTaskListener provideFullscreenTaskListener( + @DynamicOverride Optional<FullscreenTaskListener> fullscreenTaskListener, SyncTransactionQueue syncQueue, Optional<FullscreenUnfoldController> optionalFullscreenUnfoldController, - Optional<RecentTasksController> recentTasksOptional - ) { - return new FullscreenTaskListener(syncQueue, optionalFullscreenUnfoldController, - recentTasksOptional); + Optional<RecentTasksController> recentTasksOptional) { + if (fullscreenTaskListener.isPresent()) { + return fullscreenTaskListener.get(); + } else { + return new FullscreenTaskListener(syncQueue, optionalFullscreenUnfoldController, + recentTasksOptional); + } } // diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java index 05111a3d4436..9575b0a720bc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java @@ -594,10 +594,10 @@ public class PipAnimationController { getSurfaceTransactionHelper().scaleAndCrop(tx, leash, initialSourceValue, bounds, insets); if (shouldApplyCornerRadius()) { - final Rect destinationBounds = new Rect(bounds); - destinationBounds.inset(insets); + final Rect sourceBounds = new Rect(initialContainerRect); + sourceBounds.inset(insets); getSurfaceTransactionHelper().round(tx, leash, - initialContainerRect, destinationBounds); + sourceBounds, bounds); } } if (!handlePipTransaction(leash, tx, bounds)) { @@ -641,11 +641,13 @@ public class PipAnimationController { y = fraction * (end.bottom - start.top) + start.top; } } + final Rect sourceBounds = new Rect(initialContainerRect); + sourceBounds.inset(insets); getSurfaceTransactionHelper() .rotateAndScaleWithCrop(tx, leash, initialContainerRect, bounds, insets, degree, x, y, isOutPipDirection, rotationDelta == ROTATION_270 /* clockwise */) - .round(tx, leash, initialContainerRect, bounds); + .round(tx, leash, sourceBounds, bounds); tx.apply(); } 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 d18bcfc782c8..79e3444a0d82 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 @@ -88,7 +88,6 @@ import com.android.wm.shell.pip.PipUtils; import com.android.wm.shell.transition.Transitions; import java.io.PrintWriter; -import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; @@ -469,7 +468,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb } private void onDisplayChanged(DisplayLayout layout, boolean saveRestoreSnapFraction) { - if (Objects.equals(layout, mPipBoundsState.getDisplayLayout())) { + if (mPipBoundsState.getDisplayLayout().isSameGeometry(layout)) { return; } Runnable updateDisplayLayout = () -> { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java index 00083d986dbe..83390a539043 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java @@ -57,7 +57,7 @@ import java.lang.annotation.RetentionPolicy; public class TvPipController implements PipTransitionController.PipTransitionCallback, TvPipMenuController.Delegate, TvPipNotificationController.Delegate { private static final String TAG = "TvPipController"; - static final boolean DEBUG = true; + static final boolean DEBUG = false; private static final int NONEXISTENT_TASK_ID = -1; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java index 7cf3bafe499a..a006f308d694 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java @@ -111,6 +111,11 @@ public class RecentTasksController implements TaskStackListenerCallback, if (taskId1 == taskId2) { return; } + if (mSplitTasks.get(taskId1, INVALID_TASK_ID) == taskId2 + && mTaskSplitBoundsMap.get(taskId1).equals(splitBounds)) { + // If the two tasks are already paired and the bounds are the same, then skip updating + return; + } // Remove any previous pairs removeSplitPair(taskId1); removeSplitPair(taskId2); @@ -121,6 +126,7 @@ public class RecentTasksController implements TaskStackListenerCallback, mSplitTasks.put(taskId2, taskId1); mTaskSplitBoundsMap.put(taskId1, splitBounds); mTaskSplitBoundsMap.put(taskId2, splitBounds); + notifyRecentTasksChanged(); } /** @@ -133,6 +139,7 @@ public class RecentTasksController implements TaskStackListenerCallback, mSplitTasks.delete(pairedTaskId); mTaskSplitBoundsMap.remove(taskId); mTaskSplitBoundsMap.remove(pairedTaskId); + notifyRecentTasksChanged(); } } @@ -217,7 +224,7 @@ public class RecentTasksController implements TaskStackListenerCallback, } final int pairedTaskId = mSplitTasks.get(taskInfo.taskId); - if (pairedTaskId != INVALID_TASK_ID) { + if (pairedTaskId != INVALID_TASK_ID && rawMapping.contains(pairedTaskId)) { final ActivityManager.RecentTaskInfo pairedTaskInfo = rawMapping.get(pairedTaskId); rawMapping.remove(pairedTaskId); recentTasks.add(new GroupedRecentTaskInfo(taskInfo, pairedTaskInfo, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUI.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUI.java new file mode 100644 index 000000000000..a703114194a0 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUI.java @@ -0,0 +1,32 @@ +/* + * 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.sizecompatui; + +import com.android.wm.shell.common.annotations.ExternalThread; + +/** + * Interface to engage size compat UI. + */ +@ExternalThread +public interface SizeCompatUI { + /** + * Called when the keyguard occluded state changes. Removes all size compat UIs if the + * keyguard is now occluded. + * @param occluded indicates if the keyguard is now occluded. + */ + void onKeyguardOccludedChanged(boolean occluded); +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java index 04d974a09cd7..e06070ab12e5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java @@ -35,13 +35,16 @@ import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListener; import com.android.wm.shell.common.DisplayLayout; +import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; +import com.android.wm.shell.common.annotations.ExternalThread; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.function.Consumer; +import java.util.function.Predicate; /** * Controls to show/update restart-activity buttons on Tasks based on whether the foreground @@ -78,26 +81,37 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, private final DisplayInsetsController mDisplayInsetsController; private final DisplayImeController mImeController; private final SyncTransactionQueue mSyncQueue; + private final ShellExecutor mMainExecutor; + private final SizeCompatUIImpl mImpl = new SizeCompatUIImpl(); private SizeCompatUICallback mCallback; /** Only show once automatically in the process life. */ private boolean mHasShownHint; + /** Indicates if the keyguard is currently occluded, in which case size compat UIs shouldn't + * be shown. */ + private boolean mKeyguardOccluded; public SizeCompatUIController(Context context, DisplayController displayController, DisplayInsetsController displayInsetsController, DisplayImeController imeController, - SyncTransactionQueue syncQueue) { + SyncTransactionQueue syncQueue, + ShellExecutor mainExecutor) { mContext = context; mDisplayController = displayController; mDisplayInsetsController = displayInsetsController; mImeController = imeController; mSyncQueue = syncQueue; + mMainExecutor = mainExecutor; mDisplayController.addDisplayWindowListener(this); mImeController.addPositionProcessor(this); } + public SizeCompatUI asSizeCompatUI() { + return mImpl; + } + /** Sets the callback for UI interactions. */ public void setSizeCompatUICallback(SizeCompatUICallback callback) { mCallback = callback; @@ -106,6 +120,7 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, /** * Called when the Task info changed. Creates and updates the size compat UI if there is an * activity in size compat, or removes the UI if there is no size compat activity. + * * @param displayId display the task and activity are in. * @param taskId task the activity is in. * @param taskConfig task config to place the size compat UI with. @@ -180,7 +195,19 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, } // Hide the size compat UIs when input method is showing. - forAllLayoutsOnDisplay(displayId, layout -> layout.updateImeVisibility(isShowing)); + forAllLayoutsOnDisplay(displayId, + layout -> layout.updateVisibility(showOnDisplay(displayId))); + } + + @VisibleForTesting + void onKeyguardOccludedChanged(boolean occluded) { + mKeyguardOccluded = occluded; + // Hide the size compat UIs when keyguard is occluded. + forAllLayouts(layout -> layout.updateVisibility(showOnDisplay(layout.getDisplayId()))); + } + + private boolean showOnDisplay(int displayId) { + return !mKeyguardOccluded && !isImeShowingOnDisplay(displayId); } private boolean isImeShowingOnDisplay(int displayId) { @@ -198,7 +225,7 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, final SizeCompatUILayout layout = createLayout(context, displayId, taskId, taskConfig, taskListener); mActiveLayouts.put(taskId, layout); - layout.createSizeCompatButton(isImeShowingOnDisplay(displayId)); + layout.createSizeCompatButton(showOnDisplay(displayId)); } @VisibleForTesting @@ -218,8 +245,7 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, if (layout == null) { return; } - layout.updateSizeCompatInfo(taskConfig, taskListener, - isImeShowingOnDisplay(layout.getDisplayId())); + layout.updateSizeCompatInfo(taskConfig, taskListener, showOnDisplay(layout.getDisplayId())); } private void removeLayout(int taskId) { @@ -250,15 +276,37 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, } private void forAllLayoutsOnDisplay(int displayId, Consumer<SizeCompatUILayout> callback) { + forAllLayouts(layout -> layout.getDisplayId() == displayId, callback); + } + + private void forAllLayouts(Consumer<SizeCompatUILayout> callback) { + forAllLayouts(layout -> true, callback); + } + + private void forAllLayouts(Predicate<SizeCompatUILayout> condition, + Consumer<SizeCompatUILayout> callback) { for (int i = 0; i < mActiveLayouts.size(); i++) { final int taskId = mActiveLayouts.keyAt(i); final SizeCompatUILayout layout = mActiveLayouts.get(taskId); - if (layout != null && layout.getDisplayId() == displayId) { + if (layout != null && condition.test(layout)) { callback.accept(layout); } } } + /** + * The interface for calls from outside the Shell, within the host process. + */ + @ExternalThread + private class SizeCompatUIImpl implements SizeCompatUI { + @Override + public void onKeyguardOccludedChanged(boolean occluded) { + mMainExecutor.execute(() -> { + SizeCompatUIController.this.onKeyguardOccludedChanged(occluded); + }); + } + } + /** An implementation of {@link OnInsetsChangedListener} for a given display id. */ private class PerDisplayOnInsetsChangedListener implements OnInsetsChangedListener { final int mDisplayId; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java index 1a2c94fd4747..c35b89af6c1b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java @@ -103,9 +103,9 @@ class SizeCompatUILayout { } /** Creates the activity restart button window. */ - void createSizeCompatButton(boolean isImeShowing) { - if (isImeShowing || mButton != null) { - // When ime is showing, wait until ime is dismiss to create UI. + void createSizeCompatButton(boolean show) { + if (!show || mButton != null) { + // Wait until button should be visible. return; } mButton = mButtonWindowManager.createSizeCompatButton(); @@ -154,7 +154,7 @@ class SizeCompatUILayout { /** Called when size compat info changed. */ void updateSizeCompatInfo(Configuration taskConfig, - ShellTaskOrganizer.TaskListener taskListener, boolean isImeShowing) { + ShellTaskOrganizer.TaskListener taskListener, boolean show) { final Configuration prevTaskConfig = mTaskConfig; final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener; mTaskConfig = taskConfig; @@ -170,7 +170,7 @@ class SizeCompatUILayout { if (mButton == null || prevTaskListener != taskListener) { // TaskListener changed, recreate the button for new surface parent. release(); - createSizeCompatButton(isImeShowing); + createSizeCompatButton(show); return; } @@ -204,16 +204,16 @@ class SizeCompatUILayout { } } - /** Called when IME visibility changed. */ - void updateImeVisibility(boolean isImeShowing) { + /** Called when the visibility of the UI should change. */ + void updateVisibility(boolean show) { if (mButton == null) { - // Button may not be created because ime is previous showing. - createSizeCompatButton(isImeShowing); + // Button may not have been created because it was hidden previously. + createSizeCompatButton(show); return; } // Hide size compat UIs when IME is showing. - final int newVisibility = isImeShowing ? View.GONE : View.VISIBLE; + final int newVisibility = show ? View.VISIBLE : View.GONE; if (mButton.getVisibility() != newVisibility) { mButton.setVisibility(newVisibility); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java index f8c03044c5c9..1ba1d22e7831 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java @@ -50,10 +50,6 @@ class SideStage extends StageTaskListener { wct.setBounds(rootToken, rootBounds).reorder(rootToken, true /* onTop */); } - void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) { - wct.reparent(task.token, mRootTaskInfo.token, true /* onTop*/); - } - boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) { // No matter if the root task is empty or not, moving the root to bottom because it no // longer preserves visible child task. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java index e86462f666c9..02edaa00fac3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java @@ -87,6 +87,12 @@ public interface SplitScreen { */ void onKeyguardVisibilityChanged(boolean showing); + /** Called when device waking up finished. */ + void onFinishedWakingUp(); + + /** Called when device going to sleep finished. */ + void onFinishedGoingToSleep(); + /** Get a string representation of a stage type */ static String stageTypeToString(@StageType int stage) { switch (stage) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 8af72a89a75f..6b42ed775fb7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -24,6 +24,8 @@ import static android.view.RemoteAnimationTarget.MODE_OPENING; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE; +import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; import android.app.ActivityManager; import android.app.ActivityTaskManager; @@ -182,30 +184,17 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition) { - final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId); - if (task == null) { - throw new IllegalArgumentException("Unknown taskId" + taskId); - } - return moveToSideStage(task, sideStagePosition); + return moveToStage(taskId, STAGE_TYPE_SIDE, sideStagePosition, + new WindowContainerTransaction()); } - public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition, - WindowContainerTransaction wct) { + private boolean moveToStage(int taskId, @SplitScreen.StageType int stageType, + @SplitPosition int stagePosition, WindowContainerTransaction wct) { final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId); if (task == null) { throw new IllegalArgumentException("Unknown taskId" + taskId); } - return moveToSideStage(task, sideStagePosition, wct); - } - - public boolean moveToSideStage(ActivityManager.RunningTaskInfo task, - @SplitPosition int sideStagePosition) { - return mStageCoordinator.moveToSideStage(task, sideStagePosition); - } - - public boolean moveToSideStage(ActivityManager.RunningTaskInfo task, - @SplitPosition int sideStagePosition, WindowContainerTransaction wct) { - return mStageCoordinator.moveToSideStage(task, sideStagePosition, wct); + return mStageCoordinator.moveToStage(task, stageType, stagePosition, wct); } public boolean removeFromSideStage(int taskId) { @@ -221,13 +210,14 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } public void enterSplitScreen(int taskId, boolean leftOrTop) { - moveToSideStage(taskId, - leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT); + enterSplitScreen(taskId, leftOrTop, new WindowContainerTransaction()); } public void enterSplitScreen(int taskId, boolean leftOrTop, WindowContainerTransaction wct) { - moveToSideStage(taskId, - leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT, wct); + final int stageType = isSplitScreenVisible() ? STAGE_TYPE_UNDEFINED : STAGE_TYPE_SIDE; + final int stagePosition = + leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT; + moveToStage(taskId, stageType, stagePosition, wct); } public void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) { @@ -242,6 +232,14 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator.onKeyguardVisibilityChanged(showing); } + public void onFinishedWakingUp() { + mStageCoordinator.onFinishedWakingUp(); + } + + public void onFinishedGoingToSleep() { + mStageCoordinator.onFinishedGoingToSleep(); + } + public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) { mStageCoordinator.exitSplitScreenOnHide(exitSplitScreenOnHide); } @@ -501,6 +499,20 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, SplitScreenController.this.onKeyguardVisibilityChanged(showing); }); } + + @Override + public void onFinishedWakingUp() { + mMainExecutor.execute(() -> { + SplitScreenController.this.onFinishedWakingUp(); + }); + } + + @Override + public void onFinishedGoingToSleep() { + mMainExecutor.execute(() -> { + SplitScreenController.this.onFinishedGoingToSleep(); + }); + } } /** 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 d4941916850d..a3726d46d2a4 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 @@ -155,6 +155,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, private boolean mShouldUpdateRecents; private boolean mExitSplitScreenOnHide; private boolean mKeyguardOccluded; + private boolean mDeviceSleep; @SplitScreen.StageType private int mDismissTop = NO_DISMISS; @@ -273,18 +274,31 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, return mSideStageListener.mVisible && mMainStageListener.mVisible; } - boolean moveToSideStage(ActivityManager.RunningTaskInfo task, - @SplitPosition int sideStagePosition) { - final WindowContainerTransaction wct = new WindowContainerTransaction(); - return moveToSideStage(task, sideStagePosition, wct); - } + boolean moveToStage(ActivityManager.RunningTaskInfo task, @SplitScreen.StageType int stageType, + @SplitPosition int stagePosition, WindowContainerTransaction wct) { + StageTaskListener targetStage; + int sideStagePosition; + if (stageType == STAGE_TYPE_MAIN) { + targetStage = mMainStage; + sideStagePosition = SplitLayout.reversePosition(stagePosition); + } else if (stageType == STAGE_TYPE_SIDE) { + targetStage = mSideStage; + sideStagePosition = stagePosition; + } else { + if (mMainStage.isActive()) { + // If the split screen is activated, retrieves target stage based on position. + targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage; + sideStagePosition = mSideStagePosition; + } else { + targetStage = mSideStage; + sideStagePosition = stagePosition; + } + } - boolean moveToSideStage(ActivityManager.RunningTaskInfo task, - @SplitPosition int sideStagePosition, WindowContainerTransaction wct) { - final WindowContainerTransaction evictWct = new WindowContainerTransaction(); setSideStagePosition(sideStagePosition, wct); - mSideStage.evictAllChildren(evictWct); - mSideStage.addTask(task, wct); + final WindowContainerTransaction evictWct = new WindowContainerTransaction(); + targetStage.evictAllChildren(evictWct); + targetStage.addTask(task, wct); if (!evictWct.isEmpty()) { wct.merge(evictWct, true /* transfer */); } @@ -463,9 +477,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, case STAGE_TYPE_MAIN: { if (position != SPLIT_POSITION_UNDEFINED) { // Set the side stage opposite of what we want to the main stage. - final int sideStagePosition = position == SPLIT_POSITION_TOP_OR_LEFT - ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT; - setSideStagePosition(sideStagePosition, wct); + setSideStagePosition(SplitLayout.reversePosition(position), wct); } else { position = getMainStagePosition(); } @@ -489,8 +501,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @SplitLayout.SplitPosition int getMainStagePosition() { - return mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT - ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT; + return SplitLayout.reversePosition(mSideStagePosition); } void setSideStagePosition(@SplitPosition int sideStagePosition, @@ -537,6 +548,17 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } + void onFinishedWakingUp() { + if (mMainStage.isActive()) { + exitSplitScreenIfKeyguardOccluded(); + } + mDeviceSleep = false; + } + + void onFinishedGoingToSleep() { + mDeviceSleep = true; + } + void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) { mExitSplitScreenOnHide = exitSplitScreenOnHide; } @@ -565,6 +587,19 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, applyExitSplitScreen(childrenToTop, wct, exitReason); } + private void exitSplitScreenIfKeyguardOccluded() { + final boolean mainStageVisible = mMainStageListener.mVisible; + final boolean oneStageVisible = mainStageVisible ^ mSideStageListener.mVisible; + if (mDeviceSleep && mKeyguardOccluded && oneStageVisible) { + // Only the stages include show-when-locked activity is visible while keyguard occluded. + // Dismiss split because there's show-when-locked activity showing on top of keyguard. + // Also make sure the task contains show-when-locked activity remains on top after split + // dismissed. + final StageTaskListener toTop = mainStageVisible ? mMainStage : mSideStage; + exitSplitScreen(toTop, EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP); + } + } + private void applyExitSplitScreen(StageTaskListener childrenToTop, WindowContainerTransaction wct, @ExitReason int exitReason) { mRecentTasks.ifPresent(recentTasks -> { @@ -780,14 +815,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, // like the cases keyguard showing or screen off. exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RETURN_HOME); } - } else if (mKeyguardOccluded) { - // At least one of the stages is visible while keyguard occluded. Dismiss split because - // there's show-when-locked activity showing on top of keyguard. Also make sure the - // task contains show-when-locked activity remains on top after split dismissed. - final StageTaskListener toTop = - mainStageVisible ? mMainStage : (sideStageVisible ? mSideStage : null); - exitSplitScreen(toTop, EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP); } + exitSplitScreenIfKeyguardOccluded(); mSyncQueue.runInSync(t -> { // Same above, we only set root tasks and divider leash visibility when both stage @@ -870,8 +899,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Override public void onDoubleTappedDivider() { - setSideStagePosition(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT - ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT, null /* wct */); + setSideStagePosition(SplitLayout.reversePosition(mSideStagePosition), null /* wct */); mLogger.logSwap(getMainStagePosition(), mMainStage.getTopChildTaskUid(), getSideStagePosition(), mSideStage.getTopChildTaskUid(), mSplitLayout.isLandscape()); @@ -1296,11 +1324,16 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, pw.println(prefix + TAG + " mDisplayId=" + mDisplayId); pw.println(innerPrefix + "mDividerVisible=" + mDividerVisible); pw.println(innerPrefix + "MainStage"); + pw.println(childPrefix + "stagePosition=" + getMainStagePosition()); pw.println(childPrefix + "isActive=" + mMainStage.isActive()); mMainStageListener.dump(pw, childPrefix); pw.println(innerPrefix + "SideStage"); + pw.println(childPrefix + "stagePosition=" + getSideStagePosition()); mSideStageListener.dump(pw, childPrefix); - pw.println(innerPrefix + "mSplitLayout=" + mSplitLayout); + if (mMainStage.isActive()) { + pw.println(innerPrefix + "SplitLayout"); + mSplitLayout.dump(pw, childPrefix); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index 62b8638a2582..5b0824567194 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -293,6 +293,10 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { } } + void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) { + wct.reparent(task.token, mRootTaskInfo.token, true /* onTop*/); + } + void setBounds(Rect bounds, WindowContainerTransaction wct) { wct.setBounds(mRootTaskInfo.token, bounds); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/StagedSplitBounds.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/StagedSplitBounds.java index aadf792c572f..a0c84cc33ebd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/StagedSplitBounds.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/StagedSplitBounds.java @@ -19,6 +19,8 @@ import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; +import java.util.Objects; + /** * Container of various information needed to display split screen * tasks/leashes/etc in Launcher @@ -93,6 +95,24 @@ public class StagedSplitBounds implements Parcelable { } @Override + public boolean equals(Object obj) { + if (!(obj instanceof StagedSplitBounds)) { + return false; + } + // Only need to check the base fields (the other fields are derived from these) + final StagedSplitBounds other = (StagedSplitBounds) obj; + return Objects.equals(leftTopBounds, other.leftTopBounds) + && Objects.equals(rightBottomBounds, other.rightBottomBounds) + && leftTopTaskId == other.leftTopTaskId + && rightBottomTaskId == other.rightBottomTaskId; + } + + @Override + public int hashCode() { + return Objects.hash(leftTopBounds, rightBottomBounds, leftTopTaskId, rightBottomTaskId); + } + + @Override public String toString() { return "LeftTop: " + leftTopBounds + ", taskId: " + leftTopTaskId + "\n" + "RightBottom: " + rightBottomBounds + ", taskId: " + rightBottomTaskId + "\n" diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java index 19a5417aace6..50f6bd7b4927 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static java.lang.Integer.MAX_VALUE; @@ -83,6 +84,36 @@ public class RecentTasksControllerTest extends ShellTestCase { } @Test + public void testAddRemoveSplitNotifyChange() { + ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1); + ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2); + setRawList(t1, t2); + + mRecentTasksController.addSplitPair(t1.taskId, t2.taskId, mock(StagedSplitBounds.class)); + verify(mRecentTasksController).notifyRecentTasksChanged(); + + reset(mRecentTasksController); + mRecentTasksController.removeSplitPair(t1.taskId); + verify(mRecentTasksController).notifyRecentTasksChanged(); + } + + @Test + public void testAddSameSplitBoundsInfoSkipNotifyChange() { + ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1); + ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2); + setRawList(t1, t2); + + // Verify only one update if the split info is the same + StagedSplitBounds bounds1 = new StagedSplitBounds(new Rect(0, 0, 50, 50), + new Rect(50, 50, 100, 100), t1.taskId, t2.taskId); + mRecentTasksController.addSplitPair(t1.taskId, t2.taskId, bounds1); + StagedSplitBounds bounds2 = new StagedSplitBounds(new Rect(0, 0, 50, 50), + new Rect(50, 50, 100, 100), t1.taskId, t2.taskId); + mRecentTasksController.addSplitPair(t1.taskId, t2.taskId, bounds2); + verify(mRecentTasksController, times(1)).notifyRecentTasksChanged(); + } + + @Test public void testGetRecentTasks() { ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1); ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java index d12cf5c3518a..877b19223bf6 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java @@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.content.Context; @@ -43,6 +44,7 @@ import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListener; import com.android.wm.shell.common.DisplayLayout; +import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import org.junit.Before; @@ -72,6 +74,7 @@ public class SizeCompatUIControllerTest extends ShellTestCase { private @Mock DisplayImeController mMockImeController; private @Mock ShellTaskOrganizer.TaskListener mMockTaskListener; private @Mock SyncTransactionQueue mMockSyncQueue; + private @Mock ShellExecutor mMockExecutor; private @Mock SizeCompatUILayout mMockLayout; @Captor @@ -85,7 +88,7 @@ public class SizeCompatUIControllerTest extends ShellTestCase { doReturn(DISPLAY_ID).when(mMockLayout).getDisplayId(); doReturn(TASK_ID).when(mMockLayout).getTaskId(); mController = new SizeCompatUIController(mContext, mMockDisplayController, - mMockDisplayInsetsController, mMockImeController, mMockSyncQueue) { + mMockDisplayInsetsController, mMockImeController, mMockSyncQueue, mMockExecutor) { @Override SizeCompatUILayout createLayout(Context context, int displayId, int taskId, Configuration taskConfig, ShellTaskOrganizer.TaskListener taskListener) { @@ -106,19 +109,17 @@ public class SizeCompatUIControllerTest extends ShellTestCase { final Configuration taskConfig = new Configuration(); // Verify that the restart button is added with non-null size compat info. - mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, - mMockTaskListener); + mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); verify(mController).createLayout(any(), eq(DISPLAY_ID), eq(TASK_ID), eq(taskConfig), eq(mMockTaskListener)); // Verify that the restart button is updated with non-null new size compat info. final Configuration newTaskConfig = new Configuration(); - mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, newTaskConfig, - mMockTaskListener); + mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, newTaskConfig, mMockTaskListener); verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener, - false /* isImeShowing */); + true /* show */); // Verify that the restart button is removed with null size compat info. mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, null, mMockTaskListener); @@ -196,15 +197,90 @@ public class SizeCompatUIControllerTest extends ShellTestCase { @Test public void testChangeButtonVisibilityOnImeShowHide() { final Configuration taskConfig = new Configuration(); - mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, - mMockTaskListener); + mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + // Verify that the restart button is hidden after IME is showing. mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); - verify(mMockLayout).updateImeVisibility(true); + verify(mMockLayout).updateVisibility(false); + + // Verify button remains hidden while IME is showing. + mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener, + false /* show */); + + // Verify button is shown after IME is hidden. mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); - verify(mMockLayout).updateImeVisibility(false); + verify(mMockLayout).updateVisibility(true); + } + + @Test + public void testChangeButtonVisibilityOnKeyguardOccludedChanged() { + final Configuration taskConfig = new Configuration(); + mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + + // Verify that the restart button is hidden after keyguard becomes occluded. + mController.onKeyguardOccludedChanged(true); + + verify(mMockLayout).updateVisibility(false); + + // Verify button remains hidden while keyguard is occluded. + mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + + verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener, + false /* show */); + + // Verify button is shown after keyguard becomes not occluded. + mController.onKeyguardOccludedChanged(false); + + verify(mMockLayout).updateVisibility(true); + } + + @Test + public void testButtonRemainsHiddenOnKeyguardOccludedFalseWhenImeIsShowing() { + final Configuration taskConfig = new Configuration(); + mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + + mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); + mController.onKeyguardOccludedChanged(true); + + verify(mMockLayout, times(2)).updateVisibility(false); + + clearInvocations(mMockLayout); + + // Verify button remains hidden after keyguard becomes not occluded since IME is showing. + mController.onKeyguardOccludedChanged(false); + + verify(mMockLayout).updateVisibility(false); + + // Verify button is shown after IME is not showing. + mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); + + verify(mMockLayout).updateVisibility(true); + } + + @Test + public void testButtonRemainsHiddenOnImeHideWhenKeyguardIsOccluded() { + final Configuration taskConfig = new Configuration(); + mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + + mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); + mController.onKeyguardOccludedChanged(true); + + verify(mMockLayout, times(2)).updateVisibility(false); + + clearInvocations(mMockLayout); + + // Verify button remains hidden after IME is hidden since keyguard is occluded. + mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); + + verify(mMockLayout).updateVisibility(false); + + // Verify button is shown after keyguard becomes not occluded. + mController.onKeyguardOccludedChanged(false); + + verify(mMockLayout).updateVisibility(true); } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java index 2ba603c8eda8..eb9305b2e995 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java @@ -96,8 +96,8 @@ public class SizeCompatUILayoutTest extends ShellTestCase { @Test public void testCreateSizeCompatButton() { - // Not create button if IME is showing. - mLayout.createSizeCompatButton(true /* isImeShowing */); + // Not create button if show is false. + mLayout.createSizeCompatButton(false /* show */); verify(mLayout.mButtonWindowManager, never()).createSizeCompatButton(); assertNull(mLayout.mButton); @@ -106,7 +106,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase { // Not create hint popup. mLayout.mShouldShowHint = false; - mLayout.createSizeCompatButton(false /* isImeShowing */); + mLayout.createSizeCompatButton(true /* show */); verify(mLayout.mButtonWindowManager).createSizeCompatButton(); assertNotNull(mLayout.mButton); @@ -116,7 +116,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase { // Create hint popup. mLayout.release(); mLayout.mShouldShowHint = true; - mLayout.createSizeCompatButton(false /* isImeShowing */); + mLayout.createSizeCompatButton(true /* show */); verify(mLayout.mButtonWindowManager, times(2)).createSizeCompatButton(); assertNotNull(mLayout.mButton); @@ -128,7 +128,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase { @Test public void testRelease() { - mLayout.createSizeCompatButton(false /* isImeShowing */); + mLayout.createSizeCompatButton(true /* show */); final SizeCompatUIWindowManager hintWindowManager = mLayout.mHintWindowManager; mLayout.release(); @@ -142,12 +142,11 @@ public class SizeCompatUILayoutTest extends ShellTestCase { @Test public void testUpdateSizeCompatInfo() { - mLayout.createSizeCompatButton(false /* isImeShowing */); + mLayout.createSizeCompatButton(true /* show */); // No diff clearInvocations(mLayout); - mLayout.updateSizeCompatInfo(mTaskConfig, mTaskListener, - false /* isImeShowing */); + mLayout.updateSizeCompatInfo(mTaskConfig, mTaskListener, true /* show */); verify(mLayout, never()).updateButtonSurfacePosition(); verify(mLayout, never()).release(); @@ -158,7 +157,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase { final ShellTaskOrganizer.TaskListener newTaskListener = mock( ShellTaskOrganizer.TaskListener.class); mLayout.updateSizeCompatInfo(mTaskConfig, newTaskListener, - false /* isImeShowing */); + true /* show */); verify(mLayout).release(); verify(mLayout).createSizeCompatButton(anyBoolean()); @@ -168,7 +167,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase { final Configuration newTaskConfiguration = new Configuration(); newTaskConfiguration.windowConfiguration.setBounds(new Rect(0, 1000, 0, 2000)); mLayout.updateSizeCompatInfo(newTaskConfiguration, newTaskListener, - false /* isImeShowing */); + true /* show */); verify(mLayout).updateButtonSurfacePosition(); verify(mLayout).updateHintSurfacePosition(); @@ -220,24 +219,24 @@ public class SizeCompatUILayoutTest extends ShellTestCase { } @Test - public void testUpdateImeVisibility() { + public void testUpdateVisibility() { // Create button if it is not created. mLayout.mButton = null; - mLayout.updateImeVisibility(false /* isImeShowing */); + mLayout.updateVisibility(true /* show */); - verify(mLayout).createSizeCompatButton(false /* isImeShowing */); + verify(mLayout).createSizeCompatButton(true /* show */); - // Hide button if ime is shown. + // Hide button. clearInvocations(mLayout); doReturn(View.VISIBLE).when(mButton).getVisibility(); - mLayout.updateImeVisibility(true /* isImeShowing */); + mLayout.updateVisibility(false /* show */); verify(mLayout, never()).createSizeCompatButton(anyBoolean()); verify(mButton).setVisibility(View.GONE); - // Show button if ime is not shown. + // Show button. doReturn(View.GONE).when(mButton).getVisibility(); - mLayout.updateImeVisibility(false /* isImeShowing */); + mLayout.updateVisibility(true /* show */); verify(mLayout, never()).createSizeCompatButton(anyBoolean()); verify(mButton).setVisibility(View.VISIBLE); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java index ad65c046be65..ef14d84c6a09 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java @@ -19,11 +19,14 @@ package com.android.wm.shell.splitscreen; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.view.Display.DEFAULT_DISPLAY; -import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN; +import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE; +import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; @@ -49,7 +52,6 @@ import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.split.SplitLayout; -import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.transition.Transitions; import org.junit.Before; @@ -110,12 +112,39 @@ public class StageCoordinatorTests extends ShellTestCase { } @Test - public void testMoveToSideStage() { + public void testMoveToStage() { final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build(); - mStageCoordinator.moveToSideStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT); + mStageCoordinator.moveToStage(task, STAGE_TYPE_MAIN, SPLIT_POSITION_BOTTOM_OR_RIGHT, + new WindowContainerTransaction()); + verify(mMainStage).addTask(eq(task), any(WindowContainerTransaction.class)); + assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition()); + mStageCoordinator.moveToStage(task, STAGE_TYPE_SIDE, SPLIT_POSITION_BOTTOM_OR_RIGHT, + new WindowContainerTransaction()); verify(mSideStage).addTask(eq(task), any(WindowContainerTransaction.class)); + assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition()); + } + + @Test + public void testMoveToUndefinedStage() { + final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build(); + + // Verify move to undefined stage while split screen not activated moves task to side stage. + when(mMainStage.isActive()).thenReturn(false); + mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null); + mStageCoordinator.moveToStage(task, STAGE_TYPE_UNDEFINED, SPLIT_POSITION_BOTTOM_OR_RIGHT, + new WindowContainerTransaction()); + verify(mSideStage).addTask(eq(task), any(WindowContainerTransaction.class)); + assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition()); + + // Verify move to undefined stage after split screen activated moves task based on position. + when(mMainStage.isActive()).thenReturn(true); + assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition()); + mStageCoordinator.moveToStage(task, STAGE_TYPE_UNDEFINED, SPLIT_POSITION_TOP_OR_LEFT, + new WindowContainerTransaction()); + verify(mMainStage).addTask(eq(task), any(WindowContainerTransaction.class)); + assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition()); } @Test diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp index 5aad821ad59f..6fc251dc815c 100644 --- a/libs/hwui/WebViewFunctorManager.cpp +++ b/libs/hwui/WebViewFunctorManager.cpp @@ -118,6 +118,24 @@ void WebViewFunctor::onRemovedFromTree() { } } +bool WebViewFunctor::prepareRootSurfaceControl() { + if (!Properties::enableWebViewOverlays) return false; + + renderthread::CanvasContext* activeContext = renderthread::CanvasContext::getActiveContext(); + if (!activeContext) return false; + + ASurfaceControl* rootSurfaceControl = activeContext->getSurfaceControl(); + if (!rootSurfaceControl) return false; + + int32_t rgid = activeContext->getSurfaceControlGenerationId(); + if (mParentSurfaceControlGenerationId != rgid) { + reparentSurfaceControl(rootSurfaceControl); + mParentSurfaceControlGenerationId = rgid; + } + + return true; +} + void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) { ATRACE_NAME("WebViewFunctor::drawGl"); if (!mHasContext) { @@ -131,20 +149,8 @@ void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) { .mergeTransaction = currentFunctor.mergeTransaction, }; - if (Properties::enableWebViewOverlays && !drawInfo.isLayer) { - renderthread::CanvasContext* activeContext = - renderthread::CanvasContext::getActiveContext(); - if (activeContext != nullptr) { - ASurfaceControl* rootSurfaceControl = activeContext->getSurfaceControl(); - if (rootSurfaceControl) { - overlayParams.overlaysMode = OverlaysMode::Enabled; - int32_t rgid = activeContext->getSurfaceControlGenerationId(); - if (mParentSurfaceControlGenerationId != rgid) { - reparentSurfaceControl(rootSurfaceControl); - mParentSurfaceControlGenerationId = rgid; - } - } - } + if (!drawInfo.isLayer && prepareRootSurfaceControl()) { + overlayParams.overlaysMode = OverlaysMode::Enabled; } mCallbacks.gles.draw(mFunctor, mData, drawInfo, overlayParams); @@ -170,7 +176,10 @@ void WebViewFunctor::drawVk(const VkFunctorDrawParams& params) { .mergeTransaction = currentFunctor.mergeTransaction, }; - // TODO, enable surface control once offscreen mode figured out + if (!params.is_layer && prepareRootSurfaceControl()) { + overlayParams.overlaysMode = OverlaysMode::Enabled; + } + mCallbacks.vk.draw(mFunctor, mData, params, overlayParams); } diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h index f28f310993ec..0a02f2d4b720 100644 --- a/libs/hwui/WebViewFunctorManager.h +++ b/libs/hwui/WebViewFunctorManager.h @@ -88,6 +88,7 @@ public: } private: + bool prepareRootSurfaceControl(); void reparentSurfaceControl(ASurfaceControl* parent); private: diff --git a/libs/hwui/jni/text/MeasuredText.cpp b/libs/hwui/jni/text/MeasuredText.cpp index 7793746ee285..bd9bd7121f8a 100644 --- a/libs/hwui/jni/text/MeasuredText.cpp +++ b/libs/hwui/jni/text/MeasuredText.cpp @@ -80,15 +80,17 @@ static void nAddReplacementRun(JNIEnv* /* unused */, jclass /* unused */, jlong } // Regular JNI -static jlong nBuildMeasuredText(JNIEnv* env, jclass /* unused */, jlong builderPtr, - jlong hintPtr, jcharArray javaText, jboolean computeHyphenation, - jboolean computeLayout) { +static jlong nBuildMeasuredText(JNIEnv* env, jclass /* unused */, jlong builderPtr, jlong hintPtr, + jcharArray javaText, jboolean computeHyphenation, + jboolean computeLayout, jboolean fastHyphenationMode) { ScopedCharArrayRO text(env, javaText); const minikin::U16StringPiece textBuffer(text.get(), text.size()); // Pass the ownership to Java. - return toJLong(toBuilder(builderPtr)->build(textBuffer, computeHyphenation, computeLayout, - toMeasuredParagraph(hintPtr)).release()); + return toJLong(toBuilder(builderPtr) + ->build(textBuffer, computeHyphenation, computeLayout, + fastHyphenationMode, toMeasuredParagraph(hintPtr)) + .release()); } // Regular JNI @@ -140,12 +142,12 @@ static jint nGetMemoryUsage(CRITICAL_JNI_PARAMS_COMMA jlong ptr) { } static const JNINativeMethod gMTBuilderMethods[] = { - // MeasuredParagraphBuilder native functions. - {"nInitBuilder", "()J", (void*) nInitBuilder}, - {"nAddStyleRun", "(JJIIZ)V", (void*) nAddStyleRun}, - {"nAddReplacementRun", "(JJIIF)V", (void*) nAddReplacementRun}, - {"nBuildMeasuredText", "(JJ[CZZ)J", (void*) nBuildMeasuredText}, - {"nFreeBuilder", "(J)V", (void*) nFreeBuilder}, + // MeasuredParagraphBuilder native functions. + {"nInitBuilder", "()J", (void*)nInitBuilder}, + {"nAddStyleRun", "(JJIIZ)V", (void*)nAddStyleRun}, + {"nAddReplacementRun", "(JJIIF)V", (void*)nAddReplacementRun}, + {"nBuildMeasuredText", "(JJ[CZZZ)J", (void*)nBuildMeasuredText}, + {"nFreeBuilder", "(J)V", (void*)nFreeBuilder}, }; static const JNINativeMethod gMTMethods[] = { diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp index 8abf4534a04c..e6ef95b9cf91 100644 --- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp +++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp @@ -72,6 +72,7 @@ void VkFunctorDrawHandler::draw(const GrBackendDrawableInfo& info) { .clip_top = mClip.fTop, .clip_right = mClip.fRight, .clip_bottom = mClip.fBottom, + .is_layer = !vulkan_info.fFromSwapchainOrAndroidWindow, }; mat4.getColMajor(¶ms.transform[0]); params.secondary_command_buffer = vulkan_info.fSecondaryCommandBuffer; diff --git a/libs/hwui/private/hwui/DrawVkInfo.h b/libs/hwui/private/hwui/DrawVkInfo.h index 4ae0f5a0a2e5..5c596576df4e 100644 --- a/libs/hwui/private/hwui/DrawVkInfo.h +++ b/libs/hwui/private/hwui/DrawVkInfo.h @@ -68,6 +68,9 @@ struct VkFunctorDrawParams { int clip_top; int clip_right; int clip_bottom; + + // Input: Whether destination surface is offscreen surface. + bool is_layer; }; } // namespace uirenderer diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp index fe9a30a59870..611a4d9c8f2c 100644 --- a/libs/hwui/renderthread/VulkanSurface.cpp +++ b/libs/hwui/renderthread/VulkanSurface.cpp @@ -426,7 +426,7 @@ VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() { if (bufferInfo->skSurface.get() == nullptr) { bufferInfo->skSurface = SkSurface::MakeFromAHardwareBuffer( mGrContext, ANativeWindowBuffer_getHardwareBuffer(bufferInfo->buffer.get()), - kTopLeft_GrSurfaceOrigin, mWindowInfo.colorspace, nullptr); + kTopLeft_GrSurfaceOrigin, mWindowInfo.colorspace, nullptr, /*from_window=*/true); if (bufferInfo->skSurface.get() == nullptr) { ALOGE("SkSurface::MakeFromAHardwareBuffer failed"); mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp index da21438bafd1..2b809eab4ae4 100644 --- a/libs/input/SpriteController.cpp +++ b/libs/input/SpriteController.cpp @@ -70,8 +70,8 @@ void SpriteController::closeTransaction() { } void SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) { - bool wasEmpty = mLocked.invalidatedSprites.isEmpty(); - mLocked.invalidatedSprites.push(sprite); + bool wasEmpty = mLocked.invalidatedSprites.empty(); + mLocked.invalidatedSprites.push_back(sprite); if (wasEmpty) { if (mLocked.transactionNestingCount != 0) { mLocked.deferredSpriteUpdate = true; @@ -82,8 +82,8 @@ void SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) { } void SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) { - bool wasEmpty = mLocked.disposedSurfaces.isEmpty(); - mLocked.disposedSurfaces.push(surfaceControl); + bool wasEmpty = mLocked.disposedSurfaces.empty(); + mLocked.disposedSurfaces.push_back(surfaceControl); if (wasEmpty) { mLooper->sendMessage(mHandler, Message(MSG_DISPOSE_SURFACES)); } @@ -113,7 +113,7 @@ void SpriteController::doUpdateSprites() { numSprites = mLocked.invalidatedSprites.size(); for (size_t i = 0; i < numSprites; i++) { - const sp<SpriteImpl>& sprite = mLocked.invalidatedSprites.itemAt(i); + const sp<SpriteImpl>& sprite = mLocked.invalidatedSprites[i]; updates.push(SpriteUpdate(sprite, sprite->getStateLocked())); sprite->resetDirtyLocked(); @@ -305,7 +305,7 @@ void SpriteController::doUpdateSprites() { void SpriteController::doDisposeSurfaces() { // Collect disposed surfaces. - Vector<sp<SurfaceControl> > disposedSurfaces; + std::vector<sp<SurfaceControl>> disposedSurfaces; { // acquire lock AutoMutex _l(mLock); @@ -313,6 +313,13 @@ void SpriteController::doDisposeSurfaces() { mLocked.disposedSurfaces.clear(); } // release lock + // Remove the parent from all surfaces. + SurfaceComposerClient::Transaction t; + for (const sp<SurfaceControl>& sc : disposedSurfaces) { + t.reparent(sc, nullptr); + } + t.apply(); + // Release the last reference to each surface outside of the lock. // We don't want the surfaces to be deleted while we are holding our lock. disposedSurfaces.clear(); diff --git a/libs/input/SpriteController.h b/libs/input/SpriteController.h index 2a80d9579711..2e9cb9685c46 100644 --- a/libs/input/SpriteController.h +++ b/libs/input/SpriteController.h @@ -251,8 +251,8 @@ private: sp<SurfaceComposerClient> mSurfaceComposerClient; struct Locked { - Vector<sp<SpriteImpl> > invalidatedSprites; - Vector<sp<SurfaceControl> > disposedSurfaces; + std::vector<sp<SpriteImpl>> invalidatedSprites; + std::vector<sp<SurfaceControl>> disposedSurfaces; uint32_t transactionNestingCount; bool deferredSpriteUpdate; } mLocked; // guarded by mLock diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 49f1f8430de9..2916b0156055 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -40,6 +40,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.media.AudioAttributes.AttributeSystemUsage; +import android.media.CallbackUtil.ListenerInfo; import android.media.audiopolicy.AudioPolicy; import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener; import android.media.audiopolicy.AudioProductStrategy; @@ -2900,77 +2901,31 @@ public class AudioManager { * List is lazy-initialized on first registration */ @GuardedBy("mModeListenerLock") - private @Nullable ArrayList<ModeListenerInfo> mModeListeners; + private @Nullable ArrayList<ListenerInfo<OnModeChangedListener>> mModeListeners; @GuardedBy("mModeListenerLock") private ModeDispatcherStub mModeDispatcherStub; - private final class ModeDispatcherStub - extends IAudioModeDispatcher.Stub { + private final class ModeDispatcherStub extends IAudioModeDispatcher.Stub { - @Override - public void dispatchAudioModeChanged(int mode) { - // make a shallow copy of listeners so callback is not executed under lock - final ArrayList<ModeListenerInfo> modeListeners; - synchronized (mModeListenerLock) { - if (mModeListeners == null || mModeListeners.size() == 0) { - return; - } - modeListeners = (ArrayList<ModeListenerInfo>) mModeListeners.clone(); - } - final long ident = Binder.clearCallingIdentity(); + public void register(boolean register) { try { - for (ModeListenerInfo info : modeListeners) { - info.mExecutor.execute(() -> - info.mListener.onModeChanged(mode)); + if (register) { + getService().registerModeDispatcher(this); + } else { + getService().unregisterModeDispatcher(this); } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - - private static class ModeListenerInfo { - final @NonNull OnModeChangedListener mListener; - final @NonNull Executor mExecutor; - - ModeListenerInfo(OnModeChangedListener listener, Executor exe) { - mListener = listener; - mExecutor = exe; - } - } - - @GuardedBy("mModeListenerLock") - private boolean hasModeListener(OnModeChangedListener listener) { - return getModeListenerInfo(listener) != null; - } - - @GuardedBy("mModeListenerLock") - private @Nullable ModeListenerInfo getModeListenerInfo( - OnModeChangedListener listener) { - if (mModeListeners == null) { - return null; - } - for (ModeListenerInfo info : mModeListeners) { - if (info.mListener == listener) { - return info; + } catch (RemoteException e) { + e.rethrowFromSystemServer(); } } - return null; - } - - @GuardedBy("mModeListenerLock") - /** - * @return true if the listener was removed from the list - */ - private boolean removeModeListener(OnModeChangedListener listener) { - final ModeListenerInfo infoToRemove = getModeListenerInfo(listener); - if (infoToRemove != null) { - mModeListeners.remove(infoToRemove); - return true; + @Override + @SuppressLint("GuardedBy") // lock applied inside callListeners method + public void dispatchAudioModeChanged(int mode) { + CallbackUtil.callListeners(mModeListeners, mModeListenerLock, + (listener) -> listener.onModeChanged(mode)); } - return false; } /** @@ -2982,30 +2937,14 @@ public class AudioManager { public void addOnModeChangedListener( @NonNull @CallbackExecutor Executor executor, @NonNull OnModeChangedListener listener) { - Objects.requireNonNull(executor); - Objects.requireNonNull(listener); synchronized (mModeListenerLock) { - if (hasModeListener(listener)) { - throw new IllegalArgumentException("attempt to call addOnModeChangedListener() " - + "on a previously registered listener"); - } - // lazy initialization of the list of strategy-preferred device listener - if (mModeListeners == null) { - mModeListeners = new ArrayList<>(); - } - final int oldCbCount = mModeListeners.size(); - mModeListeners.add(new ModeListenerInfo(listener, executor)); - if (oldCbCount == 0) { - // register binder for callbacks - if (mModeDispatcherStub == null) { - mModeDispatcherStub = new ModeDispatcherStub(); - } - try { - getService().registerModeDispatcher(mModeDispatcherStub); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + final Pair<ArrayList<ListenerInfo<OnModeChangedListener>>, ModeDispatcherStub> res = + CallbackUtil.addListener("addOnModeChangedListener", + executor, listener, mModeListeners, mModeDispatcherStub, + () -> new ModeDispatcherStub(), + stub -> stub.register(true)); + mModeListeners = res.first; + mModeDispatcherStub = res.second; } } @@ -3015,23 +2954,13 @@ public class AudioManager { * @param listener */ public void removeOnModeChangedListener(@NonNull OnModeChangedListener listener) { - Objects.requireNonNull(listener); synchronized (mModeListenerLock) { - if (!removeModeListener(listener)) { - throw new IllegalArgumentException("attempt to call removeOnModeChangedListener() " - + "on an unregistered listener"); - } - if (mModeListeners.size() == 0) { - // unregister binder for callbacks - try { - getService().unregisterModeDispatcher(mModeDispatcherStub); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } finally { - mModeDispatcherStub = null; - mModeListeners = null; - } - } + final Pair<ArrayList<ListenerInfo<OnModeChangedListener>>, ModeDispatcherStub> res = + CallbackUtil.removeListener("removeOnModeChangedListener", + listener, mModeListeners, mModeDispatcherStub, + stub -> stub.register(false)); + mModeListeners = res.first; + mModeDispatcherStub = res.second; } } @@ -7646,31 +7575,15 @@ public class AudioManager { public void addOnCommunicationDeviceChangedListener( @NonNull @CallbackExecutor Executor executor, @NonNull OnCommunicationDeviceChangedListener listener) { - Objects.requireNonNull(executor); - Objects.requireNonNull(listener); synchronized (mCommDevListenerLock) { - if (hasCommDevListener(listener)) { - throw new IllegalArgumentException( - "attempt to call addOnCommunicationDeviceChangedListener() " - + "on a previously registered listener"); - } - // lazy initialization of the list of strategy-preferred device listener - if (mCommDevListeners == null) { - mCommDevListeners = new ArrayList<>(); - } - final int oldCbCount = mCommDevListeners.size(); - mCommDevListeners.add(new CommDevListenerInfo(listener, executor)); - if (oldCbCount == 0 && mCommDevListeners.size() > 0) { - // register binder for callbacks - if (mCommDevDispatcherStub == null) { - mCommDevDispatcherStub = new CommunicationDeviceDispatcherStub(); - } - try { - getService().registerCommunicationDeviceDispatcher(mCommDevDispatcherStub); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + final Pair<ArrayList<ListenerInfo<OnCommunicationDeviceChangedListener>>, + CommunicationDeviceDispatcherStub> res = + CallbackUtil.addListener("addOnCommunicationDeviceChangedListener", + executor, listener, mCommDevListeners, mCommDevDispatcherStub, + () -> new CommunicationDeviceDispatcherStub(), + stub -> stub.register(true)); + mCommDevListeners = res.first; + mCommDevDispatcherStub = res.second; } } @@ -7681,25 +7594,14 @@ public class AudioManager { */ public void removeOnCommunicationDeviceChangedListener( @NonNull OnCommunicationDeviceChangedListener listener) { - Objects.requireNonNull(listener); synchronized (mCommDevListenerLock) { - if (!removeCommDevListener(listener)) { - throw new IllegalArgumentException( - "attempt to call removeOnCommunicationDeviceChangedListener() " - + "on an unregistered listener"); - } - if (mCommDevListeners.size() == 0) { - // unregister binder for callbacks - try { - getService().unregisterCommunicationDeviceDispatcher( - mCommDevDispatcherStub); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } finally { - mCommDevDispatcherStub = null; - mCommDevListeners = null; - } - } + final Pair<ArrayList<ListenerInfo<OnCommunicationDeviceChangedListener>>, + CommunicationDeviceDispatcherStub> res = + CallbackUtil.removeListener("removeOnCommunicationDeviceChangedListener", + listener, mCommDevListeners, mCommDevDispatcherStub, + stub -> stub.register(false)); + mCommDevListeners = res.first; + mCommDevDispatcherStub = res.second; } } @@ -7709,17 +7611,8 @@ public class AudioManager { * List is lazy-initialized on first registration */ @GuardedBy("mCommDevListenerLock") - private @Nullable ArrayList<CommDevListenerInfo> mCommDevListeners; - - private static class CommDevListenerInfo { - final @NonNull OnCommunicationDeviceChangedListener mListener; - final @NonNull Executor mExecutor; - - CommDevListenerInfo(OnCommunicationDeviceChangedListener listener, Executor exe) { - mListener = listener; - mExecutor = exe; - } - } + private @Nullable + ArrayList<ListenerInfo<OnCommunicationDeviceChangedListener>> mCommDevListeners; @GuardedBy("mCommDevListenerLock") private CommunicationDeviceDispatcherStub mCommDevDispatcherStub; @@ -7727,59 +7620,25 @@ public class AudioManager { private final class CommunicationDeviceDispatcherStub extends ICommunicationDeviceDispatcher.Stub { - @Override - public void dispatchCommunicationDeviceChanged(int portId) { - // make a shallow copy of listeners so callback is not executed under lock - final ArrayList<CommDevListenerInfo> commDevListeners; - synchronized (mCommDevListenerLock) { - if (mCommDevListeners == null || mCommDevListeners.size() == 0) { - return; - } - commDevListeners = (ArrayList<CommDevListenerInfo>) mCommDevListeners.clone(); - } - AudioDeviceInfo device = getDeviceForPortId(portId, GET_DEVICES_OUTPUTS); - final long ident = Binder.clearCallingIdentity(); + public void register(boolean register) { try { - for (CommDevListenerInfo info : commDevListeners) { - info.mExecutor.execute(() -> - info.mListener.onCommunicationDeviceChanged(device)); + if (register) { + getService().registerCommunicationDeviceDispatcher(this); + } else { + getService().unregisterCommunicationDeviceDispatcher(this); } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - - @GuardedBy("mCommDevListenerLock") - private @Nullable CommDevListenerInfo getCommDevListenerInfo( - OnCommunicationDeviceChangedListener listener) { - if (mCommDevListeners == null) { - return null; - } - for (CommDevListenerInfo info : mCommDevListeners) { - if (info.mListener == listener) { - return info; + } catch (RemoteException e) { + e.rethrowFromSystemServer(); } } - return null; - } - - @GuardedBy("mCommDevListenerLock") - private boolean hasCommDevListener(OnCommunicationDeviceChangedListener listener) { - return getCommDevListenerInfo(listener) != null; - } - @GuardedBy("mCommDevListenerLock") - /** - * @return true if the listener was removed from the list - */ - private boolean removeCommDevListener(OnCommunicationDeviceChangedListener listener) { - final CommDevListenerInfo infoToRemove = getCommDevListenerInfo(listener); - if (infoToRemove != null) { - mCommDevListeners.remove(infoToRemove); - return true; + @Override + @SuppressLint("GuardedBy") // lock applied inside callListeners method + public void dispatchCommunicationDeviceChanged(int portId) { + AudioDeviceInfo device = getDeviceForPortId(portId, GET_DEVICES_OUTPUTS); + CallbackUtil.callListeners(mCommDevListeners, mCommDevListenerLock, + (listener) -> listener.onCommunicationDeviceChanged(device)); } - return false; } //--------------------------------------------------------- @@ -7838,4 +7697,4 @@ public class AudioManager { return mHandler; } } -} +}
\ No newline at end of file diff --git a/media/java/android/media/CallbackUtil.java b/media/java/android/media/CallbackUtil.java new file mode 100644 index 000000000000..ac39317ed1d5 --- /dev/null +++ b/media/java/android/media/CallbackUtil.java @@ -0,0 +1,224 @@ +/* + * 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 android.media; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.media.permission.ClearCallingIdentityContext; +import android.media.permission.SafeCloseable; +import android.util.Log; +import android.util.Pair; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.concurrent.Executor; + +/** + * @hide + * A utility class to implement callback listeners and their management. + * This is meant to be used for lazily-initialized listener lists and stubs for event reception, + * typically received from server (e.g. AudioService). + */ + +/*package*/ class CallbackUtil { + + private static final String TAG = "CallbackUtil"; + + /** + * Container class to store a listener and associated Executor + * @param <T> the type of the listener + */ + static class ListenerInfo<T> { + final @NonNull T mListener; + final @NonNull Executor mExecutor; + + ListenerInfo(@NonNull T listener, @NonNull Executor exe) { + mListener = listener; + mExecutor = exe; + } + } + + /** + * Finds the listener information (listener + Executor) in a given list of listeners + * @param listener the listener to find + * @param listeners the list of listener informations, can be null if not instantiated yet + * @param <T> the type of the listeners + * @return null if the listener is not in the given list of listener informations + */ + static <T> @Nullable ListenerInfo<T> getListenerInfo( + @NonNull T listener, @Nullable ArrayList<ListenerInfo<T>> listeners) { + if (listeners == null) { + return null; + } + for (ListenerInfo<T> info : listeners) { + if (info.mListener == listener) { + return info; + } + } + return null; + } + + /** + * Returns true if the given listener is present in the list of listener informations + * @param listener the listener to find + * @param listeners the list of listener informations, can be null if not instantiated yet + * @param <T> the type of the listeners + * @return true if the listener is in the list + */ + static <T> boolean hasListener(@NonNull T listener, + @Nullable ArrayList<ListenerInfo<T>> listeners) { + return getListenerInfo(listener, listeners) != null; + } + + /** + * Removes the given listener from the list of listener informations + * @param listener the listener to remove + * @param listeners the list of listener informations, can be null if not instantiated yet + * @param <T> the type of the listeners + * @return true if the listener was found and removed from the list, false otherwise + */ + static <T> boolean removeListener(@NonNull T listener, + @Nullable ArrayList<ListenerInfo<T>> listeners) { + final ListenerInfo<T> infoToRemove = getListenerInfo(listener, listeners); + if (infoToRemove != null) { + listeners.remove(infoToRemove); + return true; + } + return false; + } + + /** + * Adds a listener and associated Executor in the list of listeners. + * This method handles the lazy initialization of both the list of listeners and the stub + * used to receive the events that will be forwarded to the listener, see the returned pair + * for the updated references. + * @param methodName the name of the method calling this, for inclusion in the + * string in case of IllegalArgumentException + * @param executor the Executor for the listener + * @param listener the listener to add + * @param listeners the list of listener informations, can be null if not instantiated yet + * @param dispatchStub the stub that receives the events to be forwarded to the listeners, + * can be null if not instantiated yet + * @param newStub the function to create a new stub if needed + * @param registerStub the function for the stub registration if needed + * @param <T> the type of the listener interface + * @param <S> the type of the event receiver stub + * @return a pair of the listener list and the event receiver stub which may have been + * initialized if needed (e.g. on the first ever addition of a listener) + */ + static <T, S> Pair<ArrayList<ListenerInfo<T>>, S> addListener(String methodName, + @NonNull Executor executor, + @NonNull T listener, + @Nullable ArrayList<ListenerInfo<T>> listeners, + @Nullable S dispatchStub, + @NonNull java.util.function.Supplier<S> newStub, + @NonNull java.util.function.Consumer<S> registerStub) { + Objects.requireNonNull(executor); + Objects.requireNonNull(listener); + + if (hasListener(listener, listeners)) { + throw new IllegalArgumentException("attempt to call " + methodName + + "on a previously registered listener"); + } + // lazy initialization of the list of strategy-preferred device listener + if (listeners == null) { + listeners = new ArrayList<>(); + } + if (listeners.size() == 0) { + // register binder for callbacks + if (dispatchStub == null) { + try { + dispatchStub = newStub.get(); + } catch (Exception e) { + Log.e(TAG, "Exception while creating stub in " + methodName, e); + return new Pair<>(null, null); + } + } + registerStub.accept(dispatchStub); + } + listeners.add(new ListenerInfo<T>(listener, executor)); + return new Pair(listeners, dispatchStub); + } + + /** + * Removes a listener from the list of listeners. + * This method handles the freeing of both the list of listeners and the stub + * used to receive the events that will be forwarded to the listener,see the returned pair + * for the updated references. + * @param methodName the name of the method calling this, for inclusion in the + * string in case of IllegalArgumentException + * @param listener the listener to remove + * @param listeners the list of listener informations, can be null if not instantiated yet + * @param dispatchStub the stub that receives the events to be forwarded to the listeners, + * can be null if not instantiated yet + * @param unregisterStub the function to unregister the stub if needed + * @param <T> the type of the listener interface + * @param <S> the type of the event receiver stub + * @return a pair of the listener list and the event receiver stub which may have been + * changed if needed (e.g. on the removal of the last listener) + */ + static <T, S> Pair<ArrayList<ListenerInfo<T>>, S> removeListener(String methodName, + @NonNull T listener, + @Nullable ArrayList<ListenerInfo<T>> listeners, + @Nullable S dispatchStub, + @NonNull java.util.function.Consumer<S> unregisterStub) { + Objects.requireNonNull(listener); + + if (!removeListener(listener, listeners)) { + throw new IllegalArgumentException("attempt to call " + methodName + + "on an unregistered listener"); + } + if (listeners.size() == 0) { + unregisterStub.accept(dispatchStub); + return new Pair<>(null, null); + } else { + return new Pair<>(listeners, dispatchStub); + } + } + + interface CallbackMethod<T> { + void callbackMethod(T listener); + } + + /** + * Exercise the callback of the listeners + * @param listeners the list of listeners + * @param listenerLock the lock guarding the list of listeners + * @param callback the function to call for each listener + * @param <T> the type of the listener interface + */ + static <T> void callListeners( + @Nullable ArrayList<ListenerInfo<T>> listeners, + @NonNull Object listenerLock, + @NonNull CallbackMethod<T> callback) { + Objects.requireNonNull(listenerLock); + // make a shallow copy of listeners so callback is not executed under lock + final ArrayList<ListenerInfo<T>> listenersShallowCopy; + synchronized (listenerLock) { + if (listeners == null || listeners.size() == 0) { + return; + } + listenersShallowCopy = (ArrayList<ListenerInfo<T>>) listeners.clone(); + } + try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { + for (ListenerInfo<T> info : listenersShallowCopy) { + info.mExecutor.execute(() -> callback.callbackMethod(info.mListener)); + } + } + + } +} diff --git a/media/java/android/media/Spatializer.java b/media/java/android/media/Spatializer.java index e6fff392c264..c0793ec58e53 100644 --- a/media/java/android/media/Spatializer.java +++ b/media/java/android/media/Spatializer.java @@ -22,11 +22,14 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; +import android.media.CallbackUtil.ListenerInfo; import android.media.permission.ClearCallingIdentityContext; import android.media.permission.SafeCloseable; import android.os.RemoteException; import android.util.Log; +import android.util.Pair; import com.android.internal.annotations.GuardedBy; @@ -373,32 +376,15 @@ public class Spatializer { public void addOnSpatializerStateChangedListener( @NonNull @CallbackExecutor Executor executor, @NonNull OnSpatializerStateChangedListener listener) { - Objects.requireNonNull(executor); - Objects.requireNonNull(listener); synchronized (mStateListenerLock) { - if (hasSpatializerStateListener(listener)) { - throw new IllegalArgumentException( - "Called addOnSpatializerStateChangedListener() " - + "on a previously registered listener"); - } - // lazy initialization of the list of strategy-preferred device listener - if (mStateListeners == null) { - mStateListeners = new ArrayList<>(); - } - mStateListeners.add(new StateListenerInfo(listener, executor)); - if (mStateListeners.size() == 1) { - // register binder for callbacks - if (mInfoDispatcherStub == null) { - mInfoDispatcherStub = - new SpatializerInfoDispatcherStub(); - } - try { - mAm.getService().registerSpatializerCallback( - mInfoDispatcherStub); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + final Pair<ArrayList<ListenerInfo<OnSpatializerStateChangedListener>>, + SpatializerInfoDispatcherStub> res = + CallbackUtil.addListener("addOnSpatializerStateChangedListener", + executor, listener, mStateListeners, mInfoDispatcherStub, + () -> new SpatializerInfoDispatcherStub(), + stub -> stub.register(true)); + mStateListeners = res.first; + mInfoDispatcherStub = res.second; } } @@ -410,24 +396,14 @@ public class Spatializer { */ public void removeOnSpatializerStateChangedListener( @NonNull OnSpatializerStateChangedListener listener) { - Objects.requireNonNull(listener); synchronized (mStateListenerLock) { - if (!removeStateListener(listener)) { - throw new IllegalArgumentException( - "Called removeOnSpatializerStateChangedListener() " - + "on an unregistered listener"); - } - if (mStateListeners.size() == 0) { - // unregister binder for callbacks - try { - mAm.getService().unregisterSpatializerCallback(mInfoDispatcherStub); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } finally { - mInfoDispatcherStub = null; - mStateListeners = null; - } - } + final Pair<ArrayList<ListenerInfo<OnSpatializerStateChangedListener>>, + SpatializerInfoDispatcherStub> res = + CallbackUtil.removeListener("removeOnSpatializerStateChangedListener", + listener, mStateListeners, mInfoDispatcherStub, + stub -> stub.register(false)); + mStateListeners = res.first; + mInfoDispatcherStub = res.second; } } @@ -489,91 +465,39 @@ public class Spatializer { * List is lazy-initialized on first registration */ @GuardedBy("mStateListenerLock") - private @Nullable ArrayList<StateListenerInfo> mStateListeners; + private @Nullable ArrayList<ListenerInfo<OnSpatializerStateChangedListener>> mStateListeners; @GuardedBy("mStateListenerLock") private @Nullable SpatializerInfoDispatcherStub mInfoDispatcherStub; private final class SpatializerInfoDispatcherStub extends ISpatializerCallback.Stub { - @Override - public void dispatchSpatializerEnabledChanged(boolean enabled) { - // make a shallow copy of listeners so callback is not executed under lock - final ArrayList<StateListenerInfo> stateListeners; - synchronized (mStateListenerLock) { - if (mStateListeners == null || mStateListeners.size() == 0) { - return; - } - stateListeners = (ArrayList<StateListenerInfo>) mStateListeners.clone(); - } - try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { - for (StateListenerInfo info : stateListeners) { - info.mExecutor.execute(() -> - info.mListener.onSpatializerEnabledChanged(Spatializer.this, enabled)); + public void register(boolean register) { + try { + if (register) { + mAm.getService().registerSpatializerCallback(this); + } else { + mAm.getService().unregisterSpatializerCallback(this); } + } catch (RemoteException e) { + e.rethrowFromSystemServer(); } } @Override - public void dispatchSpatializerAvailableChanged(boolean available) { - // make a shallow copy of listeners so callback is not executed under lock - final ArrayList<StateListenerInfo> stateListeners; - synchronized (mStateListenerLock) { - if (mStateListeners == null || mStateListeners.size() == 0) { - return; - } - stateListeners = (ArrayList<StateListenerInfo>) mStateListeners.clone(); - } - try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { - for (StateListenerInfo info : stateListeners) { - info.mExecutor.execute(() -> - info.mListener.onSpatializerAvailableChanged( - Spatializer.this, available)); - } - } - } - } - - private static class StateListenerInfo { - final @NonNull OnSpatializerStateChangedListener mListener; - final @NonNull Executor mExecutor; - - StateListenerInfo(@NonNull OnSpatializerStateChangedListener listener, - @NonNull Executor exe) { - mListener = listener; - mExecutor = exe; - } - } - - @GuardedBy("mStateListenerLock") - private boolean hasSpatializerStateListener(OnSpatializerStateChangedListener listener) { - return getStateListenerInfo(listener) != null; - } - - @GuardedBy("mStateListenerLock") - private @Nullable StateListenerInfo getStateListenerInfo( - OnSpatializerStateChangedListener listener) { - if (mStateListeners == null) { - return null; - } - for (StateListenerInfo info : mStateListeners) { - if (info.mListener == listener) { - return info; - } + @SuppressLint("GuardedBy") // lock applied inside callListeners method + public void dispatchSpatializerEnabledChanged(boolean enabled) { + CallbackUtil.callListeners(mStateListeners, mStateListenerLock, + (listener) -> listener.onSpatializerEnabledChanged( + Spatializer.this, enabled)); } - return null; - } - @GuardedBy("mStateListenerLock") - /** - * @return true if the listener was removed from the list - */ - private boolean removeStateListener(OnSpatializerStateChangedListener listener) { - final StateListenerInfo infoToRemove = getStateListenerInfo(listener); - if (infoToRemove != null) { - mStateListeners.remove(infoToRemove); - return true; + @Override + @SuppressLint("GuardedBy") // lock applied inside callListeners method + public void dispatchSpatializerAvailableChanged(boolean available) { + CallbackUtil.callListeners(mStateListeners, mStateListenerLock, + (listener) -> listener.onSpatializerAvailableChanged( + Spatializer.this, available)); } - return false; } @@ -688,33 +612,15 @@ public class Spatializer { public void addOnHeadTrackingModeChangedListener( @NonNull @CallbackExecutor Executor executor, @NonNull OnHeadTrackingModeChangedListener listener) { - Objects.requireNonNull(executor); - Objects.requireNonNull(listener); synchronized (mHeadTrackingListenerLock) { - if (hasListener(listener, mHeadTrackingListeners)) { - throw new IllegalArgumentException( - "Called addOnHeadTrackingModeChangedListener() " - + "on a previously registered listener"); - } - // lazy initialization of the list of strategy-preferred device listener - if (mHeadTrackingListeners == null) { - mHeadTrackingListeners = new ArrayList<>(); - } - mHeadTrackingListeners.add( - new ListenerInfo<OnHeadTrackingModeChangedListener>(listener, executor)); - if (mHeadTrackingListeners.size() == 1) { - // register binder for callbacks - if (mHeadTrackingDispatcherStub == null) { - mHeadTrackingDispatcherStub = - new SpatializerHeadTrackingDispatcherStub(); - } - try { - mAm.getService().registerSpatializerHeadTrackingCallback( - mHeadTrackingDispatcherStub); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + final Pair<ArrayList<ListenerInfo<OnHeadTrackingModeChangedListener>>, + SpatializerHeadTrackingDispatcherStub> res = CallbackUtil.addListener( + "addOnHeadTrackingModeChangedListener", executor, listener, + mHeadTrackingListeners, mHeadTrackingDispatcherStub, + () -> new SpatializerHeadTrackingDispatcherStub(), + stub -> stub.register(true)); + mHeadTrackingListeners = res.first; + mHeadTrackingDispatcherStub = res.second; } } @@ -728,25 +634,14 @@ public class Spatializer { @RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS) public void removeOnHeadTrackingModeChangedListener( @NonNull OnHeadTrackingModeChangedListener listener) { - Objects.requireNonNull(listener); synchronized (mHeadTrackingListenerLock) { - if (!removeListener(listener, mHeadTrackingListeners)) { - throw new IllegalArgumentException( - "Called removeOnHeadTrackingModeChangedListener() " - + "on an unregistered listener"); - } - if (mHeadTrackingListeners.size() == 0) { - // unregister binder for callbacks - try { - mAm.getService().unregisterSpatializerHeadTrackingCallback( - mHeadTrackingDispatcherStub); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } finally { - mHeadTrackingDispatcherStub = null; - mHeadTrackingListeners = null; - } - } + final Pair<ArrayList<ListenerInfo<OnHeadTrackingModeChangedListener>>, + SpatializerHeadTrackingDispatcherStub> res = CallbackUtil.removeListener( + "removeOnHeadTrackingModeChangedListener", listener, + mHeadTrackingListeners, mHeadTrackingDispatcherStub, + stub -> stub.register(false)); + mHeadTrackingListeners = res.first; + mHeadTrackingDispatcherStub = res.second; } } @@ -931,45 +826,6 @@ public class Spatializer { } //----------------------------------------------------------------------------- - // callback helper definitions - - private static class ListenerInfo<T> { - final @NonNull T mListener; - final @NonNull Executor mExecutor; - - ListenerInfo(T listener, Executor exe) { - mListener = listener; - mExecutor = exe; - } - } - - private static <T> ListenerInfo<T> getListenerInfo( - T listener, ArrayList<ListenerInfo<T>> listeners) { - if (listeners == null) { - return null; - } - for (ListenerInfo<T> info : listeners) { - if (info.mListener == listener) { - return info; - } - } - return null; - } - - private static <T> boolean hasListener(T listener, ArrayList<ListenerInfo<T>> listeners) { - return getListenerInfo(listener, listeners) != null; - } - - private static <T> boolean removeListener(T listener, ArrayList<ListenerInfo<T>> listeners) { - final ListenerInfo<T> infoToRemove = getListenerInfo(listener, listeners); - if (infoToRemove != null) { - listeners.remove(infoToRemove); - return true; - } - return false; - } - - //----------------------------------------------------------------------------- // head tracking callback management and stub private final Object mHeadTrackingListenerLock = new Object(); @@ -986,42 +842,31 @@ public class Spatializer { private final class SpatializerHeadTrackingDispatcherStub extends ISpatializerHeadTrackingModeCallback.Stub { - @Override - public void dispatchSpatializerActualHeadTrackingModeChanged(int mode) { - // make a shallow copy of listeners so callback is not executed under lock - final ArrayList<ListenerInfo<OnHeadTrackingModeChangedListener>> headTrackingListeners; - synchronized (mHeadTrackingListenerLock) { - if (mHeadTrackingListeners == null || mHeadTrackingListeners.size() == 0) { - return; - } - headTrackingListeners = (ArrayList<ListenerInfo<OnHeadTrackingModeChangedListener>>) - mHeadTrackingListeners.clone(); - } - try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { - for (ListenerInfo<OnHeadTrackingModeChangedListener> info : headTrackingListeners) { - info.mExecutor.execute(() -> info.mListener - .onHeadTrackingModeChanged(Spatializer.this, mode)); + public void register(boolean register) { + try { + if (register) { + mAm.getService().registerSpatializerHeadTrackingCallback(this); + } else { + mAm.getService().unregisterSpatializerHeadTrackingCallback(this); } + } catch (RemoteException e) { + e.rethrowFromSystemServer(); } } @Override + @SuppressLint("GuardedBy") // lock applied inside callListeners method + public void dispatchSpatializerActualHeadTrackingModeChanged(int mode) { + CallbackUtil.callListeners(mHeadTrackingListeners, mHeadTrackingListenerLock, + (listener) -> listener.onHeadTrackingModeChanged(Spatializer.this, mode)); + } + + @Override + @SuppressLint("GuardedBy") // lock applied inside callListeners method public void dispatchSpatializerDesiredHeadTrackingModeChanged(int mode) { - // make a shallow copy of listeners so callback is not executed under lock - final ArrayList<ListenerInfo<OnHeadTrackingModeChangedListener>> headTrackingListeners; - synchronized (mHeadTrackingListenerLock) { - if (mHeadTrackingListeners == null || mHeadTrackingListeners.size() == 0) { - return; - } - headTrackingListeners = (ArrayList<ListenerInfo<OnHeadTrackingModeChangedListener>>) - mHeadTrackingListeners.clone(); - } - try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { - for (ListenerInfo<OnHeadTrackingModeChangedListener> info : headTrackingListeners) { - info.mExecutor.execute(() -> info.mListener - .onDesiredHeadTrackingModeChanged(Spatializer.this, mode)); - } - } + CallbackUtil.callListeners(mHeadTrackingListeners, mHeadTrackingListenerLock, + (listener) -> listener.onDesiredHeadTrackingModeChanged( + Spatializer.this, mode)); } } diff --git a/media/java/android/media/tv/interactive/ITvIAppService.aidl b/media/java/android/media/tv/interactive/ITvIAppService.aidl index c4f82ebc830f..2f165f0de7e5 100644 --- a/media/java/android/media/tv/interactive/ITvIAppService.aidl +++ b/media/java/android/media/tv/interactive/ITvIAppService.aidl @@ -16,6 +16,7 @@ package android.media.tv.interactive; +import android.media.tv.interactive.ITvIAppServiceCallback; import android.media.tv.interactive.ITvIAppSessionCallback; /** @@ -24,5 +25,7 @@ import android.media.tv.interactive.ITvIAppSessionCallback; * @hide */ oneway interface ITvIAppService { + void registerCallback(in ITvIAppServiceCallback callback); + void unregisterCallback(in ITvIAppServiceCallback callback); void createSession(in ITvIAppSessionCallback callback, in String iAppServiceId, int type); }
\ No newline at end of file diff --git a/media/java/android/media/tv/interactive/TvIAppService.java b/media/java/android/media/tv/interactive/TvIAppService.java index 8863729bfab3..78b8173e0af7 100644 --- a/media/java/android/media/tv/interactive/TvIAppService.java +++ b/media/java/android/media/tv/interactive/TvIAppService.java @@ -26,6 +26,7 @@ import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Log; import android.view.KeyEvent; @@ -62,11 +63,26 @@ public abstract class TvIAppService extends Service { public static final String SERVICE_META_DATA = "android.media.tv.interactive.app"; private final Handler mServiceHandler = new ServiceHandler(); + private final RemoteCallbackList<ITvIAppServiceCallback> mCallbacks = + new RemoteCallbackList<>(); /** @hide */ @Override public final IBinder onBind(Intent intent) { ITvIAppService.Stub tvIAppServiceBinder = new ITvIAppService.Stub() { + @Override + public void registerCallback(ITvIAppServiceCallback cb) { + if (cb != null) { + mCallbacks.register(cb); + } + } + + @Override + public void unregisterCallback(ITvIAppServiceCallback cb) { + if (cb != null) { + mCallbacks.unregister(cb); + } + } @Override public void createSession(ITvIAppSessionCallback cb, String iAppServiceId, int type) { @@ -137,7 +153,7 @@ public abstract class TvIAppService extends Service { * Called when the application sets the surface. * * <p>The TV IApp service should render interactive app UI onto the given surface. When - * called with {@code null}, the input service should immediately free any references to the + * called with {@code null}, the IApp service should immediately free any references to the * currently set surface and stop using it. * * @param surface The surface to be used for interactive app UI rendering. Can be diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index f28d062b75fd..bd687e467dba 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -489,7 +489,7 @@ <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carga rápida"</string> <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carga lenta"</string> - <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Cargando sin cables"</string> + <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Carga inalámbrica"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"No se está cargando"</string> <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado pero sin cargar"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Cargada"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 73fadf7e0f97..ebaf4b1747a7 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -266,7 +266,7 @@ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Veuillez vous connecter à un réseau Wi-Fi"</string> <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, débogage, développeur"</string> <string name="bugreport_in_power" msgid="8664089072534638709">"Raccourci de rapport de bogue"</string> - <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afficher un bouton permettant d\'établir un rapport de bogue dans le menu de démarrage"</string> + <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afficher un bouton permettant d\'établir un rapport de bogue dans le menu de l\'interrupteur"</string> <string name="keep_screen_on" msgid="1187161672348797558">"Rester activé"</string> <string name="keep_screen_on_summary" msgid="1510731514101925829">"L\'écran ne se met jamais en veille lors du chargement"</string> <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Activer le journal HCI Snoop Bluetooth"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 173588bb182a..0a96f59c8a8a 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -527,8 +527,8 @@ <string name="status_unavailable" msgid="5279036186589861608">"Non disponibile"</string> <string name="wifi_status_mac_randomized" msgid="466382542497832189">"Selezione casuale dell\'indirizzo MAC"</string> <plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139"> + <item quantity="one">%1$d devices connected</item> <item quantity="other">%1$d dispositivi connessi</item> - <item quantity="one">%1$d dispositivo connesso</item> </plurals> <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Più tempo."</string> <string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Meno tempo."</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index ebe5753d9c99..5a0ec2e36543 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -527,8 +527,8 @@ <string name="status_unavailable" msgid="5279036186589861608">"Indisponível"</string> <string name="wifi_status_mac_randomized" msgid="466382542497832189">"O MAC é aleatório."</string> <plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139"> - <item quantity="other">%1$d dispositivos ligados</item> <item quantity="one">%1$d dispositivo ligado</item> + <item quantity="other">%1$d dispositivos ligados</item> </plurals> <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Mais tempo."</string> <string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Menos tempo."</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java index 58d2185ea9e9..1df1bce014cb 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java @@ -160,10 +160,12 @@ public class BluetoothEventManager { private void registerIntentReceiver(BroadcastReceiver receiver, IntentFilter filter) { if (mUserHandle == null) { // If userHandle has not been provided, simply call registerReceiver. - mContext.registerReceiver(receiver, filter, null, mReceiverHandler); + mContext.registerReceiver(receiver, filter, null, mReceiverHandler, + Context.RECEIVER_EXPORTED); } else { // userHandle was explicitly specified, so need to call multi-user aware API. - mContext.registerReceiverAsUser(receiver, mUserHandle, filter, null, mReceiverHandler); + mContext.registerReceiverAsUser(receiver, mUserHandle, filter, null, mReceiverHandler, + Context.RECEIVER_EXPORTED); } } diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java index b3205d7563b2..b56ae3864fb7 100644 --- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java +++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java @@ -109,6 +109,15 @@ public class BatteryStatus { } /** + * Determine whether the device is plugged in wireless. + * + * @return true if the device is plugged in wireless + */ + public boolean isPluggedInWireless() { + return plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS; + } + + /** * Whether or not the device is charged. Note that some devices never return 100% for * battery level, so this allows either battery level or status to determine if the * battery is charged. diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java index bf62f1dfb75b..a10b8194ba5e 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java @@ -262,7 +262,6 @@ public class GlobalSettingsValidators { VALIDATORS.put(Global.Wearable.AMBIENT_TOUCH_TO_WAKE, BOOLEAN_VALIDATOR); VALIDATORS.put(Global.Wearable.DECOMPOSABLE_WATCHFACE, BOOLEAN_VALIDATOR); VALIDATORS.put(Global.Wearable.AMBIENT_FORCE_WHEN_DOCKED, BOOLEAN_VALIDATOR); - VALIDATORS.put(Global.Wearable.AMBIENT_GESTURE_SENSOR_ID, ANY_INTEGER_VALIDATOR); VALIDATORS.put(Global.Wearable.AMBIENT_LOW_BIT_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Global.Wearable.AMBIENT_PLUGGED_TIMEOUT_MIN, ANY_INTEGER_VALIDATOR); VALIDATORS.put(Global.Wearable.AMBIENT_TILT_TO_BRIGHT, BOOLEAN_VALIDATOR); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index aca70f12758d..ce7517f14e77 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -5325,9 +5325,6 @@ public class SettingsProvider extends ContentProvider { Settings.Global.Wearable.AMBIENT_FORCE_WHEN_DOCKED, SystemProperties.getBoolean("ro.ambient.force_when_docked", false)); initGlobalSettingsDefaultValForWearLocked( - Settings.Global.Wearable.AMBIENT_GESTURE_SENSOR_ID, - SystemProperties.getInt("ro.ambient.gesture_sensor_id", 0)); - initGlobalSettingsDefaultValForWearLocked( Settings.Global.Wearable.AMBIENT_LOW_BIT_ENABLED, SystemProperties.getBoolean("ro.ambient.low_bit_enabled", false)); initGlobalSettingsDefaultValForWearLocked( diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 324c05e3cbe0..c9c93c48af9d 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -640,7 +640,6 @@ public class SettingsBackupTest { Settings.Global.Wearable.AMBIENT_TILT_TO_BRIGHT, Settings.Global.Wearable.DECOMPOSABLE_WATCHFACE, Settings.Global.Wearable.AMBIENT_FORCE_WHEN_DOCKED, - Settings.Global.Wearable.AMBIENT_GESTURE_SENSOR_ID, Settings.Global.Wearable.AMBIENT_LOW_BIT_ENABLED, Settings.Global.Wearable.AMBIENT_PLUGGED_TIMEOUT_MIN, Settings.Global.Wearable.PAIRED_DEVICE_OS_TYPE, diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index f59f099c7767..abd010db7cee 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -589,6 +589,9 @@ <!-- Permission required to run GtsAssistantTestCases --> <uses-permission android:name="android.permission.MANAGE_VOICE_KEYPHRASES" /> + <!-- Permission required for CTS test - SettingsMultiPaneDeepLinkTest --> + <uses-permission android:name="android.permission.LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK" /> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml index 985f952a9526..337d4333a4db 100644 --- a/packages/SystemUI/res-keyguard/values-it/strings.xml +++ b/packages/SystemUI/res-keyguard/values-it/strings.xml @@ -53,8 +53,8 @@ <string name="kg_wrong_password" msgid="4143127991071670512">"Password errata"</string> <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN errato"</string> <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="991400408675793914"> + <item quantity="one">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item> <item quantity="other">Riprova fra <xliff:g id="NUMBER">%d</xliff:g> secondi.</item> - <item quantity="one">Riprova fra 1 secondo.</item> </plurals> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Inserisci il PIN della SIM."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Inserisci il PIN della SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string> @@ -71,13 +71,13 @@ <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. \n\nRiprova tra <xliff:g id="NUMBER_1">%2$d</xliff:g> secondi."</string> <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Codice PIN della SIM errato. Devi contattare l\'operatore per sbloccare il dispositivo."</string> <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026"> + <item quantity="one">Incorrect SIM PIN code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item> <item quantity="other">Codice PIN della SIM errato. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione.</item> - <item quantity="one">Codice PIN della SIM errato. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.</item> </plurals> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM inutilizzabile. Contatta il tuo operatore."</string> <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886"> + <item quantity="one">Incorrect SIM PUK code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable.</item> <item quantity="other">Codice PUK della SIM errato. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile.</item> - <item quantity="one">Codice PUK della SIM errato. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile.</item> </plurals> <string name="kg_password_pin_failed" msgid="5136259126330604009">"Operazione con PIN della SIM non riuscita."</string> <string name="kg_password_puk_failed" msgid="6778867411556937118">"Operazione con PUK della SIM non riuscita."</string> @@ -94,12 +94,12 @@ <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Non riconosciuto"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Non riconosciuto"</string> <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818"> + <item quantity="one">Enter SIM PIN. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item> <item quantity="other">Inserisci il codice PIN della SIM. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione.</item> - <item quantity="one">Inserisci il codice PIN della SIM. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.</item> </plurals> <plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935"> + <item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item> <item quantity="other">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.</item> - <item quantity="one">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.</item> </plurals> <string name="clock_title_default" msgid="6342735240617459864">"Predefinito"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bolla"</string> diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml index 5b0da186dbad..da663f058993 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml @@ -53,8 +53,8 @@ <string name="kg_wrong_password" msgid="4143127991071670512">"Palavra-passe incorreta."</string> <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorreto"</string> <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="991400408675793914"> - <item quantity="other">Tente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos.</item> <item quantity="one">Tente novamente dentro de 1 segundo.</item> + <item quantity="other">Tente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos.</item> </plurals> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Introduza o PIN do cartão SIM."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Introduza o PIN do cartão SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string> @@ -71,13 +71,13 @@ <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Desenhou a sua padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string> <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Código PIN do cartão SIM incorreto. Tem de contactar o seu operador para desbloquear o dispositivo."</string> <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026"> - <item quantity="other">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item> <item quantity="one">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de precisar de contactar o seu operador para desbloquear o dispositivo.</item> + <item quantity="other">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item> </plurals> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"Cartão SIM inutilizável. Contacte o seu operador."</string> <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886"> - <item quantity="other">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável.</item> <item quantity="one">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável.</item> + <item quantity="other">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável.</item> </plurals> <string name="kg_password_pin_failed" msgid="5136259126330604009">"Falha ao introduzir o PIN do cartão SIM!"</string> <string name="kg_password_puk_failed" msgid="6778867411556937118">"Falha ao introduzir o PUK do cartão SIM!"</string> @@ -94,12 +94,12 @@ <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Não reconhecido."</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Não reconhecido."</string> <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818"> - <item quantity="other">Introduza o PIN do cartão SIM. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item> <item quantity="one">Introduza o PIN do cartão SIM. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de ser necessário contactar o operador para desbloquear o dispositivo.</item> + <item quantity="other">Introduza o PIN do cartão SIM. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item> </plurals> <plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935"> - <item quantity="other">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item> <item quantity="one">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item> + <item quantity="other">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item> </plurals> <string name="clock_title_default" msgid="6342735240617459864">"Predefinido"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Balão"</string> diff --git a/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml b/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml index 0dec981bd4ae..991dc63ef830 100644 --- a/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml +++ b/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml @@ -35,7 +35,7 @@ android:id="@+id/volume_number" android:layout_width="@dimen/tv_volume_dialog_bubble_size" android:layout_height="@dimen/tv_volume_dialog_bubble_size" - android:maxLength="2" + android:maxLength="3" android:gravity="center" android:fontFeatureSettings="tnum" android:background="@drawable/tv_volume_dialog_circle" diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 4015762a0c30..f2d27c4e0109 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Die program of jou organisasie laat nie toe dat skermkiekies geneem word nie"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Wysig"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Wysig skermkiekie"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Deel skermskoot"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Vang meer vas"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Maak skermkiekie toe"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Skermkiekievoorskou"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Foon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Stembystand"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Beursie"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Ontsluit"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Toestel is gesluit"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skandeer tans gesig"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ontsluit om te gebruik"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Kon nie jou kaarte kry nie; probeer later weer"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Sluitskerminstellings"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Werkprofiel"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Vliegtuigmodus"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Jy sal nie jou volgende wekker <xliff:g id="WHEN">%1$s</xliff:g> hoor nie"</string> diff --git a/packages/SystemUI/res/values-af/tiles_states_strings.xml b/packages/SystemUI/res/values-af/tiles_states_strings.xml index 5ce5340479c9..c7e7618015f7 100644 --- a/packages/SystemUI/res/values-af/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-af/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Af"</item> <item msgid="6866424167599381915">"Aan"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Onbeskikbaar"</item> <item msgid="2710157085538036590">"Af"</item> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 723f766e6e8f..b71cf7ad2eff 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ቅጽበታዊ ገጽ እይታዎችን ማንሳት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"አርትዕ ያድርጉ"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"ቅጽበታዊ ገጽ ዕይታን አርትዕ ያድርጉ"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"ቅጽበታዊ ገጽ እይታን ያጋሩ"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"ተጨማሪ ይቅረጹ"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ቅጽበታዊ ገጽ ዕይታን አሰናብት"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"የቅጽበታዊ ገጽ ዕይታ ቅድመ-ዕይታ"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ስልክ"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"የድምጽ እርዳታ"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"የኪስ ቦርሳ"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"ክፈት"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"መሣሪያ ተቆልፏል"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"የቅኝት ፊት"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ለማየት ይክፈቱ"</string> <string name="wallet_error_generic" msgid="257704570182963611">"የእርስዎን ካርዶች ማግኘት ላይ ችግር ነበር፣ እባክዎ ቆይተው እንደገና ይሞክሩ"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"የገጽ መቆለፊያ ቅንብሮች"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"የስራ መገለጫ"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"የአውሮፕላን ሁነታ"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"የእርስዎን ቀጣይ ማንቂያ <xliff:g id="WHEN">%1$s</xliff:g> አይሰሙም"</string> diff --git a/packages/SystemUI/res/values-am/tiles_states_strings.xml b/packages/SystemUI/res/values-am/tiles_states_strings.xml index 0a53d20330ed..e5be86053acd 100644 --- a/packages/SystemUI/res/values-am/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-am/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"ጠፍቷል"</item> <item msgid="6866424167599381915">"በርቷል"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"አይገኝም"</item> <item msgid="2710157085538036590">"ጠፍቷል"</item> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index a163a9b38085..4141969e4089 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"يحظر التطبيق أو تحظر مؤسستك التقاط لقطات شاشة"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"تعديل"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"تعديل لقطة الشاشة"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"مشاركة لقطة الشاشة"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"التقاط المزيد من المحتوى"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"إغلاق لقطة الشاشة"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"معاينة لقطة الشاشة"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"الهاتف"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"المساعد الصوتي"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"المحفظة"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"فتح القفل"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"الجهاز مُقفل."</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"مسح الوجه"</string> @@ -477,6 +478,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"فتح القفل للاستخدام"</string> <string name="wallet_error_generic" msgid="257704570182963611">"حدثت مشكلة أثناء الحصول على البطاقات، يُرجى إعادة المحاولة لاحقًا."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"إعدادات شاشة القفل"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"الملف الشخصي للعمل"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"وضع الطيران"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"لن تسمع المنبّه القادم في <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-ar/tiles_states_strings.xml b/packages/SystemUI/res/values-ar/tiles_states_strings.xml index 90baf043a8a3..e2b8632366c1 100644 --- a/packages/SystemUI/res/values-ar/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ar/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"الميزة غير مفعّلة"</item> <item msgid="6866424167599381915">"الميزة مفعّلة"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"الميزة غير متاحة"</item> <item msgid="2710157085538036590">"الميزة غير مفعّلة"</item> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index a36532a5e02a..7c7d95ba0798 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ফ\'ন"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"কণ্ঠধ্বনিৰে সহায়"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"ৱালেট"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"আনলক কৰক"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"ডিভাইচটো লক হৈ আছে"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"চেহেৰা স্কেন কৰি থকা হৈছে"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ব্যৱহাৰ কৰিবলৈ আনলক কৰক"</string> <string name="wallet_error_generic" msgid="257704570182963611">"আপোনাৰ কাৰ্ড লাভ কৰোঁতে এটা সমস্যা হৈছে, অনুগ্ৰহ কৰি পাছত পুনৰ চেষ্টা কৰক"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"লক স্ক্ৰীনৰ ছেটিং"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"এয়াৰপ্লেইন ম\'ড"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"আপুনি আপোনাৰ পিছৰটো এলাৰ্ম <xliff:g id="WHEN">%1$s</xliff:g> বজাত শুনা নাপাব"</string> diff --git a/packages/SystemUI/res/values-as/tiles_states_strings.xml b/packages/SystemUI/res/values-as/tiles_states_strings.xml index fa333df39a49..43957f404b88 100644 --- a/packages/SystemUI/res/values-as/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-as/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"অফ আছে"</item> <item msgid="6866424167599381915">"অন কৰা আছে"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"উপলব্ধ নহয়"</item> <item msgid="2710157085538036590">"অফ আছে"</item> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 5a53dd824af8..8e27b0fbf175 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Skrinşot çəkməyə tətbiq və ya təşkilat tərəfindən icazə verilmir"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Redaktə edin"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Skrinşota düzəliş edin"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Skrinşotu paylaşın"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Genişləndirin"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ekran şəklini ötürün"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekran şəklinə önbaxış"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Səs Yardımçısı"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Pulqabı"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Kiliddən çıxarın"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Cihaz kilidlənib"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Üzün skan edilməsi"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"İstifadə etmək üçün kiliddən çıxarın"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Kartların əldə edilməsində problem oldu, sonra yenidən cəhd edin"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Kilid ekranı ayarları"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Təyyarə rejimi"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> zaman növbəti xəbərdarlığınızı eşitməyəcəksiniz"</string> diff --git a/packages/SystemUI/res/values-az/tiles_states_strings.xml b/packages/SystemUI/res/values-az/tiles_states_strings.xml index 1a3a2dc25f64..4baea08fb7bc 100644 --- a/packages/SystemUI/res/values-az/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-az/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Deaktiv"</item> <item msgid="6866424167599381915">"Aktiv"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Əlçatan deyil"</item> <item msgid="2710157085538036590">"Deaktiv"</item> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index db3d91764a9b..6d5e75abf1e0 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Izmeni"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Izmenite snimak ekrana"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Delite snimak ekrana"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Snimite još"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Odbacite snimak ekrana"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimka ekrana"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovna pomoć"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Novčanik"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Otključajte"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Uređaj je zaključan"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skeniranje lica"</string> @@ -468,6 +469,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključaj radi korišćenja"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Došlo je do problema pri preuzimanju kartica. Probajte ponovo kasnije"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Podešavanja zaključanog ekrana"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Režim rada u avionu"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sledeći alarm u <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml index 5622a82ee6d5..90b8ccebc8de 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Isključeno"</item> <item msgid="6866424167599381915">"Uključeno"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Nedostupno"</item> <item msgid="2710157085538036590">"Isključeno"</item> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 262752c726ef..e98c498a105a 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Рабіць здымкі экрана не дазваляе праграма ці ваша арганізацыя"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Змяніць"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Змяніць здымак экрана"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Абагуліць здымак экрана"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Зняць больш"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Адхіліць здымак экрана"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Перадпрагляд здымка экрана"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Тэлефон"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Галасавая дапамога"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Кашалёк"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Разблакiраваць"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Прылада заблакіравана"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Сканіраванне твару"</string> @@ -285,7 +286,7 @@ <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Уключыць у <xliff:g id="TIME">%s</xliff:g>"</string> <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Да <xliff:g id="TIME">%s</xliff:g>"</string> <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Цёмная тэма"</string> - <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Эканомія зараду"</string> + <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Энергазберажэнне"</string> <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Уключана ўвечары"</string> <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Да ўсходу сонца"</string> <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Уключана ў <xliff:g id="TIME">%s</xliff:g>"</string> @@ -471,6 +472,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Разблакіраваць для выкарыстання"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Узнікла праблема з загрузкай вашых карт. Паўтарыце спробу пазней"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Налады экрана блакіроўкі"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Працоўны профіль"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Рэжым палёту"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Вы не пачуеце наступны будзільнік <xliff:g id="WHEN">%1$s</xliff:g>"</string> @@ -546,7 +551,7 @@ <item quantity="many">%d хвілін</item> <item quantity="other">%d хвіліны</item> </plurals> - <string name="battery_detail_switch_title" msgid="6940976502957380405">"Эканомія зараду"</string> + <string name="battery_detail_switch_title" msgid="6940976502957380405">"Рэжым энергазберажэння"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"Кнопка <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string> <string name="keyboard_key_back" msgid="4185420465469481999">"Назад"</string> diff --git a/packages/SystemUI/res/values-be/tiles_states_strings.xml b/packages/SystemUI/res/values-be/tiles_states_strings.xml index b70a813507a9..4ad97d2337c8 100644 --- a/packages/SystemUI/res/values-be/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-be/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Выключана"</item> <item msgid="6866424167599381915">"Уключана"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Недаступна"</item> <item msgid="2710157085538036590">"Выключана"</item> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 8d090e423a6d..951714e08f8d 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласова помощ"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Портфейл"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Отключване"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Устройството е заключено"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Извършва се сканиране на лице"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Отключване с цел използване"</string> <string name="wallet_error_generic" msgid="257704570182963611">"При извличането на картите ви възникна проблем. Моля, опитайте отново по-късно"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Настройки за заключения екран"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Потребителски профил в Work"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Самолетен режим"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Няма да чуете следващия си будилник в <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-bg/tiles_states_strings.xml b/packages/SystemUI/res/values-bg/tiles_states_strings.xml index 85d93931afc7..e7cc889846e1 100644 --- a/packages/SystemUI/res/values-bg/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-bg/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Изкл."</item> <item msgid="6866424167599381915">"Вкл."</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Не е налице"</item> <item msgid="2710157085538036590">"Изкл."</item> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index ac6aaeb4cf3c..217f9e3ef430 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"এই অ্যাপ বা আপনার প্রতিষ্ঠান স্ক্রিনশট নেওয়ার অনুমতি দেয়নি"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"এডিট করুন"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"স্ক্রিনশট এডিট করুন"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"স্ক্রিনশট শেয়ার করুন"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"আরও বেশি ক্যাপচার করুন"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"স্ক্রিনশট বাতিল করুন"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"স্ক্রিনশটের প্রিভিউ"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ফোন"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ভয়েস সহায়তা"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"ওয়ালেট"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"আনলক করুন"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"ডিভাইস লক করা আছে"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"ফেস স্ক্যান করা হচ্ছে"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ব্যবহার করতে আনলক করুন"</string> <string name="wallet_error_generic" msgid="257704570182963611">"আপনার কার্ড সংক্রান্ত তথ্য পেতে সমস্যা হয়েছে, পরে আবার চেষ্টা করুন"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"লক স্ক্রিন সেটিংস"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"কাজের প্রোফাইল"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"বিমান মোড"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"আপনি আপনার পরবর্তী <xliff:g id="WHEN">%1$s</xliff:g> অ্যালার্ম শুনতে পাবেন না"</string> diff --git a/packages/SystemUI/res/values-bn/tiles_states_strings.xml b/packages/SystemUI/res/values-bn/tiles_states_strings.xml index 631446d5eb3d..584de5ecc70f 100644 --- a/packages/SystemUI/res/values-bn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-bn/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"বন্ধ আছে"</item> <item msgid="6866424167599381915">"চালু আছে"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"উপলভ্য নেই"</item> <item msgid="2710157085538036590">"বন্ধ আছে"</item> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 4680da9e8da9..efcb4d4c04de 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ova aplikacija ili vaša organizacija ne dozvoljavaju snimanje ekrana"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Uredite"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Uredite snimak ekrana"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Dijeljenje snimka ekrana"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Snimite više"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Odbacite snimak ekrana"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimka ekrana"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovna pomoć"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Novčanik"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Otključaj"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Uređaj je zaključan"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skeniranje lica"</string> @@ -468,6 +469,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključajte da koristite"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Došlo je do problema prilikom preuzimanja vaših kartica. Pokušajte ponovo kasnije"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključavanja ekrana"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Profil za posao"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u avionu"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sljedeći alarm u <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-bs/tiles_states_strings.xml b/packages/SystemUI/res/values-bs/tiles_states_strings.xml index 5622a82ee6d5..90b8ccebc8de 100644 --- a/packages/SystemUI/res/values-bs/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-bs/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Isključeno"</item> <item msgid="6866424167599381915">"Uključeno"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Nedostupno"</item> <item msgid="2710157085538036590">"Isključeno"</item> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 778a52cd9f46..8ddc45690408 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'aplicació o la teva organització no permeten fer captures de pantalla"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Edita"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Edita la captura de pantalla"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Comparteix la captura de pantalla"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Captura més"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ignora la captura de pantalla"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Previsualització de la captura de pantalla"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telèfon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistència per veu"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Cartera"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloqueja"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositiu bloquejat"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"S\'està escanejant la cara"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloqueja per utilitzar"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Hi ha hagut un problema en obtenir les teves targetes; torna-ho a provar més tard"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuració de la pantalla de bloqueig"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Perfil de treball"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Mode d\'avió"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> no sentiràs la pròxima alarma"</string> diff --git a/packages/SystemUI/res/values-ca/tiles_states_strings.xml b/packages/SystemUI/res/values-ca/tiles_states_strings.xml index ddb9dc8211e1..27bfb9c8f030 100644 --- a/packages/SystemUI/res/values-ca/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ca/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Desactivat"</item> <item msgid="6866424167599381915">"Activat"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"No disponible"</item> <item msgid="2710157085538036590">"Desactivat"</item> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 3c9a9c4c7691..55c53337de27 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikace nebo organizace zakazuje pořizování snímků obrazovky"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Upravit"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Upravit snímek obrazovky"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Sdílet snímek obrazovky"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Zvětšit záběr snímku"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Zavřít snímek obrazovky"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Náhled snímku obrazovky"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Hlasová asistence"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Peněženka"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Odemknout"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Zařízení uzamčeno"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skenování obličeje"</string> @@ -471,6 +472,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odemknout a použít"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Při načítání karet došlo k problému, zkuste to později"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavení obrazovky uzamčení"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Pracovní profil"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Režim Letadlo"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Svůj další budík <xliff:g id="WHEN">%1$s</xliff:g> neuslyšíte"</string> diff --git a/packages/SystemUI/res/values-cs/tiles_states_strings.xml b/packages/SystemUI/res/values-cs/tiles_states_strings.xml index 427770d7a782..ee1f8fb8e66f 100644 --- a/packages/SystemUI/res/values-cs/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-cs/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Vyp"</item> <item msgid="6866424167599381915">"Zap"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Nedostupné"</item> <item msgid="2710157085538036590">"Vyp"</item> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 9fa3baec1084..2420c7f35ab0 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller din organisation tillader ikke, at du tager screenshots"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Rediger"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Rediger screenshot"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Del screenshottet"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Medtag mere"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Luk screenshot"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Forhåndsvisning af screenshot"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Taleassistent"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Lås op"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Enheden er låst"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanner ansigt"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås op for at bruge"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Dine kort kunne ikke hentes. Prøv igen senere."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lås skærmindstillinger"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Arbejdsprofil"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Flytilstand"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-da/tiles_states_strings.xml b/packages/SystemUI/res/values-da/tiles_states_strings.xml index 6c7d4d9d7af0..770c2ed28163 100644 --- a/packages/SystemUI/res/values-da/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-da/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Fra"</item> <item msgid="6866424167599381915">"Til"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Ikke tilgængelig"</item> <item msgid="2710157085538036590">"Fra"</item> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 7241836c6f26..61d489c86356 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonnummer"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Sprachassistent"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Entsperren"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Gerät gesperrt"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Gesicht wird gescannt"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Zum Verwenden entsperren"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Beim Abrufen deiner Karten ist ein Fehler aufgetreten – bitte versuch es später noch einmal"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Einstellungen für den Sperrbildschirm"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Arbeitsprofil"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Flugmodus"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Lautloser Weckruf <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-de/tiles_states_strings.xml b/packages/SystemUI/res/values-de/tiles_states_strings.xml index 19ceead2e494..50d0ed5d05f0 100644 --- a/packages/SystemUI/res/values-de/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-de/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Aus"</item> <item msgid="6866424167599381915">"An"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Nicht verfügbar"</item> <item msgid="2710157085538036590">"Aus"</item> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 8ca961a18ab7..0bd3940b2bd8 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Η λήψη στιγμιότυπων οθόνης δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Επεξεργασία"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Επεξεργασία στιγμιότυπου οθόνης"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Κοινοποίηση στιγμιότυπου οθόνης"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Λήψη περισσότερων"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Παράβλεψη στιγμιότυπου οθόνης"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Προεπισκόπηση στιγμιότυπου οθόνης"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Τηλέφωνο"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Φωνητική υποβοήθηση"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Πορτοφόλι"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Ξεκλείδωμα"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Η συσκευή κλειδώθηκε"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Σάρωση προσώπου"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ξεκλείδωμα για χρήση"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Παρουσιάστηκε πρόβλημα με τη λήψη των καρτών σας. Δοκιμάστε ξανά αργότερα"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ρυθμίσεις κλειδώματος οθόνης"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Προφίλ εργασίας"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Λειτουργία πτήσης"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Δεν θα ακούσετε το επόμενο ξυπνητήρι σας <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-el/tiles_states_strings.xml b/packages/SystemUI/res/values-el/tiles_states_strings.xml index 1dbaaa6c9b9b..76f98f57cf5c 100644 --- a/packages/SystemUI/res/values-el/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-el/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Ανενεργό"</item> <item msgid="6866424167599381915">"Ενεργό"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Μη διαθέσιμο"</item> <item msgid="2710157085538036590">"Ανενεργό"</item> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index c1950be8ba16..9807774a43ff 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string> <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml index 0496502a40fb..2215f2d4f198 100644 --- a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Off"</item> <item msgid="6866424167599381915">"On"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Unavailable"</item> <item msgid="2710157085538036590">"Off"</item> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 393289e10a6c..246d58085995 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string> <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml index 0496502a40fb..2215f2d4f198 100644 --- a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Off"</item> <item msgid="6866424167599381915">"On"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Unavailable"</item> <item msgid="2710157085538036590">"Off"</item> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index c1950be8ba16..9807774a43ff 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string> <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml index 0496502a40fb..2215f2d4f198 100644 --- a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Off"</item> <item msgid="6866424167599381915">"On"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Unavailable"</item> <item msgid="2710157085538036590">"Off"</item> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index c1950be8ba16..9807774a43ff 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string> <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml index 0496502a40fb..2215f2d4f198 100644 --- a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Off"</item> <item msgid="6866424167599381915">"On"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Unavailable"</item> <item msgid="2710157085538036590">"Off"</item> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 44471bdafc27..95d8074c8858 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -107,6 +107,7 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"QR Code Scanner"</string> <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string> @@ -464,6 +465,8 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string> <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards, please try again later"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string> + <string name="qr_code_scanner_title" msgid="1598912458255252498">"Scan QR"</string> + <string name="qr_code_scanner_description" msgid="7452098243938659945">"Click to scan a QR code"</string> <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml index 3bc03c01b3b3..2432ea3a57a4 100644 --- a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml @@ -151,6 +151,11 @@ <item msgid="7571394439974244289">"Off"</item> <item msgid="6866424167599381915">"On"</item> </string-array> + <string-array name="tile_states_qr_code_scanner"> + <item msgid="7435143266149257618">"Unavailable"</item> + <item msgid="3301403109049256043">"Off"</item> + <item msgid="8878684975184010135">"On"</item> + </string-array> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Unavailable"</item> <item msgid="2710157085538036590">"Off"</item> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index caa77ddf7c6b..bcacd1b8aba6 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La app o tu organización no permiten las capturas de pantalla"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Editar"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Editar captura de pantalla"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Compartir captura"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturar más"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Descartar captura de pantalla"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa de la captura de pantalla"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Escaneando rostro"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Ocurrió un problema al obtener las tarjetas; vuelve a intentarlo más tarde"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuración de pantalla de bloqueo"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Modo de avión"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"No oirás la próxima alarma a la(s) <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml index 4f738c50c8a3..cc167d53116f 100644 --- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Desactivado"</item> <item msgid="6866424167599381915">"Activado"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"No disponible"</item> <item msgid="2710157085538036590">"Desactivado"</item> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 8152879d8e40..88235fd1bcd3 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La aplicación o tu organización no permiten realizar capturas de pantalla"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Editar"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Editar captura de pantalla"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Compartir captura de pantalla"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturar más"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Cerrar captura de pantalla"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa de captura de pantalla"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Cartera"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Escaneando cara"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Se ha producido un problema al obtener tus tarjetas. Inténtalo de nuevo más tarde."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ajustes de pantalla de bloqueo"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"No oirás la próxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string> diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml index 1c2f211e8b94..1d1cd71c49f1 100644 --- a/packages/SystemUI/res/values-es/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Desactivado"</item> <item msgid="6866424167599381915">"Activado"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"No disponible"</item> <item msgid="2710157085538036590">"Desactivado"</item> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index e798f9f9c481..c1b463fefc4c 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Rakendus või teie organisatsioon ei luba ekraanipilte jäädvustada"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Muutmine"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Ekraanipildi muutmine"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Jaga ekraanipilti"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Jäädvustage rohkem"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ekraanipildist loobumine"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekraanipildi eelvaade"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Häälabi"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Rahakott"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Luku avamine"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Seade on lukustatud"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Näo skannimine"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Avage kasutamiseks"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Teie kaartide hankimisel ilmnes probleem, proovige hiljem uuesti"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lukustuskuva seaded"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Tööprofiil"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Lennukirežiim"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Te ei kuule järgmist äratust kell <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-et/tiles_states_strings.xml b/packages/SystemUI/res/values-et/tiles_states_strings.xml index bba2d829ff9e..044954d9ffe1 100644 --- a/packages/SystemUI/res/values-et/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-et/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Väljas"</item> <item msgid="6866424167599381915">"Sees"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Pole saadaval"</item> <item msgid="2710157085538036590">"Väljas"</item> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 96378d79d035..a9a325a915cb 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonoa"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ahots-laguntza"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Zorroa"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Desblokeatu"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Gailua blokeatuta dago"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Aurpegia eskaneatzen"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desblokeatu erabiltzeko"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Arazo bat izan da txartelak eskuratzean. Saiatu berriro geroago."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Pantaila blokeatuaren ezarpenak"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Work profila"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Hegaldi modua"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Ez duzu entzungo hurrengo alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string> diff --git a/packages/SystemUI/res/values-eu/tiles_states_strings.xml b/packages/SystemUI/res/values-eu/tiles_states_strings.xml index 2fcddd425fcb..bb6c3846d953 100644 --- a/packages/SystemUI/res/values-eu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-eu/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Desaktibatuta"</item> <item msgid="6866424167599381915">"Aktibatuta"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Ez dago erabilgarri"</item> <item msgid="2710157085538036590">"Desaktibatuta"</item> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index e79eba00310d..9260abd1fe56 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"برنامه یا سازمان شما اجازه نمیدهند نماگرفت بگیرید."</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"ویرایش"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"ویرایش نماگرفت"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"همرسانی نماگرفت"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"ضبط محتوای بیشتر"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"رد کردن نماگرفت"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"پیشنمایش نماگرفت"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"تلفن"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"دستیار صوتی"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"باز کردن قفل"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"دستگاه قفل است"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"درحال اسکن کردن چهره"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"برای استفاده، قفل را باز کنید"</string> <string name="wallet_error_generic" msgid="257704570182963611">"هنگام دریافت کارتها مشکلی پیش آمد، لطفاً بعداً دوباره امتحان کنید"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"تنظیمات صفحه قفل"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"نمایه کاری"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"حالت هواپیما"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"در ساعت <xliff:g id="WHEN">%1$s</xliff:g>، دیگر صدای زنگ ساعت را نمیشنوید"</string> diff --git a/packages/SystemUI/res/values-fa/tiles_states_strings.xml b/packages/SystemUI/res/values-fa/tiles_states_strings.xml index d3662f9d43ec..13c7f414650e 100644 --- a/packages/SystemUI/res/values-fa/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fa/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"خاموش"</item> <item msgid="6866424167599381915">"روشن"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"دردسترس نیست"</item> <item msgid="2710157085538036590">"خاموش"</item> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 400966983010..5c36c7c2700f 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Puhelin"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ääniapuri"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Avaa lukitus"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Laite lukittu"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Kasvojen skannaus"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Avaa lukitus ja käytä"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Korttien noutamisessa oli ongelma, yritä myöhemmin uudelleen"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lukitusnäytön asetukset"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Työprofiili"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Lentokonetila"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Et kuule seuraavaa hälytystäsi (<xliff:g id="WHEN">%1$s</xliff:g>)."</string> diff --git a/packages/SystemUI/res/values-fi/tiles_states_strings.xml b/packages/SystemUI/res/values-fi/tiles_states_strings.xml index 5a88f19263b0..47013d167af8 100644 --- a/packages/SystemUI/res/values-fi/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fi/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Poissa päältä"</item> <item msgid="6866424167599381915">"Päällä"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Ei saatavilla"</item> <item msgid="2710157085538036590">"Poissa päältä"</item> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 1d19d0e26648..c5d8a48a855e 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'application ou votre organisation n\'autorise pas les saisies d\'écran"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Modifier"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Modifier la capture d\'écran"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Partagez la capture d\'écran"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturer plus"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Fermer la capture d\'écran"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Aperçu de la capture d\'écran"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Téléphone"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistance vocale"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portefeuille"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Déverrouiller"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Appareil verrouillé"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Numérisation du visage"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Un problème est survenu lors de la récupération de vos cartes, veuillez réessayer plus tard"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Vous n\'entendrez pas votre prochaine alarme à <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml index 30870dded7fc..fb929fc08ce1 100644 --- a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Désactivé"</item> <item msgid="6866424167599381915">"Activé"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Non disponible"</item> <item msgid="2710157085538036590">"Désactivée"</item> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index b571e0c75701..ead26a34cd35 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Les captures d\'écran ne sont pas autorisées par l\'application ni par votre organisation"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Modifier"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Modifier la capture d\'écran"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Partager la capture d\'écran"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturer plus"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Fermer la capture d\'écran"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Aperçu de la capture d\'écran"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Téléphoner"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistance vocale"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portefeuille"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Déverrouiller"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Appareil verrouillé"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Analyse du visage en cours"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Problème de récupération de vos cartes. Réessayez plus tard"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Vous n\'entendrez pas votre prochaine alarme <xliff:g id="WHEN">%1$s</xliff:g>."</string> diff --git a/packages/SystemUI/res/values-fr/tiles_states_strings.xml b/packages/SystemUI/res/values-fr/tiles_states_strings.xml index c987cd622676..971477d81679 100644 --- a/packages/SystemUI/res/values-fr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-fr/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Désactivé"</item> <item msgid="6866424167599381915">"Activé"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Indisponible"</item> <item msgid="2710157085538036590">"Désactivée"</item> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index ef91651bd9f1..3aa3e3fc3d10 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"A aplicación ou a túa organización non permite realizar capturas de pantalla"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Editar"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Editar a captura de pantalla"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Compartir captura de pantalla"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturar máis"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ignorar a captura de pantalla"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa da captura de pantalla"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente de voz"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Analizando cara"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Produciuse un problema ao obter as tarxetas. Téntao de novo máis tarde"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuración da pantalla de bloqueo"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Perfil de traballo"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Non escoitarás a alarma seguinte <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-gl/tiles_states_strings.xml b/packages/SystemUI/res/values-gl/tiles_states_strings.xml index c627ec06e599..e362238b141b 100644 --- a/packages/SystemUI/res/values-gl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-gl/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Non"</item> <item msgid="6866424167599381915">"Si"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Non dispoñible"</item> <item msgid="2710157085538036590">"Non"</item> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 1483cc9ae38c..be707d880b48 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશૉટ લેવાની મંજૂરી નથી"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"ફેરફાર કરો"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"સ્ક્રીનશૉટમાં ફેરફાર કરો"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"સ્ક્રીનશૉટ શેર કરો"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"વધુ કૅપ્ચર કરો"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"સ્ક્રીનશૉટ છોડી દો"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"સ્ક્રીનશૉટનો પ્રીવ્યૂ"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ફોન"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"વૉઇસ સહાય"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"વૉલેટ"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"અનલૉક કરો"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"ડિવાઇસ લૉક કરેલું છે"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"ચહેરો સ્કૅન કરવો"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ઉપયોગ કરવા માટે અનલૉક કરો"</string> <string name="wallet_error_generic" msgid="257704570182963611">"તમારા કાર્ડની માહિતી મેળવવામાં સમસ્યા આવી હતી, કૃપા કરીને થોડા સમય પછી ફરી પ્રયાસ કરો"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"લૉક સ્ક્રીનના સેટિંગ"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"ઑફિસની પ્રોફાઇલ"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"એરપ્લેન મોડ"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"તમે <xliff:g id="WHEN">%1$s</xliff:g> એ તમારો આગલો એલાર્મ સાંભળશો નહીં"</string> diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml index 67dfb34d0f33..12c2de7fba67 100644 --- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"બંધ છે"</item> <item msgid="6866424167599381915">"ચાલુ છે"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"ઉપલબ્ધ નથી"</item> <item msgid="2710157085538036590">"બંધ છે"</item> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 08417e48de11..80b52d23b68a 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"फ़ोन"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज़ से डिवाइस का इस्तेमाल"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"वॉलेट बटन"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"अनलॉक करें"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"डिवाइस लॉक है"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"डिवाइस अनलॉक करने के लिए चेहरा स्कैन किया जाता है"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"इस्तेमाल करने के लिए, डिवाइस अनलॉक करें"</string> <string name="wallet_error_generic" msgid="257704570182963611">"आपके कार्ड की जानकारी पाने में कोई समस्या हुई है. कृपया बाद में कोशिश करें"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लॉक स्क्रीन की सेटिंग"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"वर्क प्रोफ़ाइल"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"हवाई जहाज़ मोड"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"आपको <xliff:g id="WHEN">%1$s</xliff:g> पर अपना अगला अलार्म नहीं सुनाई देगा"</string> diff --git a/packages/SystemUI/res/values-hi/tiles_states_strings.xml b/packages/SystemUI/res/values-hi/tiles_states_strings.xml index 40d15e7cadb9..f7fce26d5b8d 100644 --- a/packages/SystemUI/res/values-hi/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hi/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"बंद है"</item> <item msgid="6866424167599381915">"चालू है"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"उपलब्ध नहीं है"</item> <item msgid="2710157085538036590">"बंद है"</item> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 59aa397300f7..886490137741 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ili vaša organizacija ne dopuštaju snimanje zaslona"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Uredi"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Uređivanje snimke zaslona"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Podijeli snimku zaslona"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Snimi više"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Odbacivanje snimke zaslona"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimke zaslona"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovna pomoć"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Otključavanje"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Uređaj je zaključan"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skeniranje lica"</string> @@ -468,6 +469,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključajte da biste koristili"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Pojavio se problem prilikom dohvaćanja kartica, pokušajte ponovo kasnije"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključanog zaslona"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u zrakoplovu"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sljedeći alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-hr/tiles_states_strings.xml b/packages/SystemUI/res/values-hr/tiles_states_strings.xml index 5622a82ee6d5..90b8ccebc8de 100644 --- a/packages/SystemUI/res/values-hr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hr/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Isključeno"</item> <item msgid="6866424167599381915">"Uključeno"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Nedostupno"</item> <item msgid="2710157085538036590">"Isključeno"</item> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index fbcaa99f3fdb..d8f2238813db 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Az alkalmazás vagy az Ön szervezete nem engedélyezi képernyőkép készítését"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Szerkesztés"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Képernyőkép szerkesztése"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Képernyőkép megosztása"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Több rögzítése"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Képernyőkép elvetése"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Képernyőkép előnézete"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Hangsegéd"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Feloldás"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Az eszköz zárolva van"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Arc keresése"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Oldja fel a használathoz"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Probléma merült fel a kártyák lekérésekor, próbálja újra később"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lezárási képernyő beállításai"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Munkahelyi profil"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Repülős üzemmód"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Nem fogja hallani az ébresztést ekkor: <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-hu/tiles_states_strings.xml b/packages/SystemUI/res/values-hu/tiles_states_strings.xml index 113e61f71165..6e1d636b48d3 100644 --- a/packages/SystemUI/res/values-hu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hu/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Ki"</item> <item msgid="6866424167599381915">"Be"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Nem áll rendelkezésre"</item> <item msgid="2710157085538036590">"Ki"</item> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index b70be8a384e8..c5f55956a3b5 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Հեռախոս"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ձայնային հուշումներ"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Դրամապանակ"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Ապակողպել"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Սարքը կողպված է"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Դեմքի սկանավորում"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ապակողպել՝ օգտագործելու համար"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Չհաջողվեց բեռնել քարտերը։ Նորից փորձեք։"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Կողպէկրանի կարգավորումներ"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Android for Work-ի պրոֆիլ"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Ավիառեժիմ"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Ժամը <xliff:g id="WHEN">%1$s</xliff:g>-ի զարթուցիչը չի զանգի"</string> diff --git a/packages/SystemUI/res/values-hy/tiles_states_strings.xml b/packages/SystemUI/res/values-hy/tiles_states_strings.xml index a8d89d22e290..3e9c28cb74cf 100644 --- a/packages/SystemUI/res/values-hy/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-hy/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Անջատված է"</item> <item msgid="6866424167599381915">"Միացված է"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Հասանելի չէ"</item> <item msgid="2710157085538036590">"Անջատված է"</item> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 3333a28f2624..1bae18ea3cde 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -108,6 +108,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telepon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Bantuan Suara"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Buka kunci"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Perangkat terkunci"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Memindai wajah"</string> @@ -465,6 +467,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Buka kunci untuk menggunakan"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Terjadi masalah saat mendapatkan kartu Anda, coba lagi nanti"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setelan layar kunci"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Mode pesawat"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Anda tidak akan mendengar alarm berikutnya <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-in/tiles_states_strings.xml b/packages/SystemUI/res/values-in/tiles_states_strings.xml index 84a9342e2f09..70ee1bc3f2ed 100644 --- a/packages/SystemUI/res/values-in/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-in/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Nonaktif"</item> <item msgid="6866424167599381915">"Aktif"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Tidak tersedia"</item> <item msgid="2710157085538036590">"Nonaktif"</item> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 060cb7761663..9c3889dc363b 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Forritið eða fyrirtækið þitt leyfir ekki skjámyndatöku"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Breyta"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Breyta skjámynd"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Deila skjámynd"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Mynda meira"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Loka skjámynd"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Forskoðun skjámyndar"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Sími"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Raddaðstoð"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Veski"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Taka úr lás"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Tækið er læst"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Andlit skannað"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Taktu úr lás til að nota"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Vandamál kom upp við að sækja kortin þín. Reyndu aftur síðar"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Stillingar fyrir læstan skjá"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Vinnusnið"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Flugstilling"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Ekki mun heyrast í vekjaranum <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-is/tiles_states_strings.xml b/packages/SystemUI/res/values-is/tiles_states_strings.xml index 5616d74dc7dd..3565a9c27b5f 100644 --- a/packages/SystemUI/res/values-is/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-is/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Slökkt"</item> <item msgid="6866424167599381915">"Kveikt"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Ekki í boði"</item> <item msgid="2710157085538036590">"Slökkt"</item> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index f99b6baa4fe1..4a5530f0e192 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'acquisizione di screenshot non è consentita dall\'app o dall\'organizzazione"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Modifica"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Modifica screenshot"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Condividi screenshot"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Acquisisci di più"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ignora screenshot"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Anteprima screenshot"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefono"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portafoglio"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Sblocca"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloccato"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scansione del viso"</string> @@ -212,8 +213,8 @@ <string name="accessibility_clear_all" msgid="970525598287244592">"Cancella tutte le notifiche."</string> <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string> <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192"> + <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item> <item quantity="other">Altre <xliff:g id="NUMBER_1">%s</xliff:g> notifiche nel gruppo.</item> - <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> altra notifica nel gruppo.</item> </plurals> <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"Lo schermo è bloccato in orientamento orizzontale."</string> <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"Lo schermo è bloccato in orientamento verticale."</string> @@ -262,8 +263,8 @@ <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Attivazione…"</string> <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Risp. dati attivo"</string> <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976"> + <item quantity="one">%d devices</item> <item quantity="other">%d dispositivi</item> - <item quantity="one">%d dispositivo</item> </plurals> <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Torcia"</string> <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Fotocamera in uso"</string> @@ -342,8 +343,8 @@ <string name="user_add_user_message_short" msgid="2599370307878014791">"Il nuovo utente, una volta aggiunto, deve impostare il proprio spazio.\n\nQualsiasi utente può aggiornare le app per tutti gli altri."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite di utenti raggiunto"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> + <item quantity="one">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item> <item quantity="other">Puoi aggiungere fino a <xliff:g id="COUNT">%d</xliff:g> utenti.</item> - <item quantity="one">È possibile creare un solo utente.</item> </plurals> <string name="user_remove_user_title" msgid="9124124694835811874">"Rimuovere l\'utente?"</string> <string name="user_remove_user_message" msgid="6702834122128031833">"Tutte le app e i dati di questo utente verranno eliminati."</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Sblocca per usare"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Si è verificato un problema durante il recupero delle tue carte. Riprova più tardi."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Impostazioni schermata di blocco"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Profilo di lavoro"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Modalità aereo"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Non sentirai la tua prossima sveglia <xliff:g id="WHEN">%1$s</xliff:g>"</string> @@ -529,12 +534,12 @@ <string name="snooze_undo" msgid="2738844148845992103">"Annulla"</string> <string name="snoozed_for_time" msgid="7586689374860469469">"Posticipato di <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <plurals name="snoozeHourOptions" formatted="false" msgid="2066838694120718170"> + <item quantity="one">%d hours</item> <item quantity="other">%d ore</item> - <item quantity="one">%d ora</item> </plurals> <plurals name="snoozeMinuteOptions" formatted="false" msgid="8998483159208055980"> + <item quantity="one">%d minutes</item> <item quantity="other">%d minuti</item> - <item quantity="one">%d minuto</item> </plurals> <string name="battery_detail_switch_title" msgid="6940976502957380405">"Risparmio energetico"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"Pulsante <xliff:g id="NAME">%1$s</xliff:g>"</string> @@ -756,8 +761,8 @@ <string name="quick_controls_title" msgid="6839108006171302273">"Controllo dispositivi"</string> <string name="controls_providers_title" msgid="6879775889857085056">"Scegli un\'app per aggiungere controlli"</string> <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380"> + <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> controlli aggiunti.</item> <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controlli aggiunti.</item> - <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> controllo aggiunto.</item> </plurals> <string name="controls_removed" msgid="3731789252222856959">"Rimosso"</string> <string name="accessibility_control_favorite" msgid="8694362691985545985">"Aggiunto ai preferiti"</string> diff --git a/packages/SystemUI/res/values-it/tiles_states_strings.xml b/packages/SystemUI/res/values-it/tiles_states_strings.xml index f18536cb09a0..a9c67d5cb99a 100644 --- a/packages/SystemUI/res/values-it/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-it/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Off"</item> <item msgid="6866424167599381915">"On"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Non disponibile"</item> <item msgid="2710157085538036590">"Off"</item> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 98fcf424401b..93688089f73d 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"האפליקציה או הארגון שלך אינם מתירים ליצור צילומי מסך"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"עריכה"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"עריכת צילום מסך"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"שיתוף של צילום מסך"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"צילום תוכן נוסף"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"סגירת צילום מסך"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"תצוגה מקדימה של צילום מסך"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"טלפון"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"האסיסטנט"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"ארנק"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"ביטול נעילה"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"המכשיר נעול"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"סורק פנים"</string> @@ -471,6 +472,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"יש לבטל את הנעילה כדי להשתמש"</string> <string name="wallet_error_generic" msgid="257704570182963611">"הייתה בעיה בקבלת הכרטיסים שלך. כדאי לנסות שוב מאוחר יותר"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"הגדרות מסך הנעילה"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"פרופיל עבודה"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"מצב טיסה"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"לא ניתן יהיה לשמוע את ההתראה הבאה שלך <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-iw/tiles_states_strings.xml b/packages/SystemUI/res/values-iw/tiles_states_strings.xml index 0be95b8dd5a6..c769a8447652 100644 --- a/packages/SystemUI/res/values-iw/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-iw/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"כבוי"</item> <item msgid="6866424167599381915">"פועל"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"לא זמין"</item> <item msgid="2710157085538036590">"כבוי"</item> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 3eb2b65d67ae..bb35ad8c001c 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"音声アシスト"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"ウォレット"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"ロック解除"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"デバイスはロックされています"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"顔のスキャン"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ロックを解除して使用"</string> <string name="wallet_error_generic" msgid="257704570182963611">"カードの取得中に問題が発生しました。しばらくしてからもう一度お試しください"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ロック画面の設定"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"仕事用プロファイル"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"機内モード"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"次回のアラーム(<xliff:g id="WHEN">%1$s</xliff:g>)は鳴りません"</string> diff --git a/packages/SystemUI/res/values-ja/tiles_states_strings.xml b/packages/SystemUI/res/values-ja/tiles_states_strings.xml index bee2deb88f0e..6383accd2122 100644 --- a/packages/SystemUI/res/values-ja/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ja/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"OFF"</item> <item msgid="6866424167599381915">"ON"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"使用不可"</item> <item msgid="2710157085538036590">"OFF"</item> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index d788fdb73c83..94eb7c2d614d 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ეკრანის ანაბეჭდების შექმნა არ არის ნებადართული აპის ან თქვენი ორგანიზაციის მიერ"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"რედაქტირება"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"ეკრანის ანაბეჭდის რედაქტირება"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"ეკრანის ანაბეჭდის გაზიარება"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"მეტის აღბეჭდვა"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ეკრანის ანაბეჭდის დახურვა"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"ეკრანის ანაბეჭდის გადახედვა"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ტელეფონი"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ხმოვანი დახმარება"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"განბლოკვა"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"მოწყობილობა ჩაკეტილია"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"მიმდინარეობს სახის სკანირება"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"გამოსაყენებლად განბლოკვა"</string> <string name="wallet_error_generic" msgid="257704570182963611">"თქვენი ბარათების მიღებისას პრობლემა წარმოიშვა. ცადეთ ხელახლა მოგვიანებით"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ჩაკეტილი ეკრანის პარამეტრები"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"სამსახურის პროფილი"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"თვითმფრინავის რეჟიმი"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"ვერ გაიგონებთ მომდევნო მაღვიძარას <xliff:g id="WHEN">%1$s</xliff:g>-ზე"</string> diff --git a/packages/SystemUI/res/values-ka/tiles_states_strings.xml b/packages/SystemUI/res/values-ka/tiles_states_strings.xml index eb5f47041d1f..4c23237af1d5 100644 --- a/packages/SystemUI/res/values-ka/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ka/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"გამორთულია"</item> <item msgid="6866424167599381915">"ჩართულია"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"მიუწვდომელია"</item> <item msgid="2710157085538036590">"გამორთულია"</item> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index ad345a9f1bbd..18ce927e8636 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Қолданба немесе ұйым скриншоттар түсіруге рұқсат етпейді"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Өзгерту"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Скриншотты өзгерту"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Скриншотты бөлісу"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Тағы суретке түсіру"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Скриншотты жабу"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Скриншотты алдын ала қарау"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Дауыс көмекшісі"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Әмиян"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Бекітпесін ашу"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Құрылғы құлыпталды."</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Бетті сканерлеу"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Пайдалану үшін құлыпты ашу"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Карталарыңыз алынбады, кейінірек қайталап көріңіз."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Экран құлпының параметрлері"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Жұмыс профилі"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Ұшақ режимі"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Келесі <xliff:g id="WHEN">%1$s</xliff:g> дабылыңызды есітпейсіз"</string> diff --git a/packages/SystemUI/res/values-kk/tiles_states_strings.xml b/packages/SystemUI/res/values-kk/tiles_states_strings.xml index cdb553069f09..7a4676f52093 100644 --- a/packages/SystemUI/res/values-kk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-kk/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Өшірулі"</item> <item msgid="6866424167599381915">"Қосулы"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Қолжетімсіз"</item> <item msgid="2710157085538036590">"Өшірулі"</item> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 7f358114795d..b86f9b5cd00b 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ការថតរូបអេក្រង់មិនត្រូវបានអនុញ្ញាតដោយកម្មវិធីនេះ ឬស្ថាប័នរបស់អ្នក"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"កែ"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"កែរូបថតអេក្រង់"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"ចែករំលែករូបថតអេក្រង់"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"ថតច្រើនទៀត"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ច្រានចោលរូបថតអេក្រង់"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"ការមើលរូបថតអេក្រង់សាកល្បង"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ទូរសព្ទ"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ជំនួយសំឡេង"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"កាបូប"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"ដោះសោ"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"បានចាក់សោឧបករណ៍"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"ការស្កេនមុខ"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ដោះសោដើម្បីប្រើប្រាស់"</string> <string name="wallet_error_generic" msgid="257704570182963611">"មានបញ្ហាក្នុងការទាញយកកាតរបស់អ្នក សូមព្យាយាមម្ដងទៀតនៅពេលក្រោយ"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ការកំណត់អេក្រង់ចាក់សោ"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"ប្រវត្តិរូបការងារ"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"ពេលជិះយន្តហោះ"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"អ្នកនឹងមិនលឺម៉ោងរោទ៍ <xliff:g id="WHEN">%1$s</xliff:g> បន្ទាប់របស់អ្នកទេ"</string> diff --git a/packages/SystemUI/res/values-km/tiles_states_strings.xml b/packages/SystemUI/res/values-km/tiles_states_strings.xml index 4ac3c83cf1b0..be3f754405ba 100644 --- a/packages/SystemUI/res/values-km/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-km/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"បិទ"</item> <item msgid="6866424167599381915">"បើក"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"មិនមានទេ"</item> <item msgid="2710157085538036590">"បិទ"</item> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 1d818ce677b4..614b0ca76a9b 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ಸಂಸ್ಥೆಯು ಸ್ಕ್ರೀನ್ಶಾಟ್ಗಳನ್ನು ತೆಗೆಯುವುದನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"ಎಡಿಟ್ ಮಾಡಿ"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"ಇನ್ನಷ್ಟು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ವಜಾಗೊಳಿಸಿ"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"ಸ್ಕ್ರೀನ್ಶಾಟ್ನ ಪೂರ್ವವೀಕ್ಷಣೆ"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ಫೋನ್"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ಧ್ವನಿ ಸಹಾಯಕ"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"ಅನ್ಲಾಕ್"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"ಸಾಧನ ಲಾಕ್ ಆಗಿದೆ"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"ಮುಖವನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ಬಳಸಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> <string name="wallet_error_generic" msgid="257704570182963611">"ನಿಮ್ಮ ಕಾರ್ಡ್ಗಳನ್ನು ಪಡೆಯುವಾಗ ಸಮಸ್ಯೆ ಉಂಟಾಗಿದೆ, ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ಲಾಕ್ ಸ್ಕ್ರ್ರೀನ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"ಏರ್ಪ್ಲೇನ್ ಮೋಡ್"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"ನಿಮ್ಮ ಮುಂದಿನ <xliff:g id="WHEN">%1$s</xliff:g> ಅಲಾರಮ್ ಅನ್ನು ನೀವು ಆಲಿಸುವುದಿಲ್ಲ"</string> diff --git a/packages/SystemUI/res/values-kn/tiles_states_strings.xml b/packages/SystemUI/res/values-kn/tiles_states_strings.xml index ae8f5a2eda31..7eea89d34484 100644 --- a/packages/SystemUI/res/values-kn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-kn/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"ಆಫ್ ಮಾಡಿ"</item> <item msgid="6866424167599381915">"ಆನ್ ಮಾಡಿ"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"ಲಭ್ಯವಿಲ್ಲ"</item> <item msgid="2710157085538036590">"ಆಫ್ ಮಾಡಿ"</item> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 0e01272b48c7..fff2b55270be 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"전화"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"음성 지원"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"지갑"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"잠금 해제"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"기기 잠김"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"얼굴 스캔 중"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"잠금 해제하여 사용"</string> <string name="wallet_error_generic" msgid="257704570182963611">"카드를 가져오는 중에 문제가 발생했습니다. 나중에 다시 시도해 보세요."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"잠금 화면 설정"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"직장 프로필"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"비행기 모드"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>에 다음 알람을 들을 수 없습니다."</string> diff --git a/packages/SystemUI/res/values-ko/tiles_states_strings.xml b/packages/SystemUI/res/values-ko/tiles_states_strings.xml index b583f242cff8..fd03b4da20a0 100644 --- a/packages/SystemUI/res/values-ko/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ko/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"꺼짐"</item> <item msgid="6866424167599381915">"켜짐"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"이용 불가"</item> <item msgid="2710157085538036590">"꺼짐"</item> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 2456ad47b69c..81e3d5d5f9b9 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Скриншот тартууга колдонмо же ишканаңыз тыюу салган."</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Түзөтүү"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Скриншотту түзөтүү"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Скриншотту бөлүшүү"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Көбүрөөк тартуу"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Скриншотту четке кагуу"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Скриншотту алдын ала көрүү"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Үн жардамчысы"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Капчык"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Кулпусун ачуу"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Түзмөк кулпуланды"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Жүз скандалууда"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Колдонуу үчүн кулпусун ачыңыз"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Кыйытмаларды алууда ката кетти. Бир аздан кийин кайталап көрүңүз."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Кулпуланган экран жөндөөлөрү"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Жумуш профили"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Учак режими"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> боло турган кийинки эскертмени укпайсыз"</string> diff --git a/packages/SystemUI/res/values-ky/tiles_states_strings.xml b/packages/SystemUI/res/values-ky/tiles_states_strings.xml index 6e75bf34e544..27aabb8ff205 100644 --- a/packages/SystemUI/res/values-ky/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ky/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Өчүк"</item> <item msgid="6866424167599381915">"Күйүк"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Жеткиликсиз"</item> <item msgid="2710157085538036590">"Өчүк"</item> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index edbda76be0ed..ed5db048c905 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ແອັບ ຫຼື ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ຖ່າຍຮູບໜ້າຈໍ"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"ແກ້ໄຂ"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"ແກ້ໄຂຮູບໜ້າຈໍ"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"ແບ່ງປັນຮູບໜ້າຈໍ"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"ຖ່າຍຮູບເພີ່ມເຕີມ"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ປິດຮູບໜ້າຈໍ"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"ຕົວຢ່າງຮູບໜ້າຈໍ"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ໂທລະສັບ"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ຊ່ວຍເຫຼືອທາງສຽງ"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"ກະເປົາ"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"ປົດລັອກ"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"ອຸປະກອນຖືກລັອກໄວ້"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"ການສະແກນໜ້າ"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ປົດລັອກເພື່ອໃຊ້"</string> <string name="wallet_error_generic" msgid="257704570182963611">"ເກີດບັນຫາໃນການໂຫຼດບັດຂອງທ່ານ, ກະລຸນາລອງໃໝ່ໃນພາຍຫຼັງ"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ການຕັ້ງຄ່າໜ້າຈໍລັອກ"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"ໂໝດເຮືອບິນ"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"ທ່ານຈະບໍ່ໄດ້ຍິນສຽງໂມງປ <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-lo/tiles_states_strings.xml b/packages/SystemUI/res/values-lo/tiles_states_strings.xml index ac5da6f6e3dc..cbb4e9d20b11 100644 --- a/packages/SystemUI/res/values-lo/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-lo/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"ປິດ"</item> <item msgid="6866424167599381915">"ເປີດ"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"ບໍ່ສາມາດໃຊ້ໄດ້"</item> <item msgid="2710157085538036590">"ປິດ"</item> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 0f6d53e28fc9..b040dde53b42 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Jūsų organizacijoje arba naudojant šią programą neleidžiama daryti ekrano kopijų"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Redaguoti"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Redaguoti ekrano kopiją"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Bendrinti ekrano kopiją"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Fiksuoti daugiau"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Praleisti ekrano kopiją"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekrano kopijos peržiūra"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonas"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Piniginė"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Atrakinti"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Įrenginys užrakintas"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Nuskaitomas veidas"</string> @@ -471,6 +472,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Atrakinti, kad būtų galima naudoti"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Gaunant korteles kilo problema, bandykite dar kartą vėliau"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Užrakinimo ekrano nustatymai"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Darbo profilis"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Lėktuvo režimas"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Negirdėsite kito signalo <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-lt/tiles_states_strings.xml b/packages/SystemUI/res/values-lt/tiles_states_strings.xml index 4b328203a1cf..c881b1efb8ba 100644 --- a/packages/SystemUI/res/values-lt/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-lt/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Išjungta"</item> <item msgid="6866424167599381915">"Įjungta"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Nepasiekiama"</item> <item msgid="2710157085538036590">"Išjungta"</item> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 50154bc36298..031f09ee165a 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Lietotne vai jūsu organizācija neatļauj veikt ekrānuzņēmumus."</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Rediģēt"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Rediģēt ekrānuzņēmumu"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Kopīgot ekrānuzņēmumu"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Tvert vairāk"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Nerādīt ekrānuzņēmumu"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekrānuzņēmuma priekšskatījums"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Tālruņa numurs"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Balss palīgs"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Maks"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Atbloķēt"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Ierīce ir bloķēta"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Sejas skenēšana"</string> @@ -468,6 +469,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lai izmantotu, atbloķējiet ekrānu"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Ienesot jūsu kartes, radās problēma. Lūdzu, vēlāk mēģiniet vēlreiz."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Bloķēšanas ekrāna iestatījumi"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Darba profils"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Lidojuma režīms"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Nākamais signāls (<xliff:g id="WHEN">%1$s</xliff:g>) netiks atskaņots."</string> diff --git a/packages/SystemUI/res/values-lv/tiles_states_strings.xml b/packages/SystemUI/res/values-lv/tiles_states_strings.xml index d000b7c8987f..2f170e0001eb 100644 --- a/packages/SystemUI/res/values-lv/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-lv/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Izslēgts"</item> <item msgid="6866424167599381915">"Ieslēgts"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Nav pieejams"</item> <item msgid="2710157085538036590">"Izslēgts"</item> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 6148344e9c2d..ad7818af2995 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Апликацијата или вашата организација не дозволува снимање слики од екранот"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Измени"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Изменете ја сликата од екранот"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Споделете слика од екранот"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Сними повеќе"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Отфрлете ја сликата од екранот"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Преглед на слика од екранот"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласовна помош"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Паричник"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Отклучување"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Уредот е заклучен"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Скенирање лице"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Отклучете за да користите"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Имаше проблем при преземањето на картичките. Обидете се повторно подоцна"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Поставки за заклучен екран"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Работен профил"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Авионски режим"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Нема да го слушнете следниот аларм <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-mk/tiles_states_strings.xml b/packages/SystemUI/res/values-mk/tiles_states_strings.xml index 9d0c49532bca..912746ae86b7 100644 --- a/packages/SystemUI/res/values-mk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-mk/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Исклучено"</item> <item msgid="6866424167599381915">"Вклучено"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Недостапно"</item> <item msgid="2710157085538036590">"Исклучено"</item> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 28f0238dff4a..552d228a3e41 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ഫോണ്"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"വോയ്സ് സഹായം"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"വാലറ്റ്"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"അണ്ലോക്ക് ചെയ്യുക"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"ഉപകരണം ലോക്ക് ചെയ്തു"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"മുഖം സ്കാൻ ചെയ്യുന്നു"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ഉപയോഗിക്കാൻ അൺലോക്ക് ചെയ്യുക"</string> <string name="wallet_error_generic" msgid="257704570182963611">"നിങ്ങളുടെ കാർഡുകൾ ലഭ്യമാക്കുന്നതിൽ ഒരു പ്രശ്നമുണ്ടായി, പിന്നീട് വീണ്ടും ശ്രമിക്കുക"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ലോക്ക് സ്ക്രീൻ ക്രമീകരണം"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"ഫ്ലൈറ്റ് മോഡ്"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>-നുള്ള നിങ്ങളുടെ അടുത്ത അലാറം കേൾക്കില്ല"</string> diff --git a/packages/SystemUI/res/values-ml/tiles_states_strings.xml b/packages/SystemUI/res/values-ml/tiles_states_strings.xml index af2b960317cc..bdbf600aee6c 100644 --- a/packages/SystemUI/res/values-ml/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ml/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"ഓഫാണ്"</item> <item msgid="6866424167599381915">"ഓണാണ്"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"ലഭ്യമല്ല"</item> <item msgid="2710157085538036590">"ഓഫാണ്"</item> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 42bae5193352..817fc1457fcb 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Таны апп, байгууллагад дэлгэцийн зураг авахыг зөвшөөрдөггүй"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Засах"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Дэлгэцийн агшныг засах"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Дэлгэцийн агшныг хуваалцах"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Ихийг багтаасан зураг авах"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Дэлгэцийн агшныг хаах"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Дэлгэцийн агшныг урьдчилан үзэх"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Утас"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Дуут туслах"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Түрийвч"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Тайлах"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Төхөөрөмжийг түгжсэн"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Скан хийх нүүр царай"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ашиглахын тулд түгжээг тайлах"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Таны картыг авахад асуудал гарлаа. Дараа дахин оролдоно уу"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Түгжигдсэн дэлгэцийн тохиргоо"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Ажлын профайл"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Нислэгийн горим"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>-т та дараагийн сэрүүлгээ сонсохгүй"</string> diff --git a/packages/SystemUI/res/values-mn/tiles_states_strings.xml b/packages/SystemUI/res/values-mn/tiles_states_strings.xml index 47a42ffa2b9a..81b1b1dd0454 100644 --- a/packages/SystemUI/res/values-mn/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-mn/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Унтраалттай"</item> <item msgid="6866424167599381915">"Асаалттай"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Боломжгүй"</item> <item msgid="2710157085538036590">"Унтраалттай"</item> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index f7004b345765..ccbf77b07231 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"फोन"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"व्हॉइस सहाय्य"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"वॉलेट"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"अनलॉक करा"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"डिव्हाइस लॉक केले"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"चेहरा स्कॅन करत आहे"</string> @@ -438,7 +440,7 @@ <string name="volume_ringer_status_normal" msgid="1339039682222461143">"रिंग करा"</string> <string name="volume_ringer_status_vibrate" msgid="6970078708957857825">"व्हायब्रेट"</string> <string name="volume_ringer_status_silent" msgid="3691324657849880883">"म्यूट करा"</string> - <string name="volume_stream_content_description_unmute" msgid="7729576371406792977">"%1$s. सशब्द करण्यासाठी टॅप करा."</string> + <string name="volume_stream_content_description_unmute" msgid="7729576371406792977">"%1$s. अनम्यूट करण्यासाठी टॅप करा."</string> <string name="volume_stream_content_description_vibrate" msgid="4858111994183089761">"%1$s. व्हायब्रेट सेट करण्यासाठी टॅप करा. प्रवेशयोग्यता सेवा म्यूट केल्या जाऊ शकतात."</string> <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. म्यूट करण्यासाठी टॅप करा. प्रवेशक्षमता सेवा म्यूट केल्या जाऊ शकतात."</string> <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. व्हायब्रेट सेट करण्यासाठी टॅप करा."</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"वापरण्यासाठी अनलॉक करा"</string> <string name="wallet_error_generic" msgid="257704570182963611">"तुमची कार्ड मिळवताना समस्या आली, कृपया नंतर पुन्हा प्रयत्न करा"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लॉक स्क्रीन सेटिंग्ज"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाईल"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"विमान मोड"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"तुम्ही तुमचा <xliff:g id="WHEN">%1$s</xliff:g> वाजता होणारा पुढील अलार्म ऐकणार नाही"</string> diff --git a/packages/SystemUI/res/values-mr/tiles_states_strings.xml b/packages/SystemUI/res/values-mr/tiles_states_strings.xml index 4a638b5967ca..560194a367ff 100644 --- a/packages/SystemUI/res/values-mr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-mr/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"बंद आहे"</item> <item msgid="6866424167599381915">"सुरू आहे"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"उपलब्ध नाही"</item> <item msgid="2710157085538036590">"बंद आहे"</item> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 35ba5a1eae73..82174abcff68 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -108,6 +108,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Bantuan Suara"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Dompet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Buka kunci"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Peranti dikunci"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Mengimbas wajah"</string> @@ -465,6 +467,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Buka kunci untuk menggunakan"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Terdapat masalah sewaktu mendapatkan kad anda. Sila cuba sebentar lagi"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Tetapan skrin kunci"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Mod pesawat"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Anda tidak akan mendengar penggera yang seterusnya <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-ms/tiles_states_strings.xml b/packages/SystemUI/res/values-ms/tiles_states_strings.xml index 93d4e6d7ebac..fef4b1dd19b2 100644 --- a/packages/SystemUI/res/values-ms/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ms/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Mati"</item> <item msgid="6866424167599381915">"Hidup"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Tidak tersedia"</item> <item msgid="2710157085538036590">"Mati"</item> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index d2722b2d0435..281ad883e15e 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -108,6 +108,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ဖုန်း"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"အသံ အကူအညီ"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"သော့ဖွင့်ရန်"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"စက်ပစ္စည်းကို လော့ခ်ချထားသည်"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"မျက်နှာ စကင်ဖတ်နေသည်"</string> @@ -465,6 +467,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"သုံးရန် လော့ခ်ဖွင့်ပါ"</string> <string name="wallet_error_generic" msgid="257704570182963611">"သင်၏ကတ်များ ရယူရာတွင် ပြဿနာရှိနေသည်၊ နောက်မှ ထပ်စမ်းကြည့်ပါ"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"လော့ခ်မျက်နှာပြင် ဆက်တင်များ"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"အလုပ် ပရိုဖိုင်"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"လေယာဉ်ပျံမုဒ်"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> ၌သင့်နောက်ထပ် နှိုးစက်ကို ကြားမည်မဟုတ်ပါ"</string> diff --git a/packages/SystemUI/res/values-my/tiles_states_strings.xml b/packages/SystemUI/res/values-my/tiles_states_strings.xml index 3adb16e0ff14..898fca3b81b3 100644 --- a/packages/SystemUI/res/values-my/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-my/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"ပိတ်"</item> <item msgid="6866424167599381915">"ဖွင့်"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"မရနိုင်ပါ"</item> <item msgid="2710157085538036590">"ပိတ်"</item> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index a5957cb3cf14..3e5f11d7a295 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonnummer"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Talehjelp"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Lås opp"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Enheten er låst"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skanning av ansikt"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås opp for å bruke"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Det oppsto et problem med henting av kortene. Prøv igjen senere"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Innstillinger for låseskjermen"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Work-profil"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Flymodus"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Du hører ikke neste innstilte alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-nb/tiles_states_strings.xml b/packages/SystemUI/res/values-nb/tiles_states_strings.xml index 8ebe050b8a36..c0e5b3aced19 100644 --- a/packages/SystemUI/res/values-nb/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-nb/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Av"</item> <item msgid="6866424167599381915">"På"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Utilgjengelig"</item> <item msgid="2710157085538036590">"Av"</item> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 89c66e331998..77cdd5108491 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"फोन"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज सहायता"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"वालेट"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"खोल्नुहोस्"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"यन्त्र लक गरिएको छ"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"अनुहार स्क्यान गर्दै"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"यो वालेट प्रयोग गर्न डिभाइस अनलक गर्नुहोस्"</string> <string name="wallet_error_generic" msgid="257704570182963611">"तपाईंका कार्डहरू प्राप्त गर्ने क्रममा समस्या भयो, कृपया पछि फेरि प्रयास गर्नुहोस्"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लक स्क्रिनसम्बन्धी सेटिङ"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाइल"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"हवाइजहाज मोड"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"तपाईँले आफ्नो अर्को अलार्म <xliff:g id="WHEN">%1$s</xliff:g> सुन्नुहुने छैन"</string> diff --git a/packages/SystemUI/res/values-ne/tiles_states_strings.xml b/packages/SystemUI/res/values-ne/tiles_states_strings.xml index a1cf9ac8d703..571e1280b0e7 100644 --- a/packages/SystemUI/res/values-ne/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ne/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"अफ छ"</item> <item msgid="6866424167599381915">"अन छ"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"उपलब्ध छैन"</item> <item msgid="2710157085538036590">"अफ छ"</item> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 530669bdbf1f..0e8fd0dab753 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Het maken van screenshots wordt niet toegestaan door de app of je organisatie"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Bewerken"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Screenshot bewerken"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Screenshot delen"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Meer opnemen"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Screenshot sluiten"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Voorbeeld van screenshot"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefoon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Spraakassistent"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portemonnee"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Ontgrendelen"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Apparaat vergrendeld"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Gezicht scannen"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ontgrendelen om te gebruiken"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Er is een probleem opgetreden bij het ophalen van je kaarten. Probeer het later opnieuw."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Instellingen voor vergrendelscherm"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Werkprofiel"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Vliegtuigmodus"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Je hoort je volgende wekker niet <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-nl/tiles_states_strings.xml b/packages/SystemUI/res/values-nl/tiles_states_strings.xml index 06b1048d04bf..9293f520e6aa 100644 --- a/packages/SystemUI/res/values-nl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-nl/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Uit"</item> <item msgid="6866424167599381915">"Aan"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Niet beschikbaar"</item> <item msgid="2710157085538036590">"Uit"</item> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index bc4e7d12654a..d02dafbaf7d4 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ଫୋନ୍"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ଭଏସ୍ ସହାୟକ"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"ୱାଲେଟ୍"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"ଅନଲକ୍ କରନ୍ତୁ"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"ଡିଭାଇସ୍ ଲକ୍ ହୋଇଯାଇଛି"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"ଫେସ୍ ସ୍କାନିଙ୍ଗ କରାଯାଉଛି"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ବ୍ୟବହାର କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string> <string name="wallet_error_generic" msgid="257704570182963611">"ଆପଣଙ୍କ କାର୍ଡଗୁଡ଼ିକ ପାଇବାରେ ଏକ ସମସ୍ୟା ହୋଇଥିଲା। ଦୟାକରି ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ସ୍କ୍ରିନ୍ ଲକ୍ ସେଟିଂସ୍"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"ୱର୍କ ପ୍ରୋଫାଇଲ୍"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"ଏରୋପ୍ଲେନ୍ ମୋଡ୍"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>ବେଳେ ଆପଣ ନିଜର ପରବର୍ତ୍ତୀ ଆଲାର୍ମ ଶୁଣିପାରିବେ ନାହିଁ"</string> diff --git a/packages/SystemUI/res/values-or/tiles_states_strings.xml b/packages/SystemUI/res/values-or/tiles_states_strings.xml index 7129c1195c1a..848d38294ae4 100644 --- a/packages/SystemUI/res/values-or/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-or/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"ବନ୍ଦ ଅଛି"</item> <item msgid="6866424167599381915">"ଚାଲୁ ଅଛି"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"ଉପଲବ୍ଧ ନାହିଁ"</item> <item msgid="2710157085538036590">"ବନ୍ଦ ଅଛି"</item> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index de918aaaaf24..f3ea0515bb5e 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ਫ਼ੋਨ ਕਰੋ"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ਅਵਾਜ਼ੀ ਸਹਾਇਕ"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"ਵਾਲੇਟ"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"ਅਣਲਾਕ ਕਰੋ"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"ਡੀਵਾਈਸ ਲਾਕ ਹੈ"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"ਚਿਹਰਾ ਸਕੈਨ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string> <string name="wallet_error_generic" msgid="257704570182963611">"ਤੁਹਾਡੇ ਕਾਰਡ ਪ੍ਰਾਪਤ ਕਰਨ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਆਈ, ਕਿਰਪਾ ਕਰਕੇ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"ਤੁਸੀਂ <xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ ਆਪਣਾ ਅਗਲਾ ਅਲਾਰਮ ਨਹੀਂ ਸੁਣੋਗੇ"</string> diff --git a/packages/SystemUI/res/values-pa/tiles_states_strings.xml b/packages/SystemUI/res/values-pa/tiles_states_strings.xml index fbb38883381b..409b4566bde4 100644 --- a/packages/SystemUI/res/values-pa/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pa/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"ਬੰਦ ਹੈ"</item> <item msgid="6866424167599381915">"ਚਾਲੂ ਹੈ"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"ਅਣਉਪਲਬਧ ਹੈ"</item> <item msgid="2710157085538036590">"ਬੰਦ ਹੈ"</item> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 0245d36502c1..15326459487f 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asystent głosowy"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portfel"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Odblokuj"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Urządzenie zablokowane"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skanowanie twarzy"</string> @@ -470,6 +472,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odblokuj, aby użyć"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Podczas pobierania kart wystąpił problem. Spróbuj ponownie później."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ustawienia ekranu blokady"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Profil służbowy"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Tryb samolotowy"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Nie usłyszysz swojego następnego alarmu <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml index 1b213b300af5..2e6df6830a8b 100644 --- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Wyłączony"</item> <item msgid="6866424167599381915">"Włączony"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Niedostępny"</item> <item msgid="2710157085538036590">"Wyłączony"</item> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 75b0b24e2553..226220bedbf1 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"O app ou a organização não permitem capturas de tela"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Editar"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Editar captura de tela"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Compartilhar captura de tela"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturar mais"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Dispensar captura de tela"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Visualização de captura de tela"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefone"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistência de voz"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Verificando rosto"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao carregar os cards. Tente novamente mais tarde"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configurações de tela de bloqueio"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avião"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Você não ouvirá o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml index 5801d30d6efc..66472213bbbe 100644 --- a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Desativado"</item> <item msgid="6866424167599381915">"Ativado"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Indisponível"</item> <item msgid="2710157085538036590">"Desativado"</item> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 94946af56daf..d98900f6ae62 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"A app ou a sua entidade não permitem tirar capturas de ecrã"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Editar"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Editar captura de ecrã"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Partilhar captura de ecrã"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturar mais"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ignorar captura de ecrã"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Pré-visualização da captura de ecrã"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telemóvel"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistente de voz"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"A analisar o rosto…"</string> @@ -212,8 +213,8 @@ <string name="accessibility_clear_all" msgid="970525598287244592">"Limpar todas as notificações."</string> <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string> <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192"> - <item quantity="other">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item> <item quantity="one">Mais <xliff:g id="NUMBER_0">%s</xliff:g> notificação no grupo.</item> + <item quantity="other">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item> </plurals> <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"O ecrã está bloqueado na orientação horizontal."</string> <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"O ecrã está bloqueado na orientação vertical."</string> @@ -262,8 +263,8 @@ <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"A ativar..."</string> <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Poup. dados ativada"</string> <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976"> - <item quantity="other">%d dispositivos</item> <item quantity="one">%d dispositivo</item> + <item quantity="other">%d dispositivos</item> </plurals> <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Lanterna"</string> <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Câmara em utilização"</string> @@ -342,8 +343,8 @@ <string name="user_add_user_message_short" msgid="2599370307878014791">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço.\n\nQualquer utilizador pode atualizar apps para todos os outros utilizadores."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite de utilizadores alcançado"</string> <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398"> - <item quantity="other">Pode adicionar até <xliff:g id="COUNT">%d</xliff:g> utilizadores.</item> <item quantity="one">Apenas é possível criar um utilizador.</item> + <item quantity="other">Pode adicionar até <xliff:g id="COUNT">%d</xliff:g> utilizadores.</item> </plurals> <string name="user_remove_user_title" msgid="9124124694835811874">"Remover o utilizador?"</string> <string name="user_remove_user_message" msgid="6702834122128031833">"Serão eliminados todos os dados e todas as aplicações deste utilizador."</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para utilizar"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao obter os seus cartões. Tente novamente mais tarde."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Definições do ecrã de bloqueio"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Modo de avião"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Não vai ouvir o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string> @@ -529,12 +534,12 @@ <string name="snooze_undo" msgid="2738844148845992103">"Anular"</string> <string name="snoozed_for_time" msgid="7586689374860469469">"Suspensa por <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> <plurals name="snoozeHourOptions" formatted="false" msgid="2066838694120718170"> - <item quantity="other">%d horas</item> <item quantity="one">%d hora</item> + <item quantity="other">%d horas</item> </plurals> <plurals name="snoozeMinuteOptions" formatted="false" msgid="8998483159208055980"> - <item quantity="other">%d minutos</item> <item quantity="one">%d minuto</item> + <item quantity="other">%d minutos</item> </plurals> <string name="battery_detail_switch_title" msgid="6940976502957380405">"Poupança de bateria"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"Botão <xliff:g id="NAME">%1$s</xliff:g>"</string> @@ -756,8 +761,8 @@ <string name="quick_controls_title" msgid="6839108006171302273">"Controlos de dispositivos"</string> <string name="controls_providers_title" msgid="6879775889857085056">"Escolha uma app para adicionar controlos"</string> <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380"> - <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controlos adicionados.</item> <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> controlo adicionado.</item> + <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controlos adicionados.</item> </plurals> <string name="controls_removed" msgid="3731789252222856959">"Removido"</string> <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado aos favoritos"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml index 9ee9fc2a3815..fc3795a0b079 100644 --- a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Desligado"</item> <item msgid="6866424167599381915">"Ligado"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Indisponível"</item> <item msgid="2710157085538036590">"Desligado"</item> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 75b0b24e2553..226220bedbf1 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"O app ou a organização não permitem capturas de tela"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Editar"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Editar captura de tela"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Compartilhar captura de tela"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturar mais"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Dispensar captura de tela"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Visualização de captura de tela"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefone"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistência de voz"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Verificando rosto"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao carregar os cards. Tente novamente mais tarde"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configurações de tela de bloqueio"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avião"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Você não ouvirá o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-pt/tiles_states_strings.xml b/packages/SystemUI/res/values-pt/tiles_states_strings.xml index 5801d30d6efc..66472213bbbe 100644 --- a/packages/SystemUI/res/values-pt/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pt/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Desativado"</item> <item msgid="6866424167599381915">"Ativado"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Indisponível"</item> <item msgid="2710157085538036590">"Desativado"</item> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index d59403eeaec9..9e4c7da158d2 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Crearea capturilor de ecran nu este permisă de aplicație sau de organizația dvs."</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Editați"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Editați captura de ecran"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Trimiteți captura de ecran"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Surprindeți mai mult"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Închideți captura de ecran"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Previzualizare a capturii de ecran"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistent vocal"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Deblocați"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispozitiv blocat"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanarea chipului"</string> @@ -468,6 +469,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Deblocați pentru a folosi"</string> <string name="wallet_error_generic" msgid="257704570182963611">"A apărut o problemă la preluarea cardurilor. Încercați din nou mai târziu"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setările ecranului de blocare"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Profil de serviciu"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Mod Avion"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Nu veți auzi următoarea alarmă <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-ro/tiles_states_strings.xml b/packages/SystemUI/res/values-ro/tiles_states_strings.xml index 3f564245c11f..53d5fa20c755 100644 --- a/packages/SystemUI/res/values-ro/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ro/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Dezactivat"</item> <item msgid="6866424167599381915">"Activat"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Indisponibilă"</item> <item msgid="2710157085538036590">"Dezactivată"</item> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 1364c1d443ec..66e32f21cfbf 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -108,6 +108,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон."</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Аудиоподсказки"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Кошелек"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Разблокировать."</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Устройство заблокировано"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Сканирование лица"</string> @@ -471,6 +473,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Разблокировать для использования"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Не удалось получить информацию о картах. Повторите попытку позже."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Настройки заблокированного экрана"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Рабочий профиль"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Режим полета"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Следующий будильник: <xliff:g id="WHEN">%1$s</xliff:g>. Звук отключен."</string> diff --git a/packages/SystemUI/res/values-ru/tiles_states_strings.xml b/packages/SystemUI/res/values-ru/tiles_states_strings.xml index 29556da73c33..14098fcd1964 100644 --- a/packages/SystemUI/res/values-ru/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ru/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Откл."</item> <item msgid="6866424167599381915">"Вкл."</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Функция недоступна"</item> <item msgid="2710157085538036590">"Откл."</item> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index a780614e2784..a25672c37c61 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"දුරකථනය"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"හඬ සහාය"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"පසුම්බිය"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"අඟුල අරින්න"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"උපාංගය අගුලු දමා ඇත"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"මුහුණ ස්කෑන් කිරීම"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"භාවිත කිරීමට අගුලු හරින්න"</string> <string name="wallet_error_generic" msgid="257704570182963611">"ඔබගේ කාඩ්පත ලබා ගැනීමේ ගැටලුවක් විය, කරුණාකර පසුව නැවත උත්සාහ කරන්න"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"අගුලු තිර සැකසීම්"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"කාර්යාල පැතිකඩ"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"ගුවන්යානා ප්රකාරය"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"ඔබට ඔබේ ඊළඟ එලාමය <xliff:g id="WHEN">%1$s</xliff:g> නොඇසෙනු ඇත"</string> diff --git a/packages/SystemUI/res/values-si/tiles_states_strings.xml b/packages/SystemUI/res/values-si/tiles_states_strings.xml index 9ca8198b24ca..ed39e4ac29a8 100644 --- a/packages/SystemUI/res/values-si/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-si/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"අක්රියයි"</item> <item msgid="6866424167599381915">"සක්රියයි"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"නොමැත"</item> <item msgid="2710157085538036590">"අක්රියයි"</item> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 5e0b172a01ab..4c672bf80477 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Upraviť"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Upraviť snímku obrazovky"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Zdieľať snímku obrazovky"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Zachytiť viac"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Zavrieť snímku obrazovky"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Ukážka snímky obrazovky"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefón"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Hlasový asistent"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Peňaženka"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Odomknúť"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Zariadenie je uzamknuté"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skenovanie tváre"</string> @@ -471,6 +472,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odomknúť a použiť"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Pri načítavaní kariet sa vyskytol problém. Skúste to neskôr."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavenia uzamknutej obrazovky"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Pracovný profil"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Režim v lietadle"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Váš budík o <xliff:g id="WHEN">%1$s</xliff:g> sa nespustí"</string> diff --git a/packages/SystemUI/res/values-sk/tiles_states_strings.xml b/packages/SystemUI/res/values-sk/tiles_states_strings.xml index 2e80a8035a51..817e8fbb5345 100644 --- a/packages/SystemUI/res/values-sk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sk/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Vypnuté"</item> <item msgid="6866424167599381915">"Zapnuté"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Nie je k dispozícii"</item> <item msgid="2710157085538036590">"Vypnuté"</item> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 339bad503d11..43df9e7bdf7a 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovni pomočnik"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Google Denarnica"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Odkleni"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Naprava je zaklenjena."</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Optično branje obraza"</string> @@ -470,6 +472,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odklenite za uporabo"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Pri pridobivanju kartic je prišlo do težave. Poskusite znova pozneje."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavitve zaklepanja zaslona"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Profil za Android Work"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Način za letalo"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Naslednjega alarma ob <xliff:g id="WHEN">%1$s</xliff:g> ne boste slišali"</string> diff --git a/packages/SystemUI/res/values-sl/tiles_states_strings.xml b/packages/SystemUI/res/values-sl/tiles_states_strings.xml index f1d1aabb23ca..6f6a8f128afd 100644 --- a/packages/SystemUI/res/values-sl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sl/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Izklopljeno"</item> <item msgid="6866424167599381915">"Vklopljeno"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Ni na voljo"</item> <item msgid="2710157085538036590">"Izklopljeno"</item> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index bddfcbbf0f53..bc9018772262 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -108,6 +108,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefoni"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ndihma zanore"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Shkyç"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Pajisja është e kyçur"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Po skanon fytyrën"</string> @@ -465,6 +467,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Shkyçe për ta përdorur"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Pati një problem me marrjen e kartave të tua. Provo përsëri më vonë"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Cilësimet e ekranit të kyçjes"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Profili i punës"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Modaliteti i aeroplanit"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Nuk do ta dëgjosh alarmin e radhës në <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-sq/tiles_states_strings.xml b/packages/SystemUI/res/values-sq/tiles_states_strings.xml index 83069c9e970a..a88c5305e4e4 100644 --- a/packages/SystemUI/res/values-sq/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sq/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Joaktiv"</item> <item msgid="6866424167599381915">"Aktiv"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Nuk ofrohet"</item> <item msgid="2710157085538036590">"Joaktiv"</item> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 5035e8a2df1c..0606d0e5fe51 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Апликација или организација не дозвољавају прављење снимака екрана"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Измени"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Измените снимак екрана"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Делите снимак екрана"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Снимите још"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Одбаците снимак екрана"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Преглед снимка екрана"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласовна помоћ"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Новчаник"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Откључајте"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Уређај је закључан"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Скенирање лица"</string> @@ -468,6 +469,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Откључај ради коришћења"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Дошло је до проблема при преузимању картица. Пробајте поново касније"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Подешавања закључаног екрана"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Пословни профил"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Режим рада у авиону"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Нећете чути следећи аларм у <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-sr/tiles_states_strings.xml b/packages/SystemUI/res/values-sr/tiles_states_strings.xml index cec05da86d0c..e2f9c621fc1d 100644 --- a/packages/SystemUI/res/values-sr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sr/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Искључено"</item> <item msgid="6866424167599381915">"Укључено"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Недоступно"</item> <item msgid="2710157085538036590">"Искључено"</item> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 79aac89696bc..60b009754149 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller organisationen tillåter inte att du tar skärmbilder"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Redigera"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Redigera skärmbild"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Dela skärmbild"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Fånga mer"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Stäng skärmbild"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Förhandsgranskning av skärmbild"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Mobil"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Röstassistent"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Lås upp"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Enheten är låst"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Registrerar ansikte"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås upp för att använda"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Det gick inte att hämta dina kort. Försök igen senare."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Inställningar för låsskärm"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Jobbprofil"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Flygplansläge"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Nästa alarm, kl. <xliff:g id="WHEN">%1$s</xliff:g>, kommer inte att höras"</string> diff --git a/packages/SystemUI/res/values-sv/tiles_states_strings.xml b/packages/SystemUI/res/values-sv/tiles_states_strings.xml index dbe32daea971..a7ba12b565e2 100644 --- a/packages/SystemUI/res/values-sv/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sv/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Av"</item> <item msgid="6866424167599381915">"På"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Inte tillgängligt"</item> <item msgid="2710157085538036590">"Av"</item> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index a4d0118f2bfa..22e138f02920 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Programu au shirika lako halikuruhusu kupiga picha za skrini"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Badilisha"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Badilisha picha ya skrini"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Shiriki picha ya skrini"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Nasa zaidi"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ondoa picha ya skrini"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Onyesho la kukagua picha ya skrini"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Simu"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Mapendekezo ya Sauti"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Fungua"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Kifaa kimefungwa"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Inachanganua uso"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Fungua ili utumie"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Hitilafu imetokea wakati wa kuleta kadi zako, tafadhali jaribu tena baadaye"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Mipangilio ya kufunga skrini"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Wasifu wa kazini"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Hali ya ndegeni"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Hutasikia kengele yako inayofuata ya saa <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-sw/tiles_states_strings.xml b/packages/SystemUI/res/values-sw/tiles_states_strings.xml index 93f99b725ccf..f1fbf387d8ba 100644 --- a/packages/SystemUI/res/values-sw/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-sw/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Kimezimwa"</item> <item msgid="6866424167599381915">"Kimewashwa"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Hakipatikani"</item> <item msgid="2710157085538036590">"Kimezimwa"</item> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 430d00bca667..c2a3ed4b547a 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ஸ்கிரீன் ஷாட்டுகளை எடுப்பதை, ஆப்ஸ் அல்லது உங்கள் நிறுவனம் அனுமதிக்கவில்லை"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"திருத்து"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"ஸ்கிரீன்ஷாட்டைத் திருத்தும்"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"ஸ்கிரீன்ஷாட்டைப் பகிர்"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"கூடுதலாகப் படமெடு"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ஸ்கிரீன்ஷாட்டை நிராகரிக்கும்"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"ஸ்கிரீன்ஷாட்டின் மாதிரிக்காட்சி"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ஃபோன்"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"குரல் உதவி"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"வாலட்"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"அன்லாக் செய்"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"சாதனம் பூட்டப்பட்டுள்ளது"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"முகத்தை ஸ்கேன் செய்கிறது"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"பயன்படுத்துவதற்கு அன்லாக் செய்க"</string> <string name="wallet_error_generic" msgid="257704570182963611">"உங்கள் கார்டுகளின் விவரங்களைப் பெறுவதில் சிக்கல் ஏற்பட்டது, பிறகு முயலவும்"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"பூட்டுத் திரை அமைப்புகள்"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"பணிக் கணக்கு"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"விமானப் பயன்முறை"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"அடுத்த அலாரத்தை <xliff:g id="WHEN">%1$s</xliff:g> மணிக்கு கேட்க மாட்டீர்கள்"</string> diff --git a/packages/SystemUI/res/values-ta/tiles_states_strings.xml b/packages/SystemUI/res/values-ta/tiles_states_strings.xml index d2ba6a5c7c93..b2cc840d7a3d 100644 --- a/packages/SystemUI/res/values-ta/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ta/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"முடக்கப்பட்டுள்ளது"</item> <item msgid="6866424167599381915">"இயக்கப்பட்டுள்ளது"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"கிடைக்கவில்லை"</item> <item msgid="2710157085538036590">"முடக்கப்பட்டுள்ளது"</item> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 2c392db40cfe..d8a4c2141722 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"ఫోన్"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"వాయిస్ అసిస్టెంట్"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"వాలెట్"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"అన్లాక్ చేయి"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"పరికరం లాక్ చేయబడింది"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"ముఖాన్ని స్కాన్ చేస్తోంది"</string> @@ -450,7 +452,7 @@ <string name="volume_dialog_title" msgid="6502703403483577940">"%s వాల్యూమ్ నియంత్రణలు"</string> <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"కాల్స్ మరియు నోటిఫికేషన్లు రింగ్ అవుతాయి (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"సిస్టమ్ UI ట్యూనర్"</string> - <string name="status_bar" msgid="4357390266055077437">"స్థితి పట్టీ"</string> + <string name="status_bar" msgid="4357390266055077437">"స్టేటస్ పట్టీ"</string> <string name="demo_mode" msgid="263484519766901593">"సిస్టమ్ UI డెమో మోడ్"</string> <string name="enable_demo_mode" msgid="3180345364745966431">"డెమో మోడ్ ప్రారంభించండి"</string> <string name="show_demo_mode" msgid="3677956462273059726">"డెమో మోడ్ చూపు"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ఉపయోగించడానికి అన్లాక్ చేయండి"</string> <string name="wallet_error_generic" msgid="257704570182963611">"మీ కార్డ్లను పొందడంలో సమస్య ఉంది, దయచేసి తర్వాత మళ్లీ ట్రై చేయండి"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"లాక్ స్క్రీన్ సెట్టింగ్లు"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"ఆఫీస్ ప్రొఫైల్"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"ఎయిర్ప్లేన్ మోడ్"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"మీరు <xliff:g id="WHEN">%1$s</xliff:g> సెట్ చేసిన మీ తర్వాత అలారం మీకు వినిపించదు"</string> @@ -483,7 +489,7 @@ <string name="enable_bluetooth_message" msgid="6740938333772779717">"మీ కీబోర్డ్ను మీ టాబ్లెట్తో కనెక్ట్ చేయడానికి, మీరు ముందుగా బ్లూటూత్ ఆన్ చేయాలి."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ఆన్ చేయి"</string> <string name="tuner_full_importance_settings" msgid="1388025816553459059">"పవర్ నోటిఫికేషన్ నియంత్రణలు"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"పవర్ నోటిఫికేషన్ నియంత్రణలతో, మీరు యాప్ నోటిఫికేషన్ల కోసం ప్రాముఖ్యత స్థాయిని 0 నుండి 5 వరకు సెట్ చేయవచ్చు. \n\n"<b>"స్థాయి 5"</b>" \n- నోటిఫికేషన్ లిస్ట్ పైభాగంలో చూపబడతాయి \n- పూర్తి స్క్రీన్ అంతరాయం అనుమతించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 4"</b>\n"- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 3"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n\n"<b>"స్థాయి 2"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం మరియు వైబ్రేషన్ చేయవు \n\n"<b>"స్థాయి 1"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం లేదా వైబ్రేట్ చేయవు \n- లాక్ స్క్రీన్ మరియు స్థితి పట్టీ నుండి దాచబడతాయి \n- నోటిఫికేషన్ లిస్ట్ దిగువ భాగంలో చూపబడతాయి \n\n"<b>"స్థాయి 0"</b>" \n- యాప్ నుండి అన్ని నోటిఫికేషన్లు బ్లాక్ చేయబడతాయి"</string> + <string name="power_notification_controls_description" msgid="1334963837572708952">"పవర్ నోటిఫికేషన్ కంట్రోల్స్ సాయంతో, మీరు యాప్ నోటిఫికేషన్లకు ప్రాముఖ్యతా స్థాయిని 0 నుండి 5 వరకు సెట్ చేయవచ్చు. \n\n"<b>"స్థాయి 5"</b>" \n- నోటిఫికేషన్ లిస్ట్ పైభాగంలో చూపబడతాయి \n- ఫుల్-స్క్రీన్ అంతరాయం అనుమతించబడుతుంది \n- ఎల్లప్పుడూ క్విక్ వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 4"</b>\n"- ఫుల్-స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎల్లప్పుడూ క్విక్ వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 3"</b>" \n- ఫుల్-స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ క్విక్ వీక్షణ అందించబడదు \n\n"<b>"స్థాయి 2"</b>" \n- ఫుల్-స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ క్విక్ వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం మరియు వైబ్రేషన్ చేయవు \n\n"<b>"స్థాయి 1"</b>" \n- ఫుల్-స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ క్విక్ వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం లేదా వైబ్రేట్ చేయవు \n- లాక్ స్క్రీన్, స్టేటస్ బార్ల నుండి దాచబడతాయి \n- నోటిఫికేషన్ లిస్ట్ దిగువ భాగంలో చూపబడతాయి \n\n"<b>"స్థాయి 0"</b>" \n- యాప్ నుండి అన్ని నోటిఫికేషన్లు బ్లాక్ చేయబడతాయి"</string> <string name="inline_done_button" msgid="6043094985588909584">"పూర్తయింది"</string> <string name="inline_ok_button" msgid="603075490581280343">"అప్లయి చేయి"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"నోటిఫికేషన్లను ఆఫ్ చేయి"</string> @@ -803,7 +809,7 @@ <string name="controls_error_removed_title" msgid="1207794911208047818">"కంట్రోల్ అందుబాటులో లేదు"</string> <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>ను యాక్సెస్ చేయడం సాధ్యపడలేదు. <xliff:g id="APPLICATION">%2$s</xliff:g> యాప్ను తనిఖీ చేసి, కంట్రోల్ ఇప్పటికీ అందుబాటులో ఉందని, యాప్ సెట్టింగ్లు మారలేదని నిర్ధారించుకోండి."</string> <string name="controls_open_app" msgid="483650971094300141">"యాప్ను తెరువు"</string> - <string name="controls_error_generic" msgid="352500456918362905">"స్థితిని లోడ్ చేయడం సాధ్యపడదు"</string> + <string name="controls_error_generic" msgid="352500456918362905">"స్టేటస్ లోడ్ చేయడం సాధ్యపడలేదు"</string> <string name="controls_error_failed" msgid="960228639198558525">"ఎర్రర్, మళ్లీ ప్రయత్నించండి"</string> <string name="controls_menu_add" msgid="4447246119229920050">"కంట్రోల్స్ను జోడించండి"</string> <string name="controls_menu_edit" msgid="890623986951347062">"కంట్రోల్స్ను ఎడిట్ చేయండి"</string> diff --git a/packages/SystemUI/res/values-te/tiles_states_strings.xml b/packages/SystemUI/res/values-te/tiles_states_strings.xml index bbe5c8ee547e..3a2dca0943e5 100644 --- a/packages/SystemUI/res/values-te/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-te/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"ఆఫ్లో ఉంది"</item> <item msgid="6866424167599381915">"ఆన్లో ఉంది"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"అందుబాటులో లేదు"</item> <item msgid="2710157085538036590">"ఆఫ్లో ఉంది"</item> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 8e54bc135387..59226787fda7 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -108,6 +108,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"โทรศัพท์"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ตัวช่วยเสียง"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"ปลดล็อก"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"อุปกรณ์ถูกล็อก"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"กำลังสแกนใบหน้า"</string> @@ -465,6 +467,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ปลดล็อกเพื่อใช้"</string> <string name="wallet_error_generic" msgid="257704570182963611">"เกิดปัญหาในการดึงข้อมูลบัตรของคุณ โปรดลองอีกครั้งในภายหลัง"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"การตั้งค่าหน้าจอล็อก"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"โปรไฟล์งาน"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"โหมดบนเครื่องบิน"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"คุณจะไม่ได้ยินเสียงปลุกครั้งถัดไปในเวลา <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-th/tiles_states_strings.xml b/packages/SystemUI/res/values-th/tiles_states_strings.xml index 2152e1c4a236..170a9bee9721 100644 --- a/packages/SystemUI/res/values-th/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-th/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"ปิด"</item> <item msgid="6866424167599381915">"เปิด"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"ไม่พร้อมใช้งาน"</item> <item msgid="2710157085538036590">"ปิด"</item> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 218b21fcaa9b..05efac26cf13 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -108,6 +108,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telepono"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"I-unlock"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Naka-lock ang device"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Sina-scan ang mukha"</string> @@ -465,6 +467,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"I-unlock para magamit"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Nagkaproblema sa pagkuha ng iyong mga card, pakisubukan ulit sa ibang pagkakataon"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Mga setting ng lock screen"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Profile sa trabaho"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Hindi mo maririnig ang iyong susunod na alarm ng <xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-tl/tiles_states_strings.xml b/packages/SystemUI/res/values-tl/tiles_states_strings.xml index 83b9f1864ffb..6935782f5c1d 100644 --- a/packages/SystemUI/res/values-tl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-tl/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Naka-off"</item> <item msgid="6866424167599381915">"Naka-on"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Hindi available"</item> <item msgid="2710157085538036590">"Naka-off"</item> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 8d1c890c7d92..87803f346acb 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Uygulama veya kuruluşunuz, ekran görüntüsü alınmasına izin vermiyor."</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Düzenle"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Ekran görüntüsünü düzenle"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Ekranı paylaş"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Daha fazla ekran görüntüsü al"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ekran görüntüsünü kapat"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekran görüntüsü önizlemesi"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Sesli Yardım"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Cüzdan"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Kilidi aç"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Cihaz kilitlendi"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Yüz taranıyor"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Kullanmak için kilidi aç"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Kartlarınız alınırken bir sorun oluştu. Lütfen daha sonra tekrar deneyin"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Kilit ekranı ayarları"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Uçak modu"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> olarak ayarlanmış bir sonraki alarmınızı duymayacaksınız"</string> diff --git a/packages/SystemUI/res/values-tr/tiles_states_strings.xml b/packages/SystemUI/res/values-tr/tiles_states_strings.xml index c550004a0a5f..34179b5508e5 100644 --- a/packages/SystemUI/res/values-tr/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-tr/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Kapalı"</item> <item msgid="6866424167599381915">"Açık"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Kullanılamıyor"</item> <item msgid="2710157085538036590">"Kapalı"</item> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index b63571400917..0dbb0db90537 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Додаток або адміністратор вашої організації не дозволяють робити знімки екрана"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Редагувати"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Редагувати знімок екрана"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Поділитися знімком екрана"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Включити більше деталей"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Закрити знімок екрана"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Перегляд знімка екрана"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Номер телефону"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Голосові підказки"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Гаманець"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Розблокувати"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Пристрій заблоковано"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Сканування обличчя"</string> @@ -471,6 +472,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Розблокувати, щоб використовувати"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Не вдалось отримати ваші картки. Повторіть спробу пізніше."</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Параметри блокування екрана"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Робочий профіль"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Режим польоту"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Наступний сигнал о <xliff:g id="WHEN">%1$s</xliff:g> не пролунає"</string> diff --git a/packages/SystemUI/res/values-uk/tiles_states_strings.xml b/packages/SystemUI/res/values-uk/tiles_states_strings.xml index 642064748860..21e0128fd145 100644 --- a/packages/SystemUI/res/values-uk/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-uk/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Вимкнено"</item> <item msgid="6866424167599381915">"Увімкнено"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Недоступно"</item> <item msgid="2710157085538036590">"Вимкнено"</item> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index ca50746e7eb5..1d4b0b0f3662 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"ترمیم کریں"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"اسکرین شاٹ میں ترمیم کریں"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"اسکرین شاٹ کا اشتراک کریں"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"مزید کیپچر کریں"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"اسکرین شاٹ برخاست کریں"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"اسکرین شاٹ کا پیش منظر"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"فون"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"صوتی معاون"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"غیر مقفل کریں"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"آلہ مقفل کر دیا گیا"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"اسکیننگ چہرہ"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"استعمال کرنے کے لیے غیر مقفل کریں"</string> <string name="wallet_error_generic" msgid="257704570182963611">"آپ کے کارڈز حاصل کرنے میں ایک مسئلہ درپیش تھا، براہ کرم بعد میں دوبارہ کوشش کریں"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"مقفل اسکرین کی ترتیبات"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"دفتری پروفائل"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"ہوائی جہاز وضع"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"آپ کو <xliff:g id="WHEN">%1$s</xliff:g> بجے اپنا اگلا الارم سنائی نہیں دے گا"</string> diff --git a/packages/SystemUI/res/values-ur/tiles_states_strings.xml b/packages/SystemUI/res/values-ur/tiles_states_strings.xml index b8d8cf54cf81..71f2a088a559 100644 --- a/packages/SystemUI/res/values-ur/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-ur/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"آف ہے"</item> <item msgid="6866424167599381915">"آن ہے"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"دستیاب نہیں ہے"</item> <item msgid="2710157085538036590">"آف ہے"</item> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index a3955ad5dfae..eb02d157e603 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ovozli yordam"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Qulfdan chiqarish"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Qurilma qulflandi"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Yuzni skanerlash"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Foydalanish uchun qulfdan chiqarish"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Bildirgilarni yuklashda xatolik yuz berdi, keyinroq qaytadan urining"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Qulflangan ekran sozlamalari"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Ish profili"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Parvoz rejimi"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Keyingi signal (<xliff:g id="WHEN">%1$s</xliff:g>) chalinmaydi"</string> diff --git a/packages/SystemUI/res/values-uz/tiles_states_strings.xml b/packages/SystemUI/res/values-uz/tiles_states_strings.xml index dad93cbaa405..f69166e61995 100644 --- a/packages/SystemUI/res/values-uz/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-uz/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Oʻchiq"</item> <item msgid="6866424167599381915">"Yoniq"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Ishlamaydi"</item> <item msgid="2710157085538036590">"Oʻchiq"</item> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 3396f982353f..5444f4c48880 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ứng dụng hoặc tổ chức của bạn không cho phép chụp ảnh màn hình"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Chỉnh sửa"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Chỉnh sửa ảnh chụp màn hình"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Chia sẻ ảnh chụp màn hình"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Chụp thêm"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Đóng ảnh chụp màn hình"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Xem trước ảnh chụp màn hình"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Điện thoại"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Trợ lý thoại"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Ví"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Mở khóa"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Đã khóa thiết bị"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Quét tìm khuôn mặt"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Mở khóa để sử dụng"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Đã xảy ra sự cố khi tải thẻ của bạn. Vui lòng thử lại sau"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Cài đặt màn hình khóa"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Hồ sơ công việc"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Chế độ máy bay"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Bạn sẽ không nghe thấy báo thức tiếp theo lúc <xliff:g id="WHEN">%1$s</xliff:g> của mình"</string> diff --git a/packages/SystemUI/res/values-vi/tiles_states_strings.xml b/packages/SystemUI/res/values-vi/tiles_states_strings.xml index df16b221224b..a973ffce116e 100644 --- a/packages/SystemUI/res/values-vi/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-vi/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Đang tắt"</item> <item msgid="6866424167599381915">"Đang bật"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Không hoạt động"</item> <item msgid="2710157085538036590">"Đang tắt"</item> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 54c329c0e95d..e54fa0d666a0 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"电话"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"语音助理"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"电子钱包"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"解锁"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"设备已锁定"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"正在扫描面孔"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解锁设备即可使用"</string> <string name="wallet_error_generic" msgid="257704570182963611">"获取您的卡片时出现问题,请稍后重试"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"锁定屏幕设置"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"工作资料"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"飞行模式"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"您在<xliff:g id="WHEN">%1$s</xliff:g>将不会听到下次闹钟响铃"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml index 0bf03225b2a5..e4a6dcd37944 100644 --- a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"已关闭"</item> <item msgid="6866424167599381915">"已开启"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"不可用"</item> <item msgid="2710157085538036590">"已关闭"</item> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index f210619f3702..d7915549912f 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -107,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"語音助手"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"電子錢包"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"解鎖"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"裝置已上鎖"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"掃瞄緊面孔"</string> @@ -464,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解鎖即可使用"</string> <string name="wallet_error_generic" msgid="257704570182963611">"擷取資訊卡時發生問題,請稍後再試。"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"上鎖畫面設定"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"工作設定檔"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"飛行模式"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"您不會<xliff:g id="WHEN">%1$s</xliff:g>聽到鬧鐘"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml index 7339a5231bf9..4e6af224e668 100644 --- a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"已關閉"</item> <item msgid="6866424167599381915">"已開啟"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"無法使用"</item> <item msgid="2710157085538036590">"已關閉"</item> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index f96c36af6a46..628e4d4d3bbc 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"這個應用程式或貴機構不允許擷取螢幕畫面"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"編輯"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"編輯螢幕截圖"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"分享螢幕截圖"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"擴大螢幕截圖範圍"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"關閉螢幕截圖"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"螢幕截圖預覽"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"語音小幫手"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"電子錢包"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"解除鎖定"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"裝置已鎖定"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"掃描臉孔"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解鎖即可使用"</string> <string name="wallet_error_generic" msgid="257704570182963611">"擷取卡片時發生問題,請稍後再試"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"螢幕鎖定設定"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"工作資料夾"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"飛航模式"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"你不會聽到下一個<xliff:g id="WHEN">%1$s</xliff:g> 的鬧鐘"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml index 7339a5231bf9..4e6af224e668 100644 --- a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"已關閉"</item> <item msgid="6866424167599381915">"已開啟"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"無法使用"</item> <item msgid="2710157085538036590">"已關閉"</item> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index d06b166cfefc..cea362b25b45 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ukuthatha izithombe-skrini akuvunyelwe uhlelo lokusebenza noma inhlangano yakho"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Hlela"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Hlela isithombe-skrini"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Yabelana ngesithombe-skrini"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Thwebula okuningi"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Cashisa isithombe-skrini"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Ukubuka kuqala isithombe-skrini"</string> @@ -108,6 +107,8 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Ifoni"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Isisekeli sezwi"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"I-wallet"</string> + <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) --> + <skip /> <string name="accessibility_unlock_button" msgid="122785427241471085">"Vula"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Idivayisi ikhiyiwe"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Ukuskena ubuso"</string> @@ -465,6 +466,10 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Vula ukuze usebenzise"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Kube khona inkinga yokuthola amakhadi akho, sicela uzame futhi ngemuva kwesikhathi"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Amasethingi okukhiya isikrini"</string> + <!-- no translation found for qr_code_scanner_title (1598912458255252498) --> + <skip /> + <!-- no translation found for qr_code_scanner_description (7452098243938659945) --> + <skip /> <string name="status_bar_work" msgid="5238641949837091056">"Iphrofayela yomsebenzi"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Imodi yendiza"</string> <string name="zen_alarm_warning" msgid="7844303238486849503">"Ngeke uzwe i-alamu yakho elandelayo ngo-<xliff:g id="WHEN">%1$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-zu/tiles_states_strings.xml b/packages/SystemUI/res/values-zu/tiles_states_strings.xml index fa2d972d3e6d..201aa10f0187 100644 --- a/packages/SystemUI/res/values-zu/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-zu/tiles_states_strings.xml @@ -151,6 +151,9 @@ <item msgid="7571394439974244289">"Valiwe"</item> <item msgid="6866424167599381915">"Vuliwe"</item> </string-array> + <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) --> + <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) --> + <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) --> <string-array name="tile_states_alarm"> <item msgid="4936533380177298776">"Akutholakali"</item> <item msgid="2710157085538036590">"Valiwe"</item> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java index 6154d84d5b37..8d98a7540a05 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java @@ -18,7 +18,6 @@ package com.android.systemui.shared.recents.utilities; import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT; import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; -import static android.util.DisplayMetrics.DENSITY_DEVICE_STABLE; import android.annotation.TargetApi; import android.content.Context; @@ -126,10 +125,9 @@ public class Utilities { final WindowManager windowManager = context.getSystemService(WindowManager.class); final Rect bounds = windowManager.getCurrentWindowMetrics().getBounds(); - float originalSmallestWidth = dpiFromPx(Math.min(bounds.width(), bounds.height()), + float smallestWidth = dpiFromPx(Math.min(bounds.width(), bounds.height()), context.getResources().getConfiguration().densityDpi); - return dpiFromPx(Math.min(bounds.width(), bounds.height()), DENSITY_DEVICE_STABLE) - >= TABLET_MIN_DPS && originalSmallestWidth >= TABLET_MIN_DPS; + return smallestWidth >= TABLET_MIN_DPS; } public static float dpiFromPx(float size, int densityDpi) { diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java index 954cf9fd81a8..a319b4018167 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java @@ -321,7 +321,7 @@ public class RemoteTransitionCompat implements Parcelable { // re-showing it's task). final WindowContainerTransaction wct = new WindowContainerTransaction(); final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); - for (int i = mPausingTasks.size() - 1; i >= 0; ++i) { + for (int i = mPausingTasks.size() - 1; i >= 0; --i) { // reverse order so that index 0 ends up on top wct.reorder(mPausingTasks.get(i), true /* onTop */); t.show(mInfo.getChange(mPausingTasks.get(i)).getLeash()); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index e24f07c21076..b56d189d3ab3 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -801,13 +801,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mHandler.postDelayed(mRetryFingerprintAuthentication, HAL_ERROR_RETRY_TIMEOUT); } + boolean lockedOutStateChanged = false; if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) { + lockedOutStateChanged |= !mFingerprintLockedOutPermanent; mFingerprintLockedOutPermanent = true; requireStrongAuthIfAllLockedOut(); } if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) { + lockedOutStateChanged |= !mFingerprintLockedOut; mFingerprintLockedOut = true; if (isUdfpsEnrolled()) { updateFingerprintListeningState(); @@ -820,9 +823,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab cb.onBiometricError(msgId, errString, BiometricSourceType.FINGERPRINT); } } + + if (lockedOutStateChanged) { + notifyLockedOutStateChanged(BiometricSourceType.FINGERPRINT); + } } private void handleFingerprintLockoutReset() { + boolean changed = mFingerprintLockedOut || mFingerprintLockedOutPermanent; mFingerprintLockedOut = false; mFingerprintLockedOutPermanent = false; @@ -837,6 +845,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } else { updateFingerprintListeningState(); } + + if (changed) { + notifyLockedOutStateChanged(BiometricSourceType.FINGERPRINT); + } } private void setFingerprintRunningState(int fingerprintRunningState) { @@ -999,7 +1011,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } + boolean lockedOutStateChanged = false; if (msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT) { + lockedOutStateChanged = !mFaceLockedOutPermanent; mFaceLockedOutPermanent = true; requireStrongAuthIfAllLockedOut(); } @@ -1011,11 +1025,21 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab BiometricSourceType.FACE); } } + + if (lockedOutStateChanged) { + notifyLockedOutStateChanged(BiometricSourceType.FACE); + } } private void handleFaceLockoutReset() { + boolean changed = mFaceLockedOutPermanent; mFaceLockedOutPermanent = false; + updateFaceListeningState(); + + if (changed) { + notifyLockedOutStateChanged(BiometricSourceType.FACE); + } } private void setFaceRunningState(int faceRunningState) { @@ -1237,6 +1261,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } + private void notifyLockedOutStateChanged(BiometricSourceType type) { + Assert.isMainThread(); + for (int i = 0; i < mCallbacks.size(); i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onLockedOutStateChanged(type); + } + } + } + public boolean isScreenOn() { return mScreenOn; } @@ -2454,6 +2488,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } + public boolean isFingerprintLockedOut() { + return mFingerprintLockedOut || mFingerprintLockedOutPermanent; + } + /** * If biometrics hardware is available, not disabled, and user has enrolled templates. * This does NOT check if the device is encrypted or in lockdown. diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index 12431984c9b9..8170a81a09e6 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -292,6 +292,11 @@ public class KeyguardUpdateMonitorCallback { public void onStrongAuthStateChanged(int userId) { } /** + * When the current user's locked out state changed. + */ + public void onLockedOutStateChanged(BiometricSourceType biometricSourceType) { } + + /** * Called when the dream's window state is changed. * @param dreaming true if the dream's window has been created and is visible */ diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index e84024d4f88f..33538ec25fcd 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -87,7 +87,7 @@ import com.android.systemui.animation.Interpolators; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.qs.SecureSetting; +import com.android.systemui.qs.SettingObserver; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.events.PrivacyDotViewController; import com.android.systemui.tuner.TunerService; @@ -155,7 +155,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable { private float mDensity; private WindowManager mWindowManager; private int mRotation; - private SecureSetting mColorInversionSetting; + private SettingObserver mColorInversionSetting; private DelayableExecutor mExecutor; private Handler mHandler; private boolean mPendingRotationChange; @@ -346,7 +346,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable { // Watch color inversion and invert the overlay as needed. if (mColorInversionSetting == null) { - mColorInversionSetting = new SecureSetting(mSecureSettings, mHandler, + mColorInversionSetting = new SettingObserver(mSecureSettings, mHandler, Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, mUserTracker.getUserId()) { @Override diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index 43a38aaea83d..8a997284b26f 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -31,8 +31,6 @@ import com.android.systemui.dagger.WMComponent; import com.android.systemui.navigationbar.gestural.BackGestureTfClassifierProvider; import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider; import com.android.wm.shell.transition.ShellTransitions; -import com.android.wm.shell.transition.Transitions; -import com.android.wm.shell.recents.RecentTasks; import java.util.Optional; import java.util.concurrent.ExecutionException; @@ -122,7 +120,8 @@ public class SystemUIFactory { .setStartingSurface(mWMComponent.getStartingSurface()) .setDisplayAreaHelper(mWMComponent.getDisplayAreaHelper()) .setTaskSurfaceHelper(mWMComponent.getTaskSurfaceHelper()) - .setRecentTasks(mWMComponent.getRecentTasks()); + .setRecentTasks(mWMComponent.getRecentTasks()) + .setSizeCompatUI(Optional.of(mWMComponent.getSizeCompatUI())); } else { // TODO: Call on prepareSysUIComponentBuilder but not with real components. Other option // is separating this logic into newly creating SystemUITestsFactory. @@ -140,7 +139,8 @@ public class SystemUIFactory { .setDisplayAreaHelper(Optional.ofNullable(null)) .setStartingSurface(Optional.ofNullable(null)) .setTaskSurfaceHelper(Optional.ofNullable(null)) - .setRecentTasks(Optional.ofNullable(null)); + .setRecentTasks(Optional.ofNullable(null)) + .setSizeCompatUI(Optional.ofNullable(null)); } mSysUIComponent = builder.build(); if (mInitializeComponents) { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java index 33ce20686e66..794b9dd5b68b 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java @@ -68,15 +68,15 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie private Configuration mLastConfiguration; private SysUiState mSysUiState; - private static class AnimationControllerSupplier extends - DisplayIdIndexSupplier<WindowMagnificationAnimationController> { + private static class ControllerSupplier extends + DisplayIdIndexSupplier<WindowMagnificationController> { private final Context mContext; private final Handler mHandler; private final WindowMagnifierCallback mWindowMagnifierCallback; private final SysUiState mSysUiState; - AnimationControllerSupplier(Context context, Handler handler, + ControllerSupplier(Context context, Handler handler, WindowMagnifierCallback windowMagnifierCallback, DisplayManager displayManager, SysUiState sysUiState) { super(displayManager); @@ -87,19 +87,19 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie } @Override - protected WindowMagnificationAnimationController createInstance(Display display) { + protected WindowMagnificationController createInstance(Display display) { final Context windowContext = mContext.createWindowContext(display, TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, /* options */ null); - final WindowMagnificationController controller = new WindowMagnificationController( + return new WindowMagnificationController( windowContext, - mHandler, new SfVsyncFrameCallbackProvider(), null, + mHandler, new WindowMagnificationAnimationController(windowContext), + new SfVsyncFrameCallbackProvider(), null, new SurfaceControl.Transaction(), mWindowMagnifierCallback, mSysUiState); - return new WindowMagnificationAnimationController(windowContext, controller); } } @VisibleForTesting - DisplayIdIndexSupplier<WindowMagnificationAnimationController> mAnimationControllerSupplier; + DisplayIdIndexSupplier<WindowMagnificationController> mMagnificationControllerSupplier; @Inject public WindowMagnification(Context context, @Main Handler mainHandler, @@ -113,7 +113,7 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie mModeSwitchesController = modeSwitchesController; mSysUiState = sysUiState; mOverviewProxyService = overviewProxyService; - mAnimationControllerSupplier = new AnimationControllerSupplier(context, + mMagnificationControllerSupplier = new ControllerSupplier(context, mHandler, this, context.getSystemService(DisplayManager.class), sysUiState); } @@ -121,8 +121,9 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie public void onConfigurationChanged(Configuration newConfig) { final int configDiff = newConfig.diff(mLastConfiguration); mLastConfiguration.setTo(newConfig); - mAnimationControllerSupplier.forEach( - animationController -> animationController.onConfigurationChanged(configDiff)); + mMagnificationControllerSupplier.forEach( + magnificationController -> magnificationController.onConfigurationChanged( + configDiff)); if (mModeSwitchesController != null) { mModeSwitchesController.onConfigurationChanged(configDiff); } @@ -143,10 +144,10 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie private void updateSysUiStateFlag() { //TODO(b/187510533): support multi-display once SysuiState supports it. - final WindowMagnificationAnimationController controller = - mAnimationControllerSupplier.valueAt(Display.DEFAULT_DISPLAY); + final WindowMagnificationController controller = + mMagnificationControllerSupplier.valueAt(Display.DEFAULT_DISPLAY); if (controller != null) { - controller.updateSysUiStateFlag(); + controller.updateSysUIStateFlag(); } else { // The instance is initialized when there is an IPC request. Considering // self-crash cases, we need to reset the flag in such situation. @@ -158,39 +159,39 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie @MainThread void enableWindowMagnification(int displayId, float scale, float centerX, float centerY, @Nullable IRemoteMagnificationAnimationCallback callback) { - final WindowMagnificationAnimationController windowMagnificationAnimationController = - mAnimationControllerSupplier.get(displayId); - if (windowMagnificationAnimationController != null) { - windowMagnificationAnimationController.enableWindowMagnification(scale, centerX, + final WindowMagnificationController windowMagnificationController = + mMagnificationControllerSupplier.get(displayId); + if (windowMagnificationController != null) { + windowMagnificationController.enableWindowMagnification(scale, centerX, centerY, callback); } } @MainThread void setScale(int displayId, float scale) { - final WindowMagnificationAnimationController windowMagnificationAnimationController = - mAnimationControllerSupplier.get(displayId); - if (windowMagnificationAnimationController != null) { - windowMagnificationAnimationController.setScale(scale); + final WindowMagnificationController windowMagnificationController = + mMagnificationControllerSupplier.get(displayId); + if (windowMagnificationController != null) { + windowMagnificationController.setScale(scale); } } @MainThread void moveWindowMagnifier(int displayId, float offsetX, float offsetY) { - final WindowMagnificationAnimationController windowMagnificationAnimationController = - mAnimationControllerSupplier.get(displayId); - if (windowMagnificationAnimationController != null) { - windowMagnificationAnimationController.moveWindowMagnifier(offsetX, offsetY); + final WindowMagnificationController windowMagnificationcontroller = + mMagnificationControllerSupplier.get(displayId); + if (windowMagnificationcontroller != null) { + windowMagnificationcontroller.moveWindowMagnifier(offsetX, offsetY); } } @MainThread void disableWindowMagnification(int displayId, @Nullable IRemoteMagnificationAnimationCallback callback) { - final WindowMagnificationAnimationController windowMagnificationAnimationController = - mAnimationControllerSupplier.get(displayId); - if (windowMagnificationAnimationController != null) { - windowMagnificationAnimationController.deleteWindowMagnification(callback); + final WindowMagnificationController windowMagnificationController = + mMagnificationControllerSupplier.get(displayId); + if (windowMagnificationController != null) { + windowMagnificationController.deleteWindowMagnification(callback); } } @@ -234,8 +235,8 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(TAG); - mAnimationControllerSupplier.forEach( - animationController -> animationController.dump(pw)); + mMagnificationControllerSupplier.forEach( + magnificationController -> magnificationController.dump(pw)); } private void setWindowMagnificationConnection() { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java index 8cb608f768eb..1bfa9c1a2a51 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java @@ -19,6 +19,7 @@ package com.android.systemui.accessibility; import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UiContext; import android.content.Context; @@ -31,7 +32,6 @@ import android.view.animation.AccelerateInterpolator; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.R; -import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -54,11 +54,11 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp // The window magnification is enabled. private static final int STATE_ENABLED = 1; // The window magnification is going to be disabled when the animation is end. - private static final int STATE_DISABLING = 2; + private static final int STATE_DISABLING = 2; // The animation is running for enabling the window magnification. private static final int STATE_ENABLING = 3; - private final WindowMagnificationController mController; + private WindowMagnificationController mController; private final ValueAnimator mValueAnimator; private final AnimationSpec mStartSpec = new AnimationSpec(); private final AnimationSpec mEndSpec = new AnimationSpec(); @@ -71,21 +71,22 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp @MagnificationState private int mState = STATE_DISABLED; - WindowMagnificationAnimationController(@UiContext Context context, - WindowMagnificationController controller) { - this(context, controller, newValueAnimator(context.getResources())); + WindowMagnificationAnimationController(@UiContext Context context) { + this(context, newValueAnimator(context.getResources())); } @VisibleForTesting - WindowMagnificationAnimationController(Context context, - WindowMagnificationController controller, ValueAnimator valueAnimator) { + WindowMagnificationAnimationController(Context context, ValueAnimator valueAnimator) { mContext = context; - mController = controller; mValueAnimator = valueAnimator; mValueAnimator.addUpdateListener(this); mValueAnimator.addListener(this); } + void setWindowMagnificationController(@NonNull WindowMagnificationController controller) { + mController = controller; + } + /** * Wraps {@link WindowMagnificationController#enableWindowMagnification(float, float, float)} * with transition animation. If the window magnification is not enabled, the scale will start @@ -105,6 +106,9 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp */ void enableWindowMagnification(float scale, float centerX, float centerY, @Nullable IRemoteMagnificationAnimationCallback animationCallback) { + if (mController == null) { + return; + } sendAnimationCallback(false); // Enable window magnification without animation immediately. if (animationCallback == null) { @@ -139,6 +143,9 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp } private void setupEnableAnimationSpecs(float scale, float centerX, float centerY) { + if (mController == null) { + return; + } final float currentScale = mController.getScale(); final float currentCenterX = mController.getCenterX(); final float currentCenterY = mController.getCenterY(); @@ -160,15 +167,9 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp } } - /** - * Wraps {@link WindowMagnificationController#setScale(float)}. If the animation is - * running, it has no effect. - */ - void setScale(float scale) { - if (mValueAnimator.isRunning()) { - return; - } - mController.setScale(scale); + /** Returns {@code true} if the animator is running. */ + boolean isAnimating() { + return mValueAnimator.isRunning(); } /** @@ -181,6 +182,9 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp */ void deleteWindowMagnification( @Nullable IRemoteMagnificationAnimationCallback animationCallback) { + if (mController == null) { + return; + } sendAnimationCallback(false); // Delete window magnification without animation. if (animationCallback == null) { @@ -206,25 +210,6 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp setState(STATE_DISABLING); } - /** - * Wraps {@link WindowMagnificationController#moveWindowMagnifier(float, float)}. If the - * animation is running, it has no effect. - * @param offsetX The amount in pixels to offset the window magnifier in the X direction, in - * current screen pixels. - * @param offsetY The amount in pixels to offset the window magnifier in the Y direction, in - * current screen pixels. - */ - void moveWindowMagnifier(float offsetX, float offsetY) { - if (mValueAnimator.isRunning()) { - return; - } - mController.moveWindowMagnifier(offsetX, offsetY); - } - - void onConfigurationChanged(int configDiff) { - mController.onConfigurationChanged(configDiff); - } - private void setState(@MagnificationState int state) { if (DEBUG) { Log.d(TAG, "setState from " + mState + " to " + state); @@ -239,7 +224,7 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp @Override public void onAnimationEnd(Animator animation, boolean isReverse) { - if (mEndAnimationCanceled) { + if (mEndAnimationCanceled || mController == null) { return; } if (Float.isNaN(mController.getScale())) { @@ -279,6 +264,9 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp @Override public void onAnimationUpdate(ValueAnimator animation) { + if (mController == null) { + return; + } final float fract = animation.getAnimatedFraction(); final float sentScale = mStartSpec.mScale + (mEndSpec.mScale - mStartSpec.mScale) * fract; final float centerX = @@ -288,14 +276,6 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp mController.enableWindowMagnification(sentScale, centerX, centerY); } - public void updateSysUiStateFlag() { - mController.updateSysUIStateFlag(); - } - - void dump(PrintWriter pw) { - mController.dump(pw); - } - private static ValueAnimator newValueAnimator(Resources resources) { final ValueAnimator valueAnimator = new ValueAnimator(); valueAnimator.setDuration( diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index b48def2b948c..250700487b7f 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -59,6 +59,7 @@ import android.view.WindowManagerGlobal; import android.view.WindowMetrics; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; +import android.view.accessibility.IRemoteMagnificationAnimationCallback; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; @@ -133,6 +134,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold // The top Y of the system gesture rect at the bottom. Set to -1 if it is invalid. private int mSystemGestureTop = -1; + private final WindowMagnificationAnimationController mAnimationController; private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; private final MagnificationGestureDetector mGestureDetector; private final int mBounceEffectDuration; @@ -148,11 +150,14 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private MirrorWindowControl mMirrorWindowControl; WindowMagnificationController(@UiContext Context context, @NonNull Handler handler, + @NonNull WindowMagnificationAnimationController animationController, SfVsyncFrameCallbackProvider sfVsyncFrameProvider, MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction, @NonNull WindowMagnifierCallback callback, SysUiState sysUiState) { mContext = context; mHandler = handler; + mAnimationController = animationController; + mAnimationController.setWindowMagnificationController(this); mSfVsyncFrameProvider = sfVsyncFrameProvider; mWindowMagnifierCallback = callback; mSysUiState = sysUiState; @@ -259,6 +264,19 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } /** + * Wraps {@link WindowMagnificationController#deleteWindowMagnification()}} with transition + * animation. If the window magnification is enabling, it runs the animation in reverse. + * + * @param animationCallback Called when the transition is complete, the given arguments + * are as same as current values, or the transition is interrupted + * due to the new transition request. + */ + void deleteWindowMagnification( + @Nullable IRemoteMagnificationAnimationCallback animationCallback) { + mAnimationController.deleteWindowMagnification(animationCallback); + } + + /** * Deletes the magnification window. */ void deleteWindowMagnification() { @@ -693,6 +711,27 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } /** + * Wraps {@link WindowMagnificationController#enableWindowMagnification(float, float, float)} + * with transition animation. If the window magnification is not enabled, the scale will start + * from 1.0 and the center won't be changed during the animation. If animator is + * {@code STATE_DISABLING}, the animation runs in reverse. + * + * @param scale The target scale, or {@link Float#NaN} to leave unchanged. + * @param centerX The screen-relative X coordinate around which to center, + * or {@link Float#NaN} to leave unchanged. + * @param centerY The screen-relative Y coordinate around which to center, + * or {@link Float#NaN} to leave unchanged. + * @param animationCallback Called when the transition is complete, the given arguments + * are as same as current values, or the transition is interrupted + * due to the new transition request. + */ + void enableWindowMagnification(float scale, float centerX, float centerY, + @Nullable IRemoteMagnificationAnimationCallback animationCallback) { + mAnimationController.enableWindowMagnification(scale, centerX, + centerY, animationCallback); + } + + /** * Enables window magnification with specified parameters. If the given scale is <strong>less * than or equal to 1.0f<strong>, then * {@link WindowMagnificationController#deleteWindowMagnification()} will be called instead to @@ -732,7 +771,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * @param scale the target scale, or {@link Float#NaN} to leave unchanged */ void setScale(float scale) { - if (!isWindowVisible() || mScale == scale) { + if (mAnimationController.isAnimating() || !isWindowVisible() || mScale == scale) { return; } enableWindowMagnification(scale, Float.NaN, Float.NaN); @@ -749,7 +788,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * current screen pixels. */ void moveWindowMagnifier(float offsetX, float offsetY) { - if (mMirrorSurfaceView == null) { + if (mAnimationController.isAnimating() || mMirrorSurfaceView == null) { return; } if (updateMagnificationFramePosition((int) offsetX, (int) offsetY)) { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java index 223eb78044c4..8f4d6f6aa973 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java @@ -255,7 +255,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud private void maybeShowInputBouncer() { if (mShowingUdfpsBouncer && hasUdfpsBouncerShownWithMinTime()) { mKeyguardViewManager.showBouncer(true); - mKeyguardViewManager.resetAlternateAuth(false); } } diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSource.java b/packages/SystemUI/src/com/android/systemui/communal/CommunalSource.java index 99c311e37217..53586f58c5d2 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSource.java +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSource.java @@ -23,6 +23,8 @@ import com.android.systemui.util.ViewController; import com.google.common.util.concurrent.ListenableFuture; +import java.util.Optional; + /** * {@link CommunalSource} defines an interface for working with a source for communal data. Clients * may request a communal surface that can be shown within a {@link android.view.SurfaceView}. @@ -30,6 +32,28 @@ import com.google.common.util.concurrent.ListenableFuture; */ public interface CommunalSource { /** + * {@link Connector} defines an interface for {@link CommunalSource} instances to be generated. + */ + interface Connector { + ListenableFuture<Optional<CommunalSource>> connect(); + } + + /** + * The {@link Observer} interface specifies an entity which {@link CommunalSource} listeners + * can be informed of changes to the source, which will require updating. Note that this deals + * with changes to the source itself, not content which will be updated through the + * {@link CommunalSource} interface. + */ + interface Observer { + interface Callback { + void onSourceChanged(); + } + + void addCallback(Callback callback); + void removeCallback(Callback callback); + } + + /** * {@link CommunalViewResult} is handed back from {@link #requestCommunalView(Context)} and * contains the view to be displayed and its associated controller. */ diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSourcePrimer.java b/packages/SystemUI/src/com/android/systemui/communal/CommunalSourcePrimer.java new file mode 100644 index 000000000000..3c2b79e25467 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSourcePrimer.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.communal; + +import android.content.Context; +import android.content.res.Resources; +import android.util.Log; + +import com.android.systemui.CoreStartable; +import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.util.concurrency.DelayableExecutor; + +import com.google.common.util.concurrent.ListenableFuture; + +import java.util.Optional; + +import javax.inject.Inject; + +/** + * The {@link CommunalSourcePrimer} is responsible for priming SystemUI with a pre-configured + * Communal source. The SystemUI service binds to the component to retrieve the + * {@link CommunalSource}. {@link CommunalSourcePrimer} has no effect + * if there is no pre-defined value. + */ +@SysUISingleton +public class CommunalSourcePrimer extends CoreStartable { + private static final String TAG = "CommunalSourcePrimer"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private final DelayableExecutor mMainExecutor; + private final CommunalSourceMonitor mMonitor; + private final int mBaseReconnectDelayMs; + private final int mMaxReconnectAttempts; + + private int mReconnectAttempts = 0; + private Runnable mCurrentReconnectCancelable; + private ListenableFuture<Optional<CommunalSource>> mGetSourceFuture; + + private final Optional<CommunalSource.Connector> mConnector; + private final Optional<CommunalSource.Observer> mObserver; + + private final Runnable mConnectRunnable = new Runnable() { + @Override + public void run() { + mCurrentReconnectCancelable = null; + connect(); + } + }; + + @Inject + public CommunalSourcePrimer(Context context, @Main Resources resources, + DelayableExecutor mainExecutor, + CommunalSourceMonitor monitor, + Optional<CommunalSource.Connector> connector, + Optional<CommunalSource.Observer> observer) { + super(context); + mMainExecutor = mainExecutor; + mMonitor = monitor; + mConnector = connector; + mObserver = observer; + + mMaxReconnectAttempts = resources.getInteger( + R.integer.config_communalSourceMaxReconnectAttempts); + mBaseReconnectDelayMs = resources.getInteger( + R.integer.config_communalSourceReconnectBaseDelay); + } + + @Override + public void start() { + } + + private void initiateConnectionAttempt() { + // Reset attempts + mReconnectAttempts = 0; + mMonitor.setSource(null); + + // The first attempt is always a direct invocation rather than delayed. + connect(); + } + + private void scheduleConnectionAttempt() { + // always clear cancelable if present. + if (mCurrentReconnectCancelable != null) { + mCurrentReconnectCancelable.run(); + mCurrentReconnectCancelable = null; + } + + if (mReconnectAttempts >= mMaxReconnectAttempts) { + if (DEBUG) { + Log.d(TAG, "exceeded max connection attempts."); + } + return; + } + + final long reconnectDelayMs = + (long) Math.scalb(mBaseReconnectDelayMs, mReconnectAttempts); + + if (DEBUG) { + Log.d(TAG, + "scheduling connection attempt in " + reconnectDelayMs + "milliseconds"); + } + + mCurrentReconnectCancelable = mMainExecutor.executeDelayed(mConnectRunnable, + reconnectDelayMs); + + mReconnectAttempts++; + } + + @Override + protected void onBootCompleted() { + if (mObserver.isPresent()) { + mObserver.get().addCallback(() -> initiateConnectionAttempt()); + } + initiateConnectionAttempt(); + } + + private void connect() { + if (DEBUG) { + Log.d(TAG, "attempting to communal to communal source"); + } + + if (mGetSourceFuture != null) { + if (DEBUG) { + Log.d(TAG, "canceling in-flight connection"); + } + mGetSourceFuture.cancel(true); + } + + mGetSourceFuture = mConnector.get().connect(); + mGetSourceFuture.addListener(() -> { + try { + Optional<CommunalSource> result = mGetSourceFuture.get(); + if (result.isPresent()) { + final CommunalSource source = result.get(); + source.addCallback(() -> initiateConnectionAttempt()); + mMonitor.setSource(source); + } else { + scheduleConnectionAttempt(); + } + } catch (Exception e) { + e.printStackTrace(); + } + }, mMainExecutor); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java index a9fb743bff8d..5fdf026b86f3 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java @@ -37,6 +37,7 @@ import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.recents.RecentTasks; +import com.android.wm.shell.sizecompatui.SizeCompatUI; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.startingsurface.StartingSurface; import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper; @@ -107,6 +108,9 @@ public interface SysUIComponent { @BindsInstance Builder setRecentTasks(Optional<RecentTasks> r); + @BindsInstance + Builder setSizeCompatUI(Optional<SizeCompatUI> s); + SysUIComponent build(); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java index d8b77426703e..543ba8f9b854 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java @@ -20,13 +20,13 @@ import android.content.Context; import com.android.systemui.SystemUIFactory; import com.android.systemui.tv.TvWMComponent; -import com.android.wm.shell.dagger.TvWMShellModule; -import com.android.wm.shell.dagger.WMShellModule; import com.android.wm.shell.ShellCommandHandler; import com.android.wm.shell.ShellInit; import com.android.wm.shell.TaskViewFactory; import com.android.wm.shell.apppairs.AppPairs; import com.android.wm.shell.bubbles.Bubbles; +import com.android.wm.shell.dagger.TvWMShellModule; +import com.android.wm.shell.dagger.WMShellModule; import com.android.wm.shell.dagger.WMSingleton; import com.android.wm.shell.displayareahelper.DisplayAreaHelper; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; @@ -34,6 +34,7 @@ import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.recents.RecentTasks; +import com.android.wm.shell.sizecompatui.SizeCompatUI; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.startingsurface.StartingSurface; import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper; @@ -115,4 +116,7 @@ public interface WMComponent { @WMSingleton Optional<RecentTasks> getRecentTasks(); + + @WMSingleton + SizeCompatUI getSizeCompatUI(); } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index 5c3e07fbaea1..239109af7a3d 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -16,6 +16,8 @@ package com.android.systemui.doze; +import static com.android.systemui.doze.DozeLog.REASON_SENSOR_QUICK_PICKUP; +import static com.android.systemui.doze.DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS; import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_DISPLAY; import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN; @@ -98,6 +100,7 @@ public class DozeSensors { private final DozeLog mDozeLog; private final SecureSettings mSecureSettings; private final DevicePostureController mDevicePostureController; + private final AuthController mAuthController; private final boolean mScreenOffUdfpsEnabled; // Sensors @@ -115,6 +118,7 @@ public class DozeSensors { private boolean mListening; private boolean mListeningTouchScreenSensors; private boolean mListeningProxSensors; + private boolean mUdfpsEnrolled; @DevicePostureController.DevicePostureInt private int mDevicePosture; @@ -169,10 +173,11 @@ public class DozeSensors { config.screenOffUdfpsEnabled(KeyguardUpdateMonitor.getCurrentUser()); mDevicePostureController = devicePostureController; mDevicePosture = mDevicePostureController.getDevicePosture(); + mAuthController = authController; - boolean udfpsEnrolled = - authController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser()); - boolean alwaysOn = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT); + mUdfpsEnrolled = + mAuthController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser()); + mAuthController.addCallback(mAuthControllerCallback); mTriggerSensors = new TriggerSensor[] { new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION), @@ -221,7 +226,7 @@ public class DozeSensors { findSensor(config.udfpsLongPressSensorType()), "doze_pulse_on_auth", true /* settingDef */, - udfpsEnrolled && (alwaysOn || mScreenOffUdfpsEnabled), + udfpsLongPressConfigured(), DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS, true /* reports touch coordinates */, true /* touchscreen */, @@ -230,7 +235,8 @@ public class DozeSensors { new PluginSensor( new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY), Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE, - mConfig.wakeScreenGestureAvailable() && alwaysOn, + mConfig.wakeScreenGestureAvailable() + && mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT), DozeLog.REASON_SENSOR_WAKE_UP_PRESENCE, false /* reports touch coordinates */, false /* touchscreen */), @@ -246,8 +252,7 @@ public class DozeSensors { findSensor(config.quickPickupSensorType()), Settings.Secure.DOZE_QUICK_PICKUP_GESTURE, true /* setting default */, - config.quickPickupSensorEnabled(KeyguardUpdateMonitor.getCurrentUser()) - && udfpsEnrolled, + quickPickUpConfigured(), DozeLog.REASON_SENSOR_QUICK_PICKUP, false /* requiresTouchCoordinates */, false /* requiresTouchscreen */, @@ -265,6 +270,16 @@ public class DozeSensors { mDevicePostureController.addCallback(mDevicePostureCallback); } + private boolean udfpsLongPressConfigured() { + return mUdfpsEnrolled + && (mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) || mScreenOffUdfpsEnabled); + } + + private boolean quickPickUpConfigured() { + return mUdfpsEnrolled + && mConfig.quickPickupSensorEnabled(KeyguardUpdateMonitor.getCurrentUser()); + } + /** * Unregister all sensors and callbacks. */ @@ -276,6 +291,7 @@ public class DozeSensors { mProximitySensor.pause(); mDevicePostureController.removeCallback(mDevicePostureCallback); + mAuthController.removeCallback(mAuthControllerCallback); } /** @@ -450,6 +466,7 @@ public class DozeSensors { pw.println("mSelectivelyRegisterProxSensors=" + mSelectivelyRegisterProxSensors); pw.println("mListeningProxSensors=" + mListeningProxSensors); pw.println("mScreenOffUdfpsEnabled=" + mScreenOffUdfpsEnabled); + pw.println("mUdfpsEnrolled=" + mUdfpsEnrolled); IndentingPrintWriter idpw = new IndentingPrintWriter(pw); idpw.increaseIndent(); for (TriggerSensor s : mTriggerSensors) { @@ -468,7 +485,7 @@ public class DozeSensors { @VisibleForTesting class TriggerSensor extends TriggerEventListener { @NonNull final Sensor[] mSensors; // index = posture, value = sensor - final boolean mConfigured; + boolean mConfigured; final int mPulseReason; private final String mSetting; private final boolean mReportsTouchCoordinates; @@ -496,10 +513,10 @@ public class DozeSensors { true /* settingDef */, configured, pulseReason, - false /* ignoresSetting */, - false /* requiresProx */, reportsTouchCoordinates, - requiresTouchscreen + requiresTouchscreen, + false /* ignoresSetting */, + false /* requiresProx */ ); } @@ -606,8 +623,18 @@ public class DozeSensors { updateListening(); } + /** + * Update configured state. + */ + public void setConfigured(boolean configured) { + if (mConfigured == configured) return; + mConfigured = configured; + updateListening(); + } + public void updateListening() { final Sensor sensor = mSensors[mPosture]; + if (!mConfigured || sensor == null) return; if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)) { if (!mRegistered) { @@ -791,6 +818,30 @@ public class DozeSensors { } }; + private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() { + @Override + public void onAllAuthenticatorsRegistered() { + updateUdfpsEnrolled(); + } + + @Override + public void onEnrollmentsChanged() { + updateUdfpsEnrolled(); + } + + private void updateUdfpsEnrolled() { + mUdfpsEnrolled = mAuthController.isUdfpsEnrolled( + KeyguardUpdateMonitor.getCurrentUser()); + for (TriggerSensor sensor : mTriggerSensors) { + if (REASON_SENSOR_QUICK_PICKUP == sensor.mPulseReason) { + sensor.setConfigured(quickPickUpConfigured()); + } else if (REASON_SENSOR_UDFPS_LONG_PRESS == sensor.mPulseReason) { + sensor.setConfigured(udfpsLongPressConfigured()); + } + } + } + }; + public interface Callback { /** diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java index b45dc52585ad..10878dcc2474 100644 --- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java +++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java @@ -42,7 +42,6 @@ import com.android.systemui.util.leak.LeakDetector; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; @@ -308,22 +307,22 @@ public class FragmentHostManager { return instantiateWithInjections(context, className, arguments); } - private Fragment instantiateWithInjections(Context context, String className, - Bundle args) { - Method method = mManager.getInjectionMap().get(className); - if (method != null) { + private Fragment instantiateWithInjections( + Context context, String className, Bundle args) { + FragmentService.FragmentInstantiationInfo fragmentInstantiationInfo = + mManager.getInjectionMap().get(className); + if (fragmentInstantiationInfo != null) { try { - Fragment f = (Fragment) method.invoke(mManager.getFragmentCreator()); + Fragment f = (Fragment) fragmentInstantiationInfo + .mMethod + .invoke(fragmentInstantiationInfo.mDaggerComponent); // Setup the args, taken from Fragment#instantiate. if (args != null) { args.setClassLoader(f.getClass().getClassLoader()); f.setArguments(args); } return f; - } catch (IllegalAccessException e) { - throw new Fragment.InstantiationException("Unable to instantiate " + className, - e); - } catch (InvocationTargetException e) { + } catch (IllegalAccessException | InvocationTargetException e) { throw new Fragment.InstantiationException("Unable to instantiate " + className, e); } diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java index 7f57fcc56117..2a5e653dd051 100644 --- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java +++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java @@ -18,13 +18,13 @@ import android.app.Fragment; import android.content.res.Configuration; import android.os.Handler; import android.util.ArrayMap; +import android.util.Log; import android.view.View; import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.qs.QSFragment; -import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; import com.android.systemui.statusbar.policy.ConfigurationController; import java.io.FileDescriptor; @@ -46,9 +46,14 @@ public class FragmentService implements Dumpable { private static final String TAG = "FragmentService"; private final ArrayMap<View, FragmentHostState> mHosts = new ArrayMap<>(); - private final ArrayMap<String, Method> mInjectionMap = new ArrayMap<>(); + /** + * A map with the means to create fragments via Dagger injection. + * + * key: the fragment class name. + * value: see {@link FragmentInstantiationInfo}. + */ + private final ArrayMap<String, FragmentInstantiationInfo> mInjectionMap = new ArrayMap<>(); private final Handler mHandler = new Handler(); - private final FragmentCreator mFragmentCreator; private ConfigurationController.ConfigurationListener mConfigurationListener = new ConfigurationController.ConfigurationListener() { @@ -65,26 +70,31 @@ public class FragmentService implements Dumpable { FragmentCreator.Factory fragmentCreatorFactory, ConfigurationController configurationController, DumpManager dumpManager) { - mFragmentCreator = fragmentCreatorFactory.build(); - initInjectionMap(); + addFragmentInstantiationProvider(fragmentCreatorFactory.build()); configurationController.addCallback(mConfigurationListener); dumpManager.registerDumpable(getClass().getSimpleName(), this); } - ArrayMap<String, Method> getInjectionMap() { + ArrayMap<String, FragmentInstantiationInfo> getInjectionMap() { return mInjectionMap; } - FragmentCreator getFragmentCreator() { - return mFragmentCreator; - } - - private void initInjectionMap() { - for (Method method : FragmentCreator.class.getDeclaredMethods()) { + /** + * Adds a new Dagger component object that provides method(s) to create fragments via injection. + */ + public void addFragmentInstantiationProvider(Object daggerComponent) { + for (Method method : daggerComponent.getClass().getDeclaredMethods()) { if (Fragment.class.isAssignableFrom(method.getReturnType()) && (method.getModifiers() & Modifier.PUBLIC) != 0) { - mInjectionMap.put(method.getReturnType().getName(), method); + String fragmentName = method.getReturnType().getName(); + if (mInjectionMap.containsKey(fragmentName)) { + Log.w(TAG, "Fragment " + fragmentName + " is already provided by different" + + " Dagger component; Not adding method"); + continue; + } + mInjectionMap.put( + fragmentName, new FragmentInstantiationInfo(method, daggerComponent)); } } } @@ -134,9 +144,6 @@ public class FragmentService implements Dumpable { * Inject a QSFragment. */ QSFragment createQSFragment(); - - /** Inject a CollapsedStatusBarFragment. */ - CollapsedStatusBarFragment createCollapsedStatusBarFragment(); } private class FragmentHostState { @@ -161,4 +168,16 @@ public class FragmentService implements Dumpable { mFragmentHostManager.onConfigurationChanged(newConfig); } } + + /** An object containing the information needed to instantiate a fragment. */ + static class FragmentInstantiationInfo { + /** The method that returns a newly-created fragment of the given class. */ + final Method mMethod; + /** The Dagger component that the method should be invoked on. */ + final Object mDaggerComponent; + FragmentInstantiationInfo(Method method, Object daggerComponent) { + this.mMethod = method; + this.mDaggerComponent = daggerComponent; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index e97e7622c272..fb7ab60c50ba 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -793,7 +793,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN; } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) { return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; - } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) { + } else if (any && ((strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0 + || mUpdateMonitor.isFingerprintLockedOut())) { return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT; } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE) != 0) { return KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE; diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt index e87558ebee27..47ef5e4c62fd 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt @@ -833,12 +833,15 @@ internal object MediaPlayerData { ) private val comparator = - compareByDescending<MediaSortKey> { it.data.isPlaying == true && it.data.isLocalSession } - .thenByDescending { it.data.isPlaying } - .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec } - .thenByDescending { !it.data.resumption } - .thenByDescending { it.updateTime } - .thenByDescending { !it.data.isLocalSession } + compareByDescending<MediaSortKey> { it.data.isPlaying == true && + it.data.playbackLocation == MediaData.PLAYBACK_LOCAL } + .thenByDescending { it.data.isPlaying == true && + it.data.playbackLocation == MediaData.PLAYBACK_CAST_LOCAL } + .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec } + .thenByDescending { !it.data.resumption } + .thenByDescending { it.data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE } + .thenByDescending { it.updateTime } + .thenByDescending { it.data.notificationKey } private val mediaPlayers = TreeMap<MediaSortKey, MediaControlPanel>(comparator) private val mediaData: MutableMap<String, MediaSortKey> = mutableMapOf() diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt index 6f0c88710461..bda07f428218 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt @@ -82,9 +82,9 @@ data class MediaData( */ var resumeAction: Runnable?, /** - * Local or remote playback + * Playback location: one of PLAYBACK_LOCAL, PLAYBACK_CAST_LOCAL, or PLAYBACK_CAST_REMOTE */ - var isLocalSession: Boolean = true, + var playbackLocation: Int = PLAYBACK_LOCAL, /** * Indicates that this player is a resumption player (ie. It only shows a play actions which * will start the app and start playing). @@ -110,7 +110,20 @@ data class MediaData( * Timestamp when this player was last active. */ var lastActive: Long = 0L -) +) { + companion object { + /** Media is playing on the local device */ + const val PLAYBACK_LOCAL = 0 + /** Media is cast but originated on the local device */ + const val PLAYBACK_CAST_LOCAL = 1 + /** Media is from a remote cast notification */ + const val PLAYBACK_CAST_REMOTE = 2 + } + + fun isLocalSession(): Boolean { + return playbackLocation == PLAYBACK_LOCAL + } +} /** State of a media action. */ data class MediaAction( diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index 3631d2fa04fb..6e86bef40181 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -27,6 +27,8 @@ import android.content.ContentResolver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.ImageDecoder @@ -85,15 +87,7 @@ internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, "INVALID", null, emptyList(), null, 0) fun isMediaNotification(sbn: StatusBarNotification): Boolean { - if (!sbn.notification.hasMediaSession()) { - return false - } - val notificationStyle = sbn.notification.notificationStyle - if (Notification.DecoratedMediaCustomViewStyle::class.java.equals(notificationStyle) || - Notification.MediaStyle::class.java.equals(notificationStyle)) { - return true - } - return false + return sbn.notification.isMediaNotification() } /** @@ -153,6 +147,24 @@ class MediaDataManager( private var smartspaceSession: SmartspaceSession? = null private var allowMediaRecommendations = Utils.allowMediaRecommendations(context) + /** + * Check whether this notification is an RCN + * TODO(b/204910409) implement new API for explicitly declaring this + */ + private fun isRemoteCastNotification(sbn: StatusBarNotification): Boolean { + val pm = context.packageManager + try { + val info = pm.getApplicationInfo(sbn.packageName, PackageManager.MATCH_SYSTEM_ONLY) + if (info.privateFlags and ApplicationInfo.PRIVATE_FLAG_PRIVILEGED != 0) { + val extras = sbn.notification.extras + if (extras.containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)) { + return true + } + } + } catch (e: PackageManager.NameNotFoundException) { } + return false + } + @Inject constructor( context: Context, @@ -442,7 +454,7 @@ class MediaDataManager( val existed = mediaEntries[key] != null backgroundExecutor.execute { mediaEntries[key]?.let { mediaData -> - if (mediaData.isLocalSession) { + if (mediaData.isLocalSession()) { mediaData.token?.let { val mediaController = mediaControllerFactory.create(it) mediaController.transportControls.stop() @@ -626,8 +638,11 @@ class MediaDataManager( } } - val isLocalSession = mediaController.playbackInfo?.playbackType == - MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL + val playbackLocation = + if (isRemoteCastNotification(sbn)) MediaData.PLAYBACK_CAST_REMOTE + else if (mediaController.playbackInfo?.playbackType == + MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL) MediaData.PLAYBACK_LOCAL + else MediaData.PLAYBACK_CAST_LOCAL val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null val lastActive = systemClock.elapsedRealtime() foregroundExecutor.execute { @@ -637,7 +652,7 @@ class MediaDataManager( onMediaDataLoaded(key, oldKey, MediaData(sbn.normalizedUserId, true, bgColor, app, smallIcon, artist, song, artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token, notif.contentIntent, null, - active, resumeAction = resumeAction, isLocalSession = isLocalSession, + active, resumeAction = resumeAction, playbackLocation = playbackLocation, notificationKey = key, hasCheckedForResume = hasCheckedForResume, isPlaying = isPlaying, isClearable = sbn.isClearable(), lastActive = lastActive)) @@ -762,7 +777,7 @@ class MediaDataManager( fun onNotificationRemoved(key: String) { Assert.isMainThread() val removed = mediaEntries.remove(key) - if (useMediaResumption && removed?.resumeAction != null && removed?.isLocalSession) { + if (useMediaResumption && removed?.resumeAction != null && removed?.isLocalSession()) { Log.d(TAG, "Not removing $key because resumable") // Move to resume key (aka package name) if that key doesn't already exist. val resumeAction = getResumeMediaAction(removed.resumeAction!!) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt index 608c784f5d39..d8095f3179b3 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt @@ -193,7 +193,7 @@ class MediaResumeListener @Inject constructor( mediaBrowser = null } // If we don't have a resume action, check if we haven't already - if (data.resumeAction == null && !data.hasCheckedForResume && data.isLocalSession) { + if (data.resumeAction == null && !data.hasCheckedForResume && data.isLocalSession()) { // TODO also check for a media button receiver intended for restarting (b/154127084) Log.d(TAG, "Checking for service component for " + data.packageName) val pm = context.packageManager diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 19812697719c..6da4d4811ac9 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -242,7 +242,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { for (NotificationEntry entry : mNotificationEntryManager.getActiveNotificationsForCurrentUser()) { final Notification notification = entry.getSbn().getNotification(); - if (notification.hasMediaSession() + if (notification.isMediaNotification() && TextUtils.equals(entry.getSbn().getPackageName(), mPackageName)) { final Icon icon = notification.getLargeIcon(); if (icon == null) { diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java new file mode 100644 index 000000000000..52103d3bd739 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.navigationbar; + +import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; + +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.UserHandle; +import android.provider.Settings; +import android.view.accessibility.AccessibilityManager; + +import androidx.annotation.NonNull; + +import com.android.systemui.Dumpable; +import com.android.systemui.accessibility.AccessibilityButtonModeObserver; +import com.android.systemui.assist.AssistManager; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dump.DumpManager; +import com.android.systemui.recents.OverviewProxyService; +import com.android.systemui.settings.UserTracker; +import com.android.systemui.shared.system.QuickStepContract; +import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import dagger.Lazy; + +/** + * Extracts shared elements between navbar and taskbar delegate to de-dupe logic and help them + * experience the joys of friendship. + * The events are then passed through + * + * Currently consolidates + * * A11y + * * Assistant + */ +@SysUISingleton +public final class NavBarHelper implements + AccessibilityButtonModeObserver.ModeChangedListener, + OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener, + Dumpable { + private final AccessibilityManager mAccessibilityManager; + private final Lazy<AssistManager> mAssistManagerLazy; + private final UserTracker mUserTracker; + private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; + private final List<NavbarTaskbarStateUpdater> mA11yEventListeners = new ArrayList<>(); + private Context mContext; + private ContentResolver mContentResolver; + private boolean mAssistantAvailable; + private boolean mLongPressHomeEnabled; + private boolean mAssistantTouchGestureEnabled; + private int mNavBarMode; + + private final ContentObserver mAssistContentObserver = new ContentObserver( + new Handler(Looper.getMainLooper())) { + @Override + public void onChange(boolean selfChange, Uri uri) { + updateAssitantAvailability(); + } + }; + + @Inject + public NavBarHelper(AccessibilityManager accessibilityManager, + AccessibilityManagerWrapper accessibilityManagerWrapper, + AccessibilityButtonModeObserver accessibilityButtonModeObserver, + OverviewProxyService overviewProxyService, + Lazy<AssistManager> assistManagerLazy, + NavigationModeController navigationModeController, + UserTracker userTracker, + DumpManager dumpManager) { + mAccessibilityManager = accessibilityManager; + mAssistManagerLazy = assistManagerLazy; + mUserTracker = userTracker; + accessibilityManagerWrapper.addCallback( + accessibilityManager1 -> NavBarHelper.this.dispatchA11yEventUpdate()); + mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; + + mAccessibilityButtonModeObserver.addListener(this); + mNavBarMode = navigationModeController.addListener(this); + overviewProxyService.addCallback(this); + dumpManager.registerDumpable(this); + } + + public void init(Context context) { + mContext = context; + mContentResolver = mContext.getContentResolver(); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), + false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED), + false, mAssistContentObserver, UserHandle.USER_ALL); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED), + false, mAssistContentObserver, UserHandle.USER_ALL); + updateAssitantAvailability(); + } + + public void destroy() { + mContentResolver.unregisterContentObserver(mAssistContentObserver); + } + + /** + * @param listener Will immediately get callbacks based on current state + */ + public void registerNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) { + mA11yEventListeners.add(listener); + listener.updateAccessibilityServicesState(); + listener.updateAssistantAvailable(mAssistantAvailable); + } + + public void removeNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) { + mA11yEventListeners.remove(listener); + } + + private void dispatchA11yEventUpdate() { + for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) { + listener.updateAccessibilityServicesState(); + } + } + + private void dispatchAssistantEventUpdate(boolean assistantAvailable) { + for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) { + listener.updateAssistantAvailable(assistantAvailable); + } + } + + @Override + public void onAccessibilityButtonModeChanged(int mode) { + dispatchA11yEventUpdate(); + } + + /** + * See {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_CLICKABLE} and + * {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE} + * + * @return the a11y button clickable and long_clickable states, or 0 if there is no + * a11y button in the navbar + */ + public int getA11yButtonState() { + // AccessibilityManagerService resolves services for the current user since the local + // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission + final List<String> a11yButtonTargets = + mAccessibilityManager.getAccessibilityShortcutTargets( + AccessibilityManager.ACCESSIBILITY_BUTTON); + final int requestingServices = a11yButtonTargets.size(); + + // If accessibility button is floating menu mode, click and long click state should be + // disabled. + if (mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode() + == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU) { + return 0; + } + + return (requestingServices >= 1 ? SYSUI_STATE_A11Y_BUTTON_CLICKABLE : 0) + | (requestingServices >= 2 ? SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE : 0); + } + + @Override + public void onConnectionChanged(boolean isConnected) { + if (isConnected) { + updateAssitantAvailability(); + } + } + + private void updateAssitantAvailability() { + boolean assistantAvailableForUser = mAssistManagerLazy.get() + .getAssistInfoForUser(UserHandle.USER_CURRENT) != null; + boolean longPressDefault = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault); + mLongPressHomeEnabled = Settings.Secure.getIntForUser(mContentResolver, + Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, longPressDefault ? 1 : 0, + mUserTracker.getUserId()) != 0; + boolean gestureDefault = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_assistTouchGestureEnabledDefault); + mAssistantTouchGestureEnabled = Settings.Secure.getIntForUser(mContentResolver, + Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, gestureDefault ? 1 : 0, + mUserTracker.getUserId()) != 0; + + mAssistantAvailable = assistantAvailableForUser + && mAssistantTouchGestureEnabled + && QuickStepContract.isGesturalMode(mNavBarMode); + dispatchAssistantEventUpdate(mAssistantAvailable); + } + + public boolean getLongPressHomeEnabled() { + return mLongPressHomeEnabled; + } + + @Override + public void startAssistant(Bundle bundle) { + mAssistManagerLazy.get().startAssist(bundle); + } + + @Override + public void onNavigationModeChanged(int mode) { + mNavBarMode = mode; + updateAssitantAvailability(); + } + + /** + * Callbacks will get fired once immediately after registering via + * {@link #registerNavTaskStateUpdater(NavbarTaskbarStateUpdater)} + */ + public interface NavbarTaskbarStateUpdater { + void updateAccessibilityServicesState(); + void updateAssistantAvailable(boolean available); + } + + @Override + public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { + pw.println("NavbarTaskbarFriendster"); + pw.println(" longPressHomeEnabled=" + mLongPressHomeEnabled); + pw.println(" mAssistantTouchGestureEnabled=" + mAssistantTouchGestureEnabled); + pw.println(" mAssistantAvailable=" + mAssistantAvailable); + pw.println(" mNavBarMode=" + mNavBarMode); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index bdacc4118442..e0da9a0dca2c 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -67,22 +67,18 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; -import android.database.ContentObserver; import android.graphics.Insets; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.RectF; import android.inputmethodservice.InputMethodService; -import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; -import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.provider.DeviceConfig; -import android.provider.Settings; import android.telecom.TelecomManager; import android.text.TextUtils; import android.util.Log; @@ -200,8 +196,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private final Handler mHandler; private final NavigationBarOverlayController mNavbarOverlayController; private final UiEventLogger mUiEventLogger; - private final NavigationBarA11yHelper mNavigationBarA11yHelper; - private final UserTracker mUserTracker; + private final NavBarHelper mNavBarHelper; private final NotificationShadeDepthController mNotificationShadeDepthController; private Bundle mSavedState; @@ -213,9 +208,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private int mNavigationIconHints = 0; private @TransitionMode int mNavigationBarMode; private ContentResolver mContentResolver; - private boolean mAssistantAvailable; private boolean mLongPressHomeEnabled; - private boolean mAssistantTouchGestureEnabled; private int mDisabledFlags1; private int mDisabledFlags2; @@ -309,16 +302,31 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } }; + private final NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater = + new NavBarHelper.NavbarTaskbarStateUpdater() { + @Override + public void updateAccessibilityServicesState() { + updateAcessibilityStateFlags(); + } + + @Override + public void updateAssistantAvailable(boolean available) { + // TODO(b/198002034): Content observers currently can still be called back after + // being unregistered, and in this case we can ignore the change if the nav bar + // has been destroyed already + if (mNavigationBarView == null) { + return; + } + mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled(); + updateAssistantEntrypoints(available); + } + }; + private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() { @Override public void onConnectionChanged(boolean isConnected) { mNavigationBarView.updateStates(); updateScreenPinningGestures(); - - // Send the assistant availability upon connection - if (isConnected) { - updateAssistantEntrypoints(); - } } @Override @@ -421,20 +429,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } }; - private final ContentObserver mAssistContentObserver = new ContentObserver( - new Handler(Looper.getMainLooper())) { - @Override - public void onChange(boolean selfChange, Uri uri) { - // TODO(b/198002034): Content observers currently can still be called back after being - // unregistered, and in this case we can ignore the change if the nav bar has been - // destroyed already - if (mNavigationBarView == null) { - return; - } - updateAssistantEntrypoints(); - } - }; - private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener = new DeviceConfig.OnPropertiesChangedListener() { @Override @@ -504,7 +498,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, @Main Handler mainHandler, NavigationBarOverlayController navbarOverlayController, UiEventLogger uiEventLogger, - NavigationBarA11yHelper navigationBarA11yHelper, + NavBarHelper navBarHelper, UserTracker userTracker, LightBarController mainLightBarController, LightBarController.Factory lightBarControllerFactory, @@ -535,8 +529,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mHandler = mainHandler; mNavbarOverlayController = navbarOverlayController; mUiEventLogger = uiEventLogger; - mNavigationBarA11yHelper = navigationBarA11yHelper; - mUserTracker = userTracker; + mNavBarHelper = navBarHelper; mNotificationShadeDepthController = notificationShadeDepthController; mMainLightBarController = mainLightBarController; mLightBarControllerFactory = lightBarControllerFactory; @@ -568,18 +561,9 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mIsOnDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; mCommandQueue.addCallback(this); - mAssistantAvailable = mAssistManagerLazy.get() - .getAssistInfoForUser(UserHandle.USER_CURRENT) != null; + mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled(); mContentResolver = mContext.getContentResolver(); - mContentResolver.registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), - false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL); - mContentResolver.registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED), - false, mAssistContentObserver, UserHandle.USER_ALL); - mContentResolver.registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED), - false, mAssistContentObserver, UserHandle.USER_ALL); + mNavBarHelper.init(mContext); mAllowForceNavBarHandleOpaque = mContext.getResources().getBoolean( R.bool.allow_force_nav_bar_handle_opaque); mForceNavBarHandleOpaque = DeviceConfig.getBoolean( @@ -593,7 +577,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener, )).filter(duration -> duration != 0); DeviceConfig.addOnPropertiesChangedListener( DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post, mOnPropertiesChangedListener); - updateAssistantEntrypoints(); if (savedState != null) { mDisabledFlags1 = savedState.getInt(EXTRA_DISABLE_STATE, 0); @@ -620,8 +603,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mWindowManager.removeViewImmediate(mNavigationBarView.getRootView()); mNavigationModeController.removeListener(this); - mNavigationBarA11yHelper.removeA11yEventListener(mAccessibilityListener); - mContentResolver.unregisterContentObserver(mAssistContentObserver); + mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + mNavBarHelper.destroy(); mDeviceProvisionedController.removeCallback(mUserSetupListener); mNotificationShadeDepthController.removeListener(mDepthListener); @@ -643,7 +626,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mNavigationBarView.setWindowVisible(isNavBarWindowVisible()); mNavigationBarView.setBehavior(mBehavior); - mNavigationBarA11yHelper.registerA11yEventListener(mAccessibilityListener); + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); mSplitScreenOptional.ifPresent(mNavigationBarView::registerDockedListener); mPipOptional.ifPresent(mNavigationBarView::registerPipExclusionBoundsChangeListener); @@ -716,7 +699,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mHandler.removeCallbacks(mAutoDim); mHandler.removeCallbacks(mOnVariableDurationHomeLongClick); mHandler.removeCallbacks(mEnableLayoutTransitions); - mNavigationBarA11yHelper.removeA11yEventListener(mAccessibilityListener); + mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); mFrame = null; mNavigationBarView = null; mOrientationHandle = null; @@ -885,7 +868,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener, pw.println(" mCurrentRotation=" + mCurrentRotation); pw.println(" mHomeButtonLongPressDurationMs=" + mHomeButtonLongPressDurationMs); pw.println(" mLongPressHomeEnabled=" + mLongPressHomeEnabled); - pw.println(" mAssistantTouchGestureEnabled=" + mAssistantTouchGestureEnabled); pw.println(" mNavigationBarWindowState=" + windowStateToString(mNavigationBarWindowState)); pw.println(" mNavigationBarMode=" @@ -1175,7 +1157,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton(); accessibilityButton.setOnClickListener(this::onAccessibilityClick); accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick); - updateAccessibilityServicesState(); + updateAcessibilityStateFlags(); ButtonDispatcher imeSwitcherButton = mNavigationBarView.getImeSwitchButton(); imeSwitcherButton.setOnClickListener(this::onImeSwitcherClick); @@ -1400,8 +1382,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, return true; } - void updateAccessibilityServicesState() { - int a11yFlags = mNavigationBarA11yHelper.getA11yButtonState(); + void updateAcessibilityStateFlags() { + int a11yFlags = mNavBarHelper.getA11yButtonState(); if (mNavigationBarView != null) { boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; @@ -1413,7 +1395,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, public void updateSystemUiStateFlags(int a11yFlags) { if (a11yFlags < 0) { - a11yFlags = mNavigationBarA11yHelper.getA11yButtonState(); + a11yFlags = mNavBarHelper.getA11yButtonState(); } boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; @@ -1440,24 +1422,10 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } } - private void updateAssistantEntrypoints() { - mAssistantAvailable = mAssistManagerLazy.get() - .getAssistInfoForUser(UserHandle.USER_CURRENT) != null; - boolean longPressDefault = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault); - mLongPressHomeEnabled = Settings.Secure.getIntForUser(mContentResolver, - Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, longPressDefault ? 1 : 0, - mUserTracker.getUserId()) != 0; - boolean gestureDefault = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_assistTouchGestureEnabledDefault); - mAssistantTouchGestureEnabled = Settings.Secure.getIntForUser(mContentResolver, - Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, gestureDefault ? 1 : 0, - mUserTracker.getUserId()) != 0; + private void updateAssistantEntrypoints(boolean assistantAvailable) { if (mOverviewProxyService.getProxy() != null) { try { - mOverviewProxyService.getProxy().onAssistantAvailable(mAssistantAvailable - && mAssistantTouchGestureEnabled - && QuickStepContract.isGesturalMode(mNavBarMode)); + mOverviewProxyService.getProxy().onAssistantAvailable(assistantAvailable); } catch (RemoteException e) { Log.w(TAG, "Unable to send assistant availability data to launcher"); } @@ -1528,8 +1496,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener, @Override public void onNavigationModeChanged(int mode) { mNavBarMode = mode; - // update assistant entry points on system navigation radio button click - updateAssistantEntrypoints(); if (!QuickStepContract.isGesturalMode(mode)) { // Reset the override alpha @@ -1568,9 +1534,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mNavigationBarView.getBarTransitions().finishAnimations(); } - private final NavigationBarA11yHelper.NavA11yEventListener mAccessibilityListener = - this::updateAccessibilityServicesState; - private WindowManager.LayoutParams getBarLayoutParams(int rotation) { WindowManager.LayoutParams lp = getBarLayoutParamsForRotation(rotation); lp.paramsForRotation = new WindowManager.LayoutParams[4]; @@ -1674,7 +1637,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } if (Intent.ACTION_USER_SWITCHED.equals(action)) { // The accessibility settings may be different for the new user - updateAccessibilityServicesState(); + updateAcessibilityStateFlags(); } } }; @@ -1710,7 +1673,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private final Handler mMainHandler; private final NavigationBarOverlayController mNavbarOverlayController; private final UiEventLogger mUiEventLogger; - private final NavigationBarA11yHelper mNavigationBarA11yHelper; + private final NavBarHelper mNavBarHelper; private final UserTracker mUserTracker; private final LightBarController mMainLightBarController; private final LightBarController.Factory mLightBarControllerFactory; @@ -1743,7 +1706,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, @Main Handler mainHandler, NavigationBarOverlayController navbarOverlayController, UiEventLogger uiEventLogger, - NavigationBarA11yHelper navigationBarA11yHelper, + NavBarHelper navBarHelper, UserTracker userTracker, LightBarController mainLightBarController, LightBarController.Factory lightBarControllerFactory, @@ -1773,7 +1736,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mMainHandler = mainHandler; mNavbarOverlayController = navbarOverlayController; mUiEventLogger = uiEventLogger; - mNavigationBarA11yHelper = navigationBarA11yHelper; + mNavBarHelper = navBarHelper; mUserTracker = userTracker; mMainLightBarController = mainLightBarController; mLightBarControllerFactory = lightBarControllerFactory; @@ -1794,7 +1757,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mSplitScreenOptional, mRecentsOptional, mStatusBarOptionalLazy, mShadeController, mNotificationRemoteInputManager, mNotificationShadeDepthController, mSystemActions, mMainHandler, - mNavbarOverlayController, mUiEventLogger, mNavigationBarA11yHelper, + mNavbarOverlayController, mUiEventLogger, mNavBarHelper, mUserTracker, mMainLightBarController, mLightBarControllerFactory, mMainAutoHideController, mAutoHideControllerFactory, mTelecomManagerOptional, mInputMethodManager); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java deleted file mode 100644 index 13e6d8b410d6..000000000000 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.android.systemui.navigationbar; - -import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; - -import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE; -import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE; - -import android.view.accessibility.AccessibilityManager; - -import com.android.systemui.accessibility.AccessibilityButtonModeObserver; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.shared.system.QuickStepContract; -import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; - -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; - -/** - * Extracts shared elements of a11y necessary between navbar and taskbar delegate - */ -@SysUISingleton -public final class NavigationBarA11yHelper implements - AccessibilityButtonModeObserver.ModeChangedListener { - private final AccessibilityManager mAccessibilityManager; - private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; - private final List<NavA11yEventListener> mA11yEventListeners = new ArrayList<>(); - - @Inject - public NavigationBarA11yHelper(AccessibilityManager accessibilityManager, - AccessibilityManagerWrapper accessibilityManagerWrapper, - AccessibilityButtonModeObserver accessibilityButtonModeObserver) { - mAccessibilityManager = accessibilityManager; - accessibilityManagerWrapper.addCallback( - accessibilityManager1 -> NavigationBarA11yHelper.this.dispatchEventUpdate()); - mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; - - mAccessibilityButtonModeObserver.addListener(this); - } - - public void registerA11yEventListener(NavA11yEventListener listener) { - mA11yEventListeners.add(listener); - } - - public void removeA11yEventListener(NavA11yEventListener listener) { - mA11yEventListeners.remove(listener); - } - - private void dispatchEventUpdate() { - for (NavA11yEventListener listener : mA11yEventListeners) { - listener.updateAccessibilityServicesState(); - } - } - - @Override - public void onAccessibilityButtonModeChanged(int mode) { - dispatchEventUpdate(); - } - - /** - * See {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_CLICKABLE} and - * {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE} - * - * @return the a11y button clickable and long_clickable states, or 0 if there is no - * a11y button in the navbar - */ - public int getA11yButtonState() { - // AccessibilityManagerService resolves services for the current user since the local - // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission - final List<String> a11yButtonTargets = - mAccessibilityManager.getAccessibilityShortcutTargets( - AccessibilityManager.ACCESSIBILITY_BUTTON); - final int requestingServices = a11yButtonTargets.size(); - - // If accessibility button is floating menu mode, click and long click state should be - // disabled. - if (mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode() - == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU) { - return 0; - } - - return (requestingServices >= 1 ? SYSUI_STATE_A11Y_BUTTON_CLICKABLE : 0) - | (requestingServices >= 2 ? SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE : 0); - } - - public interface NavA11yEventListener { - void updateAccessibilityServicesState(); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java index 3dc79c43d894..339877824b16 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java @@ -100,7 +100,7 @@ public class NavigationBarController implements CommandQueue commandQueue, @Main Handler mainHandler, ConfigurationController configurationController, - NavigationBarA11yHelper navigationBarA11yHelper, + NavBarHelper navBarHelper, TaskbarDelegate taskbarDelegate, NavigationBar.Factory navigationBarFactory, DumpManager dumpManager, @@ -115,7 +115,7 @@ public class NavigationBarController implements mNavMode = navigationModeController.addListener(this); mTaskbarDelegate = taskbarDelegate; mTaskbarDelegate.setDependencies(commandQueue, overviewProxyService, - navigationBarA11yHelper, navigationModeController, sysUiFlagsContainer, + navBarHelper, navigationModeController, sysUiFlagsContainer, dumpManager, autoHideController); mIsTablet = isTablet(mContext); dumpManager.registerDumpable(this); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index d707dbdf5cba..428d9d6993b7 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -43,6 +43,8 @@ import android.content.res.Configuration; import android.hardware.display.DisplayManager; import android.inputmethodservice.InputMethodService; import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; import android.view.Display; import android.view.InsetsVisibilities; import android.view.View; @@ -73,19 +75,30 @@ import javax.inject.Singleton; public class TaskbarDelegate implements CommandQueue.Callbacks, OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener, ComponentCallbacks, Dumpable { + private static final String TAG = TaskbarDelegate.class.getSimpleName(); private final EdgeBackGestureHandler mEdgeBackGestureHandler; - + private boolean mInitialized; private CommandQueue mCommandQueue; private OverviewProxyService mOverviewProxyService; - private NavigationBarA11yHelper mNavigationBarA11yHelper; + private NavBarHelper mNavBarHelper; private NavigationModeController mNavigationModeController; private SysUiState mSysUiState; private AutoHideController mAutoHideController; private int mDisplayId; private int mNavigationIconHints; - private final NavigationBarA11yHelper.NavA11yEventListener mNavA11yEventListener = - this::updateSysuiFlags; + private final NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater = + new NavBarHelper.NavbarTaskbarStateUpdater() { + @Override + public void updateAccessibilityServicesState() { + updateSysuiFlags(); + } + + @Override + public void updateAssistantAvailable(boolean available) { + updateAssistantAvailability(available); + } + }; private int mDisabledFlags; private @WindowVisibleState int mTaskBarWindowState = WINDOW_STATE_SHOWING; private @Behavior int mBehavior; @@ -125,14 +138,14 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, public void setDependencies(CommandQueue commandQueue, OverviewProxyService overviewProxyService, - NavigationBarA11yHelper navigationBarA11yHelper, + NavBarHelper navBarHelper, NavigationModeController navigationModeController, SysUiState sysUiState, DumpManager dumpManager, AutoHideController autoHideController) { // TODO: adding this in the ctor results in a dagger dependency cycle :( mCommandQueue = commandQueue; mOverviewProxyService = overviewProxyService; - mNavigationBarA11yHelper = navigationBarA11yHelper; + mNavBarHelper = navBarHelper; mNavigationModeController = navigationModeController; mSysUiState = sysUiState; dumpManager.registerDumpable(this); @@ -140,12 +153,16 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, } public void init(int displayId) { + if (mInitialized) { + return; + } mDisplayId = displayId; mCommandQueue.addCallback(this); mOverviewProxyService.addCallback(this); mEdgeBackGestureHandler.onNavigationModeChanged( mNavigationModeController.addListener(this)); - mNavigationBarA11yHelper.registerA11yEventListener(mNavA11yEventListener); + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + mNavBarHelper.init(mContext); mEdgeBackGestureHandler.onNavBarAttached(); // Initialize component callback Display display = mDisplayManager.getDisplay(displayId); @@ -154,23 +171,29 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, // Set initial state for any listeners updateSysuiFlags(); mAutoHideController.setNavigationBar(mAutoHideUiElement); + mInitialized = true; } public void destroy() { + if (!mInitialized) { + return; + } mCommandQueue.removeCallback(this); mOverviewProxyService.removeCallback(this); mNavigationModeController.removeListener(this); - mNavigationBarA11yHelper.removeA11yEventListener(mNavA11yEventListener); + mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + mNavBarHelper.destroy(); mEdgeBackGestureHandler.onNavBarDetached(); if (mWindowContext != null) { mWindowContext.unregisterComponentCallbacks(this); mWindowContext = null; } mAutoHideController.setNavigationBar(null); + mInitialized = false; } private void updateSysuiFlags() { - int a11yFlags = mNavigationBarA11yHelper.getA11yButtonState(); + int a11yFlags = mNavBarHelper.getA11yButtonState(); boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; @@ -194,6 +217,18 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, .commitUpdate(mDisplayId); } + private void updateAssistantAvailability(boolean assistantAvailable) { + if (mOverviewProxyService.getProxy() == null) { + return; + } + + try { + mOverviewProxyService.getProxy().onAssistantAvailable(assistantAvailable); + } catch (RemoteException e) { + Log.e(TAG, "onAssistantAvailable() failed, available: " + assistantAvailable, e); + } + } + @Override public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, boolean showImeSwitcher) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java b/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java deleted file mode 100644 index c169df005f56..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.qs; - -import android.content.Context; -import android.database.ContentObserver; -import android.os.Handler; -import android.provider.Settings.Global; - -import com.android.systemui.statusbar.policy.Listenable; - -/** Helper for managing a global setting. **/ -public abstract class GlobalSetting extends ContentObserver implements Listenable { - private final Context mContext; - private final String mSettingName; - - protected abstract void handleValueChanged(int value); - - public GlobalSetting(Context context, Handler handler, String settingName) { - super(handler); - mContext = context; - mSettingName = settingName; - } - - public int getValue() { - return Global.getInt(mContext.getContentResolver(), mSettingName, 0); - } - - public void setValue(int value) { - Global.putInt(mContext.getContentResolver(), mSettingName, value); - } - - @Override - public void setListening(boolean listening) { - if (listening) { - mContext.getContentResolver().registerContentObserver( - Global.getUriFor(mSettingName), false, this); - } else { - mContext.getContentResolver().unregisterContentObserver(this); - } - } - - @Override - public void onChange(boolean selfChange) { - handleValueChanged(getValue()); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 71eb4a2e6cbb..d69deefc3477 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -26,6 +26,7 @@ import android.content.res.Resources; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.util.ArrayMap; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; @@ -103,6 +104,8 @@ public class QSPanel extends LinearLayout implements Tunable { protected LinearLayout mHorizontalContentContainer; protected QSTileLayout mTileLayout; + private float mSquishinessFraction = 1f; + private final ArrayMap<View, Integer> mChildrenLayoutTop = new ArrayMap<>(); public QSPanel(Context context, AttributeSet attrs) { super(context, attrs); @@ -179,10 +182,26 @@ public class QSPanel extends LinearLayout implements Tunable { if (mTileLayout == null) { mTileLayout = (QSTileLayout) LayoutInflater.from(mContext) .inflate(R.layout.qs_paged_tile_layout, this, false); + mTileLayout.setSquishinessFraction(mSquishinessFraction); } return mTileLayout; } + public void setSquishinessFraction(float squishinessFraction) { + if (Float.compare(squishinessFraction, mSquishinessFraction) == 0) { + return; + } + mSquishinessFraction = squishinessFraction; + if (mTileLayout == null) { + return; + } + mTileLayout.setSquishinessFraction(squishinessFraction); + if (getMeasuredWidth() == 0) { + return; + } + updateViewPositions(); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mTileLayout instanceof PagedTileLayout) { @@ -228,6 +247,39 @@ public class QSPanel extends LinearLayout implements Tunable { setMeasuredDimension(getMeasuredWidth(), height); } + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + mChildrenLayoutTop.put(child, child.getTop()); + } + updateViewPositions(); + } + + private void updateViewPositions() { + if (!(mTileLayout instanceof TileLayout)) { + return; + } + TileLayout layout = (TileLayout) mTileLayout; + + // Adjust view positions based on tile squishing + int tileHeightOffset = layout.getTilesHeight() - layout.getHeight(); + + boolean move = false; + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + if (move) { + int top = mChildrenLayoutTop.get(child); + child.setLeftTopRightBottom(child.getLeft(), top + tileHeightOffset, + child.getRight(), top + tileHeightOffset + child.getHeight()); + } + if (child == mTileLayout) { + move = true; + } + } + } + protected String getDumpableTag() { return TAG; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java index f7d1b1e2f5eb..eddc206db231 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java @@ -147,6 +147,10 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr return mMediaHost; } + public void setSquishinessFraction(float squishinessFraction) { + mView.setSquishinessFraction(squishinessFraction); + } + @Override protected void onViewAttached() { mQsTileRevealController = createTileRevealController(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt b/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt index c1c146d40e38..c680cb5d18a4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt @@ -1,14 +1,10 @@ package com.android.systemui.qs -import android.view.ViewGroup -import com.android.systemui.qs.dagger.QSFragmentModule.QQS_FOOTER import com.android.systemui.qs.dagger.QSScope import javax.inject.Inject -import javax.inject.Named @QSScope class QSSquishinessController @Inject constructor( - @Named(QQS_FOOTER) private val qqsFooterActionsView: FooterActionsView, private val qsAnimator: QSAnimator, private val qsPanelController: QSPanelController, private val quickQSPanelController: QuickQSPanelController @@ -33,23 +29,7 @@ class QSSquishinessController @Inject constructor( * Change the height of all tiles and repositions their siblings. */ private fun updateSquishiness() { - (qsPanelController.tileLayout as QSPanel.QSTileLayout).setSquishinessFraction(squishiness) - val tileLayout = quickQSPanelController.tileLayout as TileLayout - tileLayout.setSquishinessFraction(squishiness) - - // Calculate how much we should move the footer - val tileHeightOffset = tileLayout.height - tileLayout.tilesHeight - val footerTopMargin = (qqsFooterActionsView.layoutParams as ViewGroup.MarginLayoutParams) - .topMargin - val nextTop = tileLayout.bottom - tileHeightOffset + footerTopMargin - val amountMoved = nextTop - qqsFooterActionsView.top - - // Move the footer and other siblings (MediaPlayer) - (qqsFooterActionsView.parent as ViewGroup?)?.let { parent -> - val index = parent.indexOfChild(qqsFooterActionsView) - for (i in index until parent.childCount) { - parent.getChildAt(i).top += amountMoved - } - } + qsPanelController.setSquishinessFraction(squishiness) + quickQSPanelController.setSquishinessFraction(squishiness) } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java b/packages/SystemUI/src/com/android/systemui/qs/SettingObserver.java index d2bc38edd337..6b0abd41dfff 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java +++ b/packages/SystemUI/src/com/android/systemui/qs/SettingObserver.java @@ -21,11 +21,18 @@ import android.database.ContentObserver; import android.os.Handler; import com.android.systemui.statusbar.policy.Listenable; +import com.android.systemui.util.settings.GlobalSettings; import com.android.systemui.util.settings.SecureSettings; +import com.android.systemui.util.settings.SettingsProxy; +import com.android.systemui.util.settings.SystemSettings; -/** Helper for managing a secure setting. **/ -public abstract class SecureSetting extends ContentObserver implements Listenable { - private final SecureSettings mSecureSettings; +/** + * Helper for managing secure, global, and system settings through use of {@link SettingsProxy}, + * which is the common superclass of {@link SecureSettings}, {@link GlobalSettings}, and + * {@link SystemSettings}. + */ +public abstract class SettingObserver extends ContentObserver implements Listenable { + private final SettingsProxy mSettingsProxy; private final String mSettingName; private final int mDefaultValue; @@ -35,19 +42,19 @@ public abstract class SecureSetting extends ContentObserver implements Listenabl protected abstract void handleValueChanged(int value, boolean observedChange); - public SecureSetting(SecureSettings secureSettings, Handler handler, String settingName, + public SettingObserver(SettingsProxy settingsProxy, Handler handler, String settingName, int userId) { - this(secureSettings, handler, settingName, userId, 0); + this(settingsProxy, handler, settingName, userId, 0); } - public SecureSetting(SecureSettings secureSetting, Handler handler, String settingName) { - this(secureSetting, handler, settingName, ActivityManager.getCurrentUser()); + public SettingObserver(SettingsProxy settingsProxy, Handler handler, String settingName) { + this(settingsProxy, handler, settingName, ActivityManager.getCurrentUser()); } - public SecureSetting(SecureSettings secureSettings, Handler handler, String settingName, + public SettingObserver(SettingsProxy settingsProxy, Handler handler, String settingName, int userId, int defaultValue) { super(handler); - mSecureSettings = secureSettings; + mSettingsProxy = settingsProxy; mSettingName = settingName; mObservedValue = mDefaultValue = defaultValue; mUserId = userId; @@ -57,12 +64,17 @@ public abstract class SecureSetting extends ContentObserver implements Listenabl return mListening ? mObservedValue : getValueFromProvider(); } + /** + * Set the value of the observed setting. + * + * @param value The new value for the setting. + */ public void setValue(int value) { - mSecureSettings.putIntForUser(mSettingName, value, mUserId); + mSettingsProxy.putIntForUser(mSettingName, value, mUserId); } private int getValueFromProvider() { - return mSecureSettings.getIntForUser(mSettingName, mDefaultValue, mUserId); + return mSettingsProxy.getIntForUser(mSettingName, mDefaultValue, mUserId); } @Override @@ -71,10 +83,10 @@ public abstract class SecureSetting extends ContentObserver implements Listenabl mListening = listening; if (listening) { mObservedValue = getValueFromProvider(); - mSecureSettings.registerContentObserverForUser( - mSecureSettings.getUriFor(mSettingName), false, this, mUserId); + mSettingsProxy.registerContentObserverForUser( + mSettingsProxy.getUriFor(mSettingName), false, this, mUserId); } else { - mSecureSettings.unregisterContentObserver(this); + mSettingsProxy.unregisterContentObserver(this); mObservedValue = mDefaultValue; } } @@ -87,6 +99,9 @@ public abstract class SecureSetting extends ContentObserver implements Listenabl handleValueChanged(value, changed); } + /** + * Set user handle for which to observe the setting. + */ public void setUserId(int userId) { mUserId = userId; if (mListening) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt index 4bdeb567074e..09fad30f02ff 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt @@ -247,7 +247,10 @@ open class QSTileViewImpl @JvmOverloads constructor( } else { measuredHeight } - bottom = top + (actualHeight * squishinessFraction).toInt() + // Limit how much we affect the height, so we don't have rounding artifacts when the tile + // is too short. + val constrainedSquishiness = 0.1f + squishinessFraction * 0.9f + bottom = top + (actualHeight * constrainedSquishiness).toInt() scrollY = (actualHeight - height) / 2 } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java index 22cd6f86b165..5650a17e703a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java @@ -44,10 +44,11 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.qs.GlobalSetting; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; +import com.android.systemui.util.settings.GlobalSettings; import javax.inject.Inject; @@ -56,7 +57,7 @@ import dagger.Lazy; /** Quick settings tile: Airplane mode **/ public class AirplaneModeTile extends QSTileImpl<BooleanState> { private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_airplane); - private final GlobalSetting mSetting; + private final SettingObserver mSetting; private final BroadcastDispatcher mBroadcastDispatcher; private final Lazy<ConnectivityManager> mLazyConnectivityManager; @@ -73,16 +74,17 @@ public class AirplaneModeTile extends QSTileImpl<BooleanState> { ActivityStarter activityStarter, QSLogger qsLogger, BroadcastDispatcher broadcastDispatcher, - Lazy<ConnectivityManager> lazyConnectivityManager + Lazy<ConnectivityManager> lazyConnectivityManager, + GlobalSettings globalSettings ) { super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mBroadcastDispatcher = broadcastDispatcher; mLazyConnectivityManager = lazyConnectivityManager; - mSetting = new GlobalSetting(mContext, mHandler, Global.AIRPLANE_MODE_ON) { + mSetting = new SettingObserver(globalSettings, mHandler, Global.AIRPLANE_MODE_ON) { @Override - protected void handleValueChanged(int value) { + protected void handleValueChanged(int value, boolean observedChange) { // mHandler is the background handler so calling this is OK handleRefreshState(value); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java index e3024fa0eddc..b8ef3128f9ea 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java @@ -36,7 +36,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; -import com.android.systemui.qs.SecureSetting; +import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.BatteryController; @@ -49,7 +49,7 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements private final BatteryController mBatteryController; @VisibleForTesting - protected final SecureSetting mSetting; + protected final SettingObserver mSetting; private int mLevel; private boolean mPowerSave; @@ -76,7 +76,7 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements mBatteryController = batteryController; mBatteryController.observe(getLifecycle(), this); int currentUser = host.getUserContext().getUserId(); - mSetting = new SecureSetting( + mSetting = new SettingObserver( secureSettings, mHandler, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java index 5e502cc72c80..d2d2180bfa87 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java @@ -17,7 +17,6 @@ package com.android.systemui.qs.tiles; import android.content.Intent; -import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.provider.Settings; @@ -39,7 +38,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; -import com.android.systemui.qs.SecureSetting; +import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.settings.UserTracker; @@ -55,7 +54,7 @@ public class ColorInversionTile extends QSTileImpl<BooleanState> { private static final String COLOR_INVERSION_PREFERENCE_KEY = "toggle_inversion_preference"; private final Icon mIcon = ResourceIcon.get(drawable.ic_invert_colors); - private final SecureSetting mSetting; + private final SettingObserver mSetting; private boolean mListening; @@ -75,7 +74,7 @@ public class ColorInversionTile extends QSTileImpl<BooleanState> { super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); - mSetting = new SecureSetting(secureSettings, mHandler, + mSetting = new SettingObserver(secureSettings, mHandler, Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, userTracker.getUserId()) { @Override protected void handleValueChanged(int value, boolean observedChange) { @@ -110,11 +109,7 @@ public class ColorInversionTile extends QSTileImpl<BooleanState> { @Override public Intent getLongClickIntent() { - Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS); - Bundle bundle = new Bundle(); - bundle.putString(EXTRA_FRAGMENT_ARGS_KEY, COLOR_INVERSION_PREFERENCE_KEY); - intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGS_KEY, bundle); - return intent; + return new Intent(Settings.ACTION_COLOR_INVERSION_SETTINGS); } @Override 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 b1cd68e5185c..99cb700a324d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -61,7 +61,7 @@ import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; -import com.android.systemui.qs.SecureSetting; +import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.phone.SystemUIDialog; @@ -83,7 +83,7 @@ public class DndTile extends QSTileImpl<BooleanState> { private final ZenModeController mController; private final DndDetailAdapter mDetailAdapter; private final SharedPreferences mSharedPreferences; - private final SecureSetting mSettingZenDuration; + private final SettingObserver mSettingZenDuration; private boolean mListening; private boolean mShowingDetail; @@ -108,7 +108,7 @@ public class DndTile extends QSTileImpl<BooleanState> { mSharedPreferences = sharedPreferences; mDetailAdapter = new DndDetailAdapter(); mController.observe(getLifecycle(), mZenCallback); - mSettingZenDuration = new SecureSetting(secureSettings, mUiHandler, + mSettingZenDuration = new SettingObserver(secureSettings, mUiHandler, Settings.Secure.ZEN_DURATION, getHost().getUserId()) { @Override protected void handleValueChanged(int value, boolean observedChange) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java index c8d2cdc1e478..521dbe714906 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java @@ -36,7 +36,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; -import com.android.systemui.qs.SecureSetting; +import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.settings.UserTracker; @@ -49,7 +49,7 @@ import javax.inject.Inject; public class OneHandedModeTile extends QSTileImpl<BooleanState> { private final Icon mIcon = ResourceIcon.get( com.android.internal.R.drawable.ic_qs_one_handed_mode); - private final SecureSetting mSetting; + private final SettingObserver mSetting; @Inject public OneHandedModeTile( @@ -65,7 +65,7 @@ public class OneHandedModeTile extends QSTileImpl<BooleanState> { SecureSettings secureSettings) { super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); - mSetting = new SecureSetting(secureSettings, mHandler, + mSetting = new SettingObserver(secureSettings, mHandler, Settings.Secure.ONE_HANDED_MODE_ENABLED, userTracker.getUserId()) { @Override protected void handleValueChanged(int value, boolean observedChange) { @@ -105,7 +105,8 @@ public class OneHandedModeTile extends QSTileImpl<BooleanState> { @Override public Intent getLongClickIntent() { - return new Intent(Intent.ACTION_ONE_HANDED_SETTINGS); + // TODO(b/201743873) define new intent action ACTION_ONE_HANDED_SETTINGS in Settings. + return null; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java index 1c8bd784a00d..2a7d2c35e82f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java @@ -1077,6 +1077,9 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback, params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.format = PixelFormat.TRANSLUCENT; params.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL; + params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; params.y = systemUIToast.getYOffset(); int absGravity = Gravity.getAbsoluteGravity(systemUIToast.getGravity(), diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 75b3592d4ac6..3cecbb71407a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -533,9 +533,13 @@ public class CommandQueue extends IStatusBar.Stub implements * @param animate {@code true} to show animations. */ public void recomputeDisableFlags(int displayId, boolean animate) { - int disabled1 = getDisabled1(displayId); - int disabled2 = getDisabled2(displayId); - disable(displayId, disabled1, disabled2, animate); + // This must update holding the lock otherwise it can clobber the disabled flags set on the + // binder thread from the disable() call + synchronized (mLock) { + int disabled1 = getDisabled1(displayId); + int disabled2 = getDisabled2(displayId); + disable(displayId, disabled1, disabled2, animate); + } } private void setDisabled(int displayId, int disabled1, int disabled2) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index ed36a27fcb35..190c773ef422 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -138,6 +138,7 @@ public class KeyguardIndicationController { private boolean mPowerPluggedIn; private boolean mPowerPluggedInWired; + private boolean mPowerPluggedInWireless; private boolean mPowerCharged; private boolean mBatteryOverheated; private boolean mEnableBatteryDefender; @@ -751,10 +752,14 @@ public class KeyguardIndicationController { : R.string.keyguard_plugged_in; break; } - } else { + } else if (mPowerPluggedInWireless) { chargingId = hasChargingTime ? R.string.keyguard_indication_charging_time_wireless : R.string.keyguard_plugged_in_wireless; + } else { + chargingId = hasChargingTime + ? R.string.keyguard_indication_charging_time + : R.string.keyguard_plugged_in; } String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f); @@ -866,6 +871,7 @@ public class KeyguardIndicationController { || status.status == BatteryManager.BATTERY_STATUS_FULL; boolean wasPluggedIn = mPowerPluggedIn; mPowerPluggedInWired = status.isPluggedInWired() && isChargingOrFull; + mPowerPluggedInWireless = status.isPluggedInWireless() && isChargingOrFull; mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull; mPowerCharged = status.isCharged(); mChargingWattage = status.maxChargingWattage; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index 282babc9925b..efe02ad8b931 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -449,7 +449,8 @@ public class NotificationMediaManager implements Dumpable { NotificationEntry mediaNotification = null; MediaController controller = null; for (NotificationEntry entry : allNotifications) { - if (entry.isMediaNotification()) { + Notification notif = entry.getSbn().getNotification(); + if (notif.isMediaNotification()) { final MediaSession.Token token = entry.getSbn().getNotification().extras.getParcelable( Notification.EXTRA_MEDIA_SESSION); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java index 47e8f3254742..2d6522e26686 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java @@ -395,7 +395,7 @@ public class NotifCollection implements Dumpable { final NotificationEntry entry = mNotificationSet.get(sbn.getKey()); if (entry == null) { // TODO (b/160008901): Throw an exception here - mLogger.logNoNotificationToRemoveWithKey(sbn.getKey()); + mLogger.logNoNotificationToRemoveWithKey(sbn.getKey(), reason); return; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinator.java index 992d898531b8..bd011c3847ce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinator.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import androidx.annotation.NonNull; import com.android.systemui.communal.CommunalStateController; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotifPipeline; @@ -26,6 +27,8 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; +import java.util.concurrent.Executor; + import javax.inject.Inject; /** @@ -34,14 +37,17 @@ import javax.inject.Inject; */ @CoordinatorScope public class CommunalCoordinator implements Coordinator { + final Executor mExecutor; final CommunalStateController mCommunalStateController; final NotificationEntryManager mNotificationEntryManager; final NotificationLockscreenUserManager mNotificationLockscreenUserManager; @Inject - public CommunalCoordinator(NotificationEntryManager notificationEntryManager, + public CommunalCoordinator(@Main Executor executor, + NotificationEntryManager notificationEntryManager, NotificationLockscreenUserManager notificationLockscreenUserManager, CommunalStateController communalStateController) { + mExecutor = executor; mNotificationEntryManager = notificationEntryManager; mNotificationLockscreenUserManager = notificationLockscreenUserManager; mCommunalStateController = communalStateController; @@ -57,8 +63,10 @@ public class CommunalCoordinator implements Coordinator { final CommunalStateController.Callback mStateCallback = new CommunalStateController.Callback() { @Override public void onCommunalViewShowingChanged() { - mFilter.invalidateList(); - mNotificationEntryManager.updateNotifications("Communal mode state changed"); + mExecutor.execute(() -> { + mFilter.invalidateList(); + mNotificationEntryManager.updateNotifications("Communal mode state changed"); + }); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt index 1ebc66e4c665..b4389b95c9dc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.collection.notifcollection import android.os.RemoteException +import android.service.notification.NotificationListenerService import android.service.notification.NotificationListenerService.RankingMap import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel.DEBUG @@ -25,9 +26,36 @@ import com.android.systemui.log.LogLevel.INFO import com.android.systemui.log.LogLevel.WARNING import com.android.systemui.log.LogLevel.WTF import com.android.systemui.log.dagger.NotificationLog +import com.android.systemui.statusbar.notification.collection.NotifCollection +import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason import com.android.systemui.statusbar.notification.collection.NotificationEntry import javax.inject.Inject +fun cancellationReasonDebugString(@CancellationReason reason: Int) = + "$reason:" + when (reason) { + -1 -> "REASON_NOT_CANCELED" // NotifCollection.REASON_NOT_CANCELED + NotifCollection.REASON_UNKNOWN -> "REASON_UNKNOWN" + NotificationListenerService.REASON_CLICK -> "REASON_CLICK" + NotificationListenerService.REASON_CANCEL_ALL -> "REASON_CANCEL_ALL" + NotificationListenerService.REASON_ERROR -> "REASON_ERROR" + NotificationListenerService.REASON_PACKAGE_CHANGED -> "REASON_PACKAGE_CHANGED" + NotificationListenerService.REASON_USER_STOPPED -> "REASON_USER_STOPPED" + NotificationListenerService.REASON_PACKAGE_BANNED -> "REASON_PACKAGE_BANNED" + NotificationListenerService.REASON_APP_CANCEL -> "REASON_APP_CANCEL" + NotificationListenerService.REASON_APP_CANCEL_ALL -> "REASON_APP_CANCEL_ALL" + NotificationListenerService.REASON_LISTENER_CANCEL -> "REASON_LISTENER_CANCEL" + NotificationListenerService.REASON_LISTENER_CANCEL_ALL -> "REASON_LISTENER_CANCEL_ALL" + NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED -> "REASON_GROUP_SUMMARY_CANCELED" + NotificationListenerService.REASON_GROUP_OPTIMIZATION -> "REASON_GROUP_OPTIMIZATION" + NotificationListenerService.REASON_PACKAGE_SUSPENDED -> "REASON_PACKAGE_SUSPENDED" + NotificationListenerService.REASON_PROFILE_TURNED_OFF -> "REASON_PROFILE_TURNED_OFF" + NotificationListenerService.REASON_UNAUTOBUNDLED -> "REASON_UNAUTOBUNDLED" + NotificationListenerService.REASON_CHANNEL_BANNED -> "REASON_CHANNEL_BANNED" + NotificationListenerService.REASON_SNOOZED -> "REASON_SNOOZED" + NotificationListenerService.REASON_TIMEOUT -> "REASON_TIMEOUT" + else -> "unknown" + } + class NotifCollectionLogger @Inject constructor( @NotificationLog private val buffer: LogBuffer ) { @@ -56,12 +84,12 @@ class NotifCollectionLogger @Inject constructor( }) } - fun logNotifRemoved(key: String, reason: Int) { + fun logNotifRemoved(key: String, @CancellationReason reason: Int) { buffer.log(TAG, INFO, { str1 = key int1 = reason }, { - "REMOVED $str1 reason=$int1" + "REMOVED $str1 reason=${cancellationReasonDebugString(int1)}" }) } @@ -141,11 +169,12 @@ class NotifCollectionLogger @Inject constructor( }) } - fun logNoNotificationToRemoveWithKey(key: String) { + fun logNoNotificationToRemoveWithKey(key: String, @CancellationReason reason: Int) { buffer.log(TAG, ERROR, { str1 = key + int1 = reason }, { - "No notification to remove with key $str1" + "No notification to remove with key $str1 reason=${cancellationReasonDebugString(int1)}" }) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java index 047865845c43..e7ef2ec084b7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java @@ -99,7 +99,7 @@ public class HighPriorityProvider { private boolean hasHighPriorityCharacteristics(NotificationEntry entry) { return !hasUserSetImportance(entry) - && (entry.getSbn().getNotification().hasMediaSession() + && (entry.getSbn().getNotification().isMediaNotification() || isPeopleNotification(entry) || isMessagingStyle(entry)); } 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 d90613fc0355..9f10322b5fa3 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 @@ -3203,11 +3203,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return getCurrentBottomRoundness() == 0.0f && getCurrentTopRoundness() == 0.0f; } - //TODO: this logic can't depend on layout if we are recycling! public boolean isMediaRow() { - return getExpandedContentView() != null - && getExpandedContentView().findViewById( - com.android.internal.R.id.media_actions) != null; + return mEntry.getSbn().getNotification().isMediaNotification(); } public boolean isTopLevelChild() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java index eb7410c08733..1038e76234ae 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java @@ -468,8 +468,8 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc final int height = (view instanceof ExpandableView) ? ((ExpandableView) view).getActualHeight() : view.getHeight(); - final int rx = (int) ev.getX(); - final int ry = (int) ev.getY(); + final int rx = (int) ev.getRawX(); + final int ry = (int) ev.getRawY(); int[] temp = new int[2]; view.getLocationOnScreen(temp); final int x = temp[0]; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java index fa326203b182..244103cf419e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java @@ -31,7 +31,7 @@ import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.qs.AutoAddTracker; import com.android.systemui.qs.QSTileHost; import com.android.systemui.qs.ReduceBrightColorsController; -import com.android.systemui.qs.SecureSetting; +import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.external.CustomTile; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.CastController.CastDevice; @@ -383,8 +383,8 @@ public class AutoTileManager implements UserAwareController { }; @VisibleForTesting - protected SecureSetting getSecureSettingForKey(String key) { - for (SecureSetting s : mAutoAddSettingList) { + protected SettingObserver getSecureSettingForKey(String key) { + for (SettingObserver s : mAutoAddSettingList) { if (Objects.equals(key, s.getKey())) { return s; } @@ -398,7 +398,7 @@ public class AutoTileManager implements UserAwareController { * When the setting changes to a value different from 0, if the tile has not been auto added * before, it will be added and the listener will be stopped. */ - private class AutoAddSetting extends SecureSetting { + private class AutoAddSetting extends SettingObserver { private final String mSpec; AutoAddSetting( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index 67f51cb9ab43..aa3b3e12b8f8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.content.Context; import android.content.res.Resources; import android.hardware.biometrics.BiometricSourceType; +import android.hardware.fingerprint.FingerprintManager; import android.metrics.LogMaker; import android.os.Handler; import android.os.PowerManager; @@ -46,9 +47,11 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.policy.KeyguardStateController; import java.io.FileDescriptor; @@ -71,6 +74,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000; private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock"; private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl(); + private static final int FP_ATTEMPTS_BEFORE_SHOW_BOUNCER = 3; @IntDef(prefix = { "MODE_" }, value = { MODE_NONE, @@ -167,6 +171,10 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp private final MetricsLogger mMetricsLogger; private final AuthController mAuthController; + private final StatusBarStateController mStatusBarStateController; + + private long mLastFpFailureUptimeMillis; + private int mNumConsecutiveFpFailures; private static final class PendingAuthenticated { public final int userId; @@ -209,7 +217,10 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp BIOMETRIC_IRIS_FAILURE(403), @UiEvent(doc = "A biometric event of type iris errored.") - BIOMETRIC_IRIS_ERROR(404); + BIOMETRIC_IRIS_ERROR(404), + + @UiEvent(doc = "Bouncer was shown as a result of consecutive failed UDFPS attempts.") + BIOMETRIC_BOUNCER_SHOWN(916); private final int mId; @@ -257,7 +268,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp NotificationMediaManager notificationMediaManager, WakefulnessLifecycle wakefulnessLifecycle, ScreenLifecycle screenLifecycle, - AuthController authController) { + AuthController authController, + StatusBarStateController statusBarStateController) { mContext = context; mPowerManager = powerManager; mShadeController = shadeController; @@ -279,6 +291,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mKeyguardBypassController.setUnlockController(this); mMetricsLogger = metricsLogger; mAuthController = authController; + mStatusBarStateController = statusBarStateController; dumpManager.registerDumpable(getClass().getName(), this); } @@ -620,6 +633,22 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp .setType(MetricsEvent.TYPE_FAILURE).setSubtype(toSubtype(biometricSourceType))); Optional.ofNullable(BiometricUiEvent.FAILURE_EVENT_BY_SOURCE_TYPE.get(biometricSourceType)) .ifPresent(UI_EVENT_LOGGER::log); + + long currUptimeMillis = SystemClock.uptimeMillis(); + if (currUptimeMillis - mLastFpFailureUptimeMillis < 2000) { // attempt within 2 seconds + mNumConsecutiveFpFailures += 1; + } else { + mNumConsecutiveFpFailures = 1; + } + mLastFpFailureUptimeMillis = currUptimeMillis; + + if (biometricSourceType.equals(BiometricSourceType.FINGERPRINT) + && mUpdateMonitor.isUdfpsSupported() + && mNumConsecutiveFpFailures >= FP_ATTEMPTS_BEFORE_SHOW_BOUNCER) { + mKeyguardViewController.showBouncer(true); + UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN); + mNumConsecutiveFpFailures = 0; + } cleanup(); } @@ -631,6 +660,16 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp .addTaggedData(MetricsEvent.FIELD_BIOMETRIC_AUTH_ERROR, msgId)); Optional.ofNullable(BiometricUiEvent.ERROR_EVENT_BY_SOURCE_TYPE.get(biometricSourceType)) .ifPresent(UI_EVENT_LOGGER::log); + + // if we're on the shade and we're locked out, immediately show the bouncer + if (biometricSourceType == BiometricSourceType.FINGERPRINT + && (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT + || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) + && mUpdateMonitor.isUdfpsSupported() + && (mStatusBarStateController.getState() == StatusBarState.SHADE + || mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED)) { + mKeyguardViewController.showBouncer(true); + } cleanup(); } @@ -664,6 +703,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mBiometricModeListener.onResetMode(); mBiometricModeListener.notifyBiometricAuthModeChanged(); } + mNumConsecutiveFpFailures = 0; + mLastFpFailureUptimeMillis = 0; } @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index 353868ba969f..9647486be992 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -21,6 +21,7 @@ import static com.android.systemui.plugins.ActivityStarter.OnDismissAction; import android.content.Context; import android.content.res.ColorStateList; +import android.hardware.biometrics.BiometricSourceType; import android.os.Handler; import android.os.UserHandle; import android.os.UserManager; @@ -81,6 +82,13 @@ public class KeyguardBouncer { public void onStrongAuthStateChanged(int userId) { mBouncerPromptReason = mCallback.getBouncerPromptReason(); } + + @Override + public void onLockedOutStateChanged(BiometricSourceType type) { + if (type == BiometricSourceType.FINGERPRINT) { + mBouncerPromptReason = mCallback.getBouncerPromptReason(); + } + } }; private final Runnable mRemoveViewRunnable = this::removeView; private final KeyguardBypassController mKeyguardBypassController; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index a9753acc2de0..16aac4d765a7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -506,23 +506,11 @@ public class NotificationPanelViewController extends PanelViewController { mPanelAlphaAnimator.getProperty(), Interpolators.ALPHA_IN); private final NotificationEntryManager mEntryManager; - private final CommunalSourceMonitor.Callback mCommunalSourceMonitorCallback = - new CommunalSourceMonitor.Callback() { - @Override - public void onSourceAvailable(WeakReference<CommunalSource> source) { - setCommunalSource(source); - } - }; + private final CommunalSourceMonitor.Callback mCommunalSourceMonitorCallback; private WeakReference<CommunalSource> mCommunalSource; - private final CommunalSource.Callback mCommunalSourceCallback = - new CommunalSource.Callback() { - @Override - public void onDisconnected() { - setCommunalSource(null /*source*/); - } - }; + private final CommunalSource.Callback mCommunalSourceCallback; private final CommandQueue mCommandQueue; private final NotificationLockscreenUserManager mLockscreenUserManager; @@ -904,6 +892,15 @@ public class NotificationPanelViewController extends PanelViewController { mMaxKeyguardNotifications = resources.getInteger(R.integer.keyguard_max_notification_count); mKeyguardUnfoldTransition = unfoldComponent.map(c -> c.getKeyguardUnfoldTransition()); + + mCommunalSourceCallback = () -> { + mUiExecutor.execute(() -> setCommunalSource(null /*source*/)); + }; + + mCommunalSourceMonitorCallback = (source) -> { + mUiExecutor.execute(() -> setCommunalSource(source)); + }; + updateUserSwitcherFlags(); onFinishInflate(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt index 6dd1d4c645f8..fc549e2ca8b9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt @@ -26,6 +26,7 @@ import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.qs.carrier.QSCarrierGroupController import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope +import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_BATTERY_CONTROLLER import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_HEADER import javax.inject.Inject import javax.inject.Named @@ -36,7 +37,7 @@ class SplitShadeHeaderController @Inject constructor( private val statusBarIconController: StatusBarIconController, qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder, featureFlags: FeatureFlags, - batteryMeterViewController: BatteryMeterViewController + @Named(SPLIT_SHADE_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController ) { companion object { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 67b68de4d4c8..94b010df2218 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -151,6 +151,7 @@ import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.fragments.ExtensionFragmentListener; import com.android.systemui.fragments.FragmentHostManager; +import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.KeyguardService; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.KeyguardViewMediator; @@ -491,7 +492,6 @@ public class StatusBar extends CoreStartable implements private final DozeParameters mDozeParameters; private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy; private final StatusBarComponent.Factory mStatusBarComponentFactory; - private final StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory; private final PluginManager mPluginManager; private final Optional<LegacySplitScreen> mSplitScreenOptional; private final StatusBarNotificationActivityStarter.Builder @@ -508,6 +508,7 @@ public class StatusBar extends CoreStartable implements private final NotificationsController mNotificationsController; private final OngoingCallController mOngoingCallController; private final SystemStatusAnimationScheduler mAnimationScheduler; + private final StatusBarSignalPolicy mStatusBarSignalPolicy; private final StatusBarLocationPublisher mStatusBarLocationPublisher; private final StatusBarIconController mStatusBarIconController; private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager; @@ -539,7 +540,7 @@ public class StatusBar extends CoreStartable implements protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider; private final BrightnessSliderController.Factory mBrightnessSliderFactory; private final FeatureFlags mFeatureFlags; - + private final FragmentService mFragmentService; private final WallpaperController mWallpaperController; private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; private final MessageRouter mMessageRouter; @@ -547,6 +548,8 @@ public class StatusBar extends CoreStartable implements private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private final TunerService mTunerService; + private StatusBarComponent mStatusBarComponent; + // Flags for disabling the status bar // Two variables becaseu the first one evidently ran out of room for new flags. private int mDisabled1 = 0; @@ -692,10 +695,12 @@ public class StatusBar extends CoreStartable implements public StatusBar( Context context, NotificationsController notificationsController, + FragmentService fragmentService, LightBarController lightBarController, AutoHideController autoHideController, StatusBarWindowController statusBarWindowController, KeyguardUpdateMonitor keyguardUpdateMonitor, + StatusBarSignalPolicy statusBarSignalPolicy, PulseExpansionHandler pulseExpansionHandler, NotificationWakeUpCoordinator notificationWakeUpCoordinator, KeyguardBypassController keyguardBypassController, @@ -748,7 +753,6 @@ public class StatusBar extends CoreStartable implements CommandQueue commandQueue, CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger, StatusBarComponent.Factory statusBarComponentFactory, - StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory, PluginManager pluginManager, Optional<LegacySplitScreen> splitScreenOptional, LightsOutNotifController lightsOutNotifController, @@ -793,6 +797,7 @@ public class StatusBar extends CoreStartable implements NotifPipelineFlags notifPipelineFlags) { super(context); mNotificationsController = notificationsController; + mFragmentService = fragmentService; mLightBarController = lightBarController; mAutoHideController = autoHideController; mStatusBarWindowController = statusBarWindowController; @@ -854,7 +859,6 @@ public class StatusBar extends CoreStartable implements mCommandQueue = commandQueue; mCollapsedStatusBarFragmentLogger = collapsedStatusBarFragmentLogger; mStatusBarComponentFactory = statusBarComponentFactory; - mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory; mPluginManager = pluginManager; mSplitScreenOptional = splitScreenOptional; mStatusBarNotificationActivityStarterBuilder = statusBarNotificationActivityStarterBuilder; @@ -874,6 +878,7 @@ public class StatusBar extends CoreStartable implements mWallpaperController = wallpaperController; mOngoingCallController = ongoingCallController; mAnimationScheduler = animationScheduler; + mStatusBarSignalPolicy = statusBarSignalPolicy; mStatusBarLocationPublisher = locationPublisher; mStatusBarIconController = statusBarIconController; mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager; @@ -928,6 +933,7 @@ public class StatusBar extends CoreStartable implements mBubblesOptional.get().setExpandListener(mBubbleExpandListener); } + mStatusBarSignalPolicy.init(); mKeyguardIndicationController.init(); mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener); @@ -1185,24 +1191,7 @@ public class StatusBar extends CoreStartable implements }).getFragmentManager() .beginTransaction() .replace(R.id.status_bar_container, - new CollapsedStatusBarFragment( - mStatusBarFragmentComponentFactory, - mOngoingCallController, - mAnimationScheduler, - mStatusBarLocationPublisher, - mNotificationIconAreaController, - mPanelExpansionStateManager, - mFeatureFlags, - mStatusBarIconController, - mStatusBarHideIconsForBouncerManager, - mKeyguardStateController, - mNetworkController, - mStatusBarStateController, - () -> Optional.of(this), - mCommandQueue, - mCollapsedStatusBarFragmentLogger, - mOperatorNameViewControllerFactory - ), + mStatusBarComponent.createCollapsedStatusBarFragment(), CollapsedStatusBarFragment.TAG) .commit(); @@ -1558,32 +1547,34 @@ public class StatusBar extends CoreStartable implements } private void inflateStatusBarWindow() { - StatusBarComponent statusBarComponent = mStatusBarComponentFactory.create(); - mNotificationShadeWindowView = statusBarComponent.getNotificationShadeWindowView(); - mNotificationShadeWindowViewController = statusBarComponent + mStatusBarComponent = mStatusBarComponentFactory.create(); + mFragmentService.addFragmentInstantiationProvider(mStatusBarComponent); + + mNotificationShadeWindowView = mStatusBarComponent.getNotificationShadeWindowView(); + mNotificationShadeWindowViewController = mStatusBarComponent .getNotificationShadeWindowViewController(); mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView); mNotificationShadeWindowViewController.setupExpandedStatusBar(); - mNotificationPanelViewController = statusBarComponent.getNotificationPanelViewController(); - statusBarComponent.getLockIconViewController().init(); - mStackScrollerController = statusBarComponent.getNotificationStackScrollLayoutController(); + mNotificationPanelViewController = mStatusBarComponent.getNotificationPanelViewController(); + mStatusBarComponent.getLockIconViewController().init(); + mStackScrollerController = mStatusBarComponent.getNotificationStackScrollLayoutController(); mStackScroller = mStackScrollerController.getView(); - mNotificationShelfController = statusBarComponent.getNotificationShelfController(); - mAuthRippleController = statusBarComponent.getAuthRippleController(); + mNotificationShelfController = mStatusBarComponent.getNotificationShelfController(); + mAuthRippleController = mStatusBarComponent.getAuthRippleController(); mAuthRippleController.init(); - mHeadsUpManager.addListener(statusBarComponent.getStatusBarHeadsUpChangeListener()); + mHeadsUpManager.addListener(mStatusBarComponent.getStatusBarHeadsUpChangeListener()); - mHeadsUpManager.addListener(statusBarComponent.getStatusBarHeadsUpChangeListener()); + mHeadsUpManager.addListener(mStatusBarComponent.getStatusBarHeadsUpChangeListener()); // Listen for demo mode changes - mDemoModeController.addCallback(statusBarComponent.getStatusBarDemoMode()); + mDemoModeController.addCallback(mStatusBarComponent.getStatusBarDemoMode()); if (mCommandQueueCallbacks != null) { mCommandQueue.removeCallback(mCommandQueueCallbacks); } - mCommandQueueCallbacks = statusBarComponent.getStatusBarCommandQueueCallbacks(); + mCommandQueueCallbacks = mStatusBarComponent.getStatusBarCommandQueueCallbacks(); // Connect in to the status bar manager service mCommandQueue.addCallback(mCommandQueueCallbacks); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 7ab4a1ec237e..0d23d663c51c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -441,6 +441,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb * dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)} */ public void showBouncer(boolean scrimmed) { + resetAlternateAuth(false); + if (mShowing && !mBouncer.isShowing()) { mBouncer.show(false /* resetSecuritySelection */, scrimmed); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java index 6c81054eb248..b0206f073011 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java @@ -73,17 +73,15 @@ public class StatusBarSignalPolicy implements SignalCallback, private boolean mHideWifi; private boolean mHideEthernet; private boolean mActivityEnabled; - private boolean mForceHideWifi; // Track as little state as possible, and only for padding purposes private boolean mIsAirplaneMode = false; private boolean mIsWifiEnabled = false; - private boolean mWifiVisible = false; - private ArrayList<MobileIconState> mMobileStates = new ArrayList<MobileIconState>(); - private ArrayList<CallIndicatorIconState> mCallIndicatorStates = - new ArrayList<CallIndicatorIconState>(); + private ArrayList<MobileIconState> mMobileStates = new ArrayList<>(); + private ArrayList<CallIndicatorIconState> mCallIndicatorStates = new ArrayList<>(); private WifiIconState mWifiIconState = new WifiIconState(); + private boolean mInitialized; @Inject public StatusBarSignalPolicy( @@ -113,9 +111,15 @@ public class StatusBarSignalPolicy implements SignalCallback, mSlotCallStrength = mContext.getString(com.android.internal.R.string.status_bar_call_strength); mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity); + } - - tunerService.addTunable(this, StatusBarIconController.ICON_HIDE_LIST); + /** Call to initilaize and register this classw with the system. */ + public void init() { + if (mInitialized) { + return; + } + mInitialized = true; + mTunerService.addTunable(this, StatusBarIconController.ICON_HIDE_LIST); mNetworkController.addCallback(this); mSecurityController.addCallback(this); } @@ -163,7 +167,7 @@ public class StatusBarSignalPolicy implements SignalCallback, mHideAirplane = hideAirplane; mHideMobile = hideMobile; mHideEthernet = hideEthernet; - mHideWifi = hideWifi || mForceHideWifi; + mHideWifi = hideWifi; // Re-register to get new callbacks. mNetworkController.removeCallback(this); mNetworkController.addCallback(this); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java index e06605eac46f..375641fdb69d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java @@ -29,6 +29,7 @@ import com.android.systemui.statusbar.phone.SplitShadeHeaderController; import com.android.systemui.statusbar.phone.StatusBarCommandQueueCallbacks; import com.android.systemui.statusbar.phone.StatusBarDemoMode; import com.android.systemui.statusbar.phone.StatusBarHeadsUpChangeListener; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -38,7 +39,13 @@ import javax.inject.Scope; import dagger.Subcomponent; /** - * Dagger subcomponent tied to the lifecycle of StatusBar views. + * Dagger subcomponent for classes (semi-)related to the status bar. The component is created once + * inside {@link com.android.systemui.statusbar.phone.StatusBar} and never re-created. + * + * TODO(b/197137564): This should likely be re-factored a bit. It includes classes that aren't + * directly related to status bar functionality, like multiple notification classes. And, the fact + * that it has many getter methods indicates that we need to access many of these classes from + * outside the component. Should more items be moved *into* this component to avoid so many getters? */ @Subcomponent(modules = {StatusBarViewModule.class}) @StatusBarComponent.StatusBarScope @@ -121,4 +128,10 @@ public interface StatusBarComponent { */ @StatusBarScope SplitShadeHeaderController getSplitShadeHeaderController(); + + /** + * Creates a new {@link CollapsedStatusBarFragment} each time it's called. See + * {@link StatusBarViewModule#createCollapsedStatusBarFragment}. + */ + CollapsedStatusBarFragment createCollapsedStatusBarFragment(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index 1c3229f70b32..b3f59b461aa9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -39,6 +39,7 @@ import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; @@ -97,10 +98,10 @@ import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.phone.StatusBarLocationPublisher; import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter; +import com.android.systemui.statusbar.phone.StatusBarSignalPolicy; import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager; import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger; -import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.BatteryController; @@ -143,10 +144,12 @@ public interface StatusBarPhoneModule { static StatusBar provideStatusBar( Context context, NotificationsController notificationsController, + FragmentService fragmentService, LightBarController lightBarController, AutoHideController autoHideController, StatusBarWindowController statusBarWindowController, KeyguardUpdateMonitor keyguardUpdateMonitor, + StatusBarSignalPolicy statusBarSignalPolicy, PulseExpansionHandler pulseExpansionHandler, NotificationWakeUpCoordinator notificationWakeUpCoordinator, KeyguardBypassController keyguardBypassController, @@ -199,7 +202,6 @@ public interface StatusBarPhoneModule { CommandQueue commandQueue, CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger, StatusBarComponent.Factory statusBarComponentFactory, - StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory, PluginManager pluginManager, Optional<LegacySplitScreen> splitScreenOptional, LightsOutNotifController lightsOutNotifController, @@ -245,10 +247,12 @@ public interface StatusBarPhoneModule { return new StatusBar( context, notificationsController, + fragmentService, lightBarController, autoHideController, statusBarWindowController, keyguardUpdateMonitor, + statusBarSignalPolicy, pulseExpansionHandler, notificationWakeUpCoordinator, keyguardBypassController, @@ -301,7 +305,6 @@ public interface StatusBarPhoneModule { commandQueue, collapsedStatusBarFragmentLogger, statusBarComponentFactory, - statusBarFragmentComponentFactory, pluginManager, splitScreenOptional, lightsOutNotifController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java index 38df95aada07..8f11819b9677 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java @@ -17,6 +17,8 @@ package com.android.systemui.statusbar.phone.dagger; import android.annotation.Nullable; +import android.content.ContentResolver; +import android.os.Handler; import android.view.LayoutInflater; import android.view.View; import android.view.ViewStub; @@ -24,20 +26,46 @@ import android.view.ViewStub; import com.android.keyguard.LockIconView; import com.android.systemui.R; import com.android.systemui.battery.BatteryMeterView; +import com.android.systemui.battery.BatteryMeterViewController; import com.android.systemui.biometrics.AuthRippleView; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelfController; +import com.android.systemui.statusbar.OperatorNameViewController; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; +import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.NotificationPanelView; +import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer; +import com.android.systemui.statusbar.phone.StatusBar; +import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager; +import com.android.systemui.statusbar.phone.StatusBarIconController; +import com.android.systemui.statusbar.phone.StatusBarLocationPublisher; import com.android.systemui.statusbar.phone.TapAgainView; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; +import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger; +import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; +import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; +import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; +import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.tuner.TunerService; + +import java.util.Optional; import javax.inject.Named; +import dagger.Lazy; import dagger.Module; import dagger.Provides; @@ -45,6 +73,8 @@ import dagger.Provides; public abstract class StatusBarViewModule { public static final String SPLIT_SHADE_HEADER = "split_shade_header"; + private static final String SPLIT_SHADE_BATTERY_VIEW = "split_shade_battery_view"; + public static final String SPLIT_SHADE_BATTERY_CONTROLLER = "split_shade_battery_controller"; /** */ @Provides @@ -144,10 +174,34 @@ public abstract class StatusBarViewModule { /** */ @Provides @StatusBarComponent.StatusBarScope + @Named(SPLIT_SHADE_BATTERY_VIEW) static BatteryMeterView getBatteryMeterView(@Named(SPLIT_SHADE_HEADER) View view) { return view.findViewById(R.id.batteryRemainingIcon); } + @Provides + @StatusBarComponent.StatusBarScope + @Named(SPLIT_SHADE_BATTERY_CONTROLLER) + static BatteryMeterViewController getBatteryMeterViewController( + @Named(SPLIT_SHADE_BATTERY_VIEW) BatteryMeterView batteryMeterView, + ConfigurationController configurationController, + TunerService tunerService, + BroadcastDispatcher broadcastDispatcher, + @Main Handler mainHandler, + ContentResolver contentResolver, + BatteryController batteryController + ) { + return new BatteryMeterViewController( + batteryMeterView, + configurationController, + tunerService, + broadcastDispatcher, + mainHandler, + contentResolver, + batteryController); + + } + /** */ @Provides @StatusBarComponent.StatusBarScope @@ -162,4 +216,54 @@ public abstract class StatusBarViewModule { NotificationShadeWindowView notificationShadeWindowView) { return notificationShadeWindowView.findViewById(R.id.notification_container_parent); } + + /** + * Creates a new {@link CollapsedStatusBarFragment}. + * + * **IMPORTANT**: This method intentionally does not have + * {@link StatusBarComponent.StatusBarScope}, which means a new fragment *will* be created each + * time this method is called. This is intentional because we need fragments to re-created in + * certain lifecycle scenarios. + * + * **IMPORTANT**: This method also intentionally does not have a {@link Provides} annotation. If + * you need to get access to a {@link CollapsedStatusBarFragment}, go through + * {@link StatusBarFragmentComponent} instead. + */ + public static CollapsedStatusBarFragment createCollapsedStatusBarFragment( + StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory, + OngoingCallController ongoingCallController, + SystemStatusAnimationScheduler animationScheduler, + StatusBarLocationPublisher locationPublisher, + NotificationIconAreaController notificationIconAreaController, + PanelExpansionStateManager panelExpansionStateManager, + FeatureFlags featureFlags, + StatusBarIconController statusBarIconController, + StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, + KeyguardStateController keyguardStateController, + NotificationPanelViewController notificationPanelViewController, + NetworkController networkController, + StatusBarStateController statusBarStateController, + Lazy<Optional<StatusBar>> statusBarOptionalLazy, + CommandQueue commandQueue, + CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger, + OperatorNameViewController.Factory operatorNameViewControllerFactory + ) { + return new CollapsedStatusBarFragment(statusBarFragmentComponentFactory, + ongoingCallController, + animationScheduler, + locationPublisher, + notificationIconAreaController, + panelExpansionStateManager, + featureFlags, + statusBarIconController, + statusBarHideIconsForBouncerManager, + keyguardStateController, + notificationPanelViewController, + networkController, + statusBarStateController, + statusBarOptionalLazy, + commandQueue, + collapsedStatusBarFragmentLogger, + operatorNameViewControllerFactory); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index 2880e4dc7033..2e3893a8c21b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -53,6 +53,7 @@ import com.android.systemui.statusbar.connectivity.SignalCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.phone.NotificationIconAreaController; +import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager; @@ -94,6 +95,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private PhoneStatusBarView mStatusBar; private final StatusBarStateController mStatusBarStateController; private final KeyguardStateController mKeyguardStateController; + private final NotificationPanelViewController mNotificationPanelViewController; private final NetworkController mNetworkController; private LinearLayout mSystemIconArea; private View mClockView; @@ -146,6 +148,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue StatusBarIconController statusBarIconController, StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, KeyguardStateController keyguardStateController, + NotificationPanelViewController notificationPanelViewController, NetworkController networkController, StatusBarStateController statusBarStateController, Lazy<Optional<StatusBar>> statusBarOptionalLazy, @@ -163,6 +166,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mStatusBarIconController = statusBarIconController; mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager; mKeyguardStateController = keyguardStateController; + mNotificationPanelViewController = notificationPanelViewController; mNetworkController = networkController; mStatusBarStateController = statusBarStateController; mStatusBarOptionalLazy = statusBarOptionalLazy; @@ -354,8 +358,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue // The shelf will be hidden when dozing with a custom clock, we must show notification // icons in this occasion. if (mStatusBarStateController.isDozing() - && mStatusBarOptionalLazy.get().map( - sb -> sb.getPanelController().hasCustomClock()).orElse(false)) { + && mNotificationPanelViewController.hasCustomClock()) { state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java index 5acce7f80f6c..b5ee62df890b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java @@ -45,9 +45,10 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; -import com.android.systemui.qs.GlobalSetting; +import com.android.systemui.qs.SettingObserver; import com.android.systemui.settings.CurrentUserTracker; import com.android.systemui.util.Utils; +import com.android.systemui.util.settings.GlobalSettings; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -66,8 +67,8 @@ public class ZenModeControllerImpl extends CurrentUserTracker private final ArrayList<Callback> mCallbacks = new ArrayList<>(); private final Object mCallbacksLock = new Object(); private final Context mContext; - private final GlobalSetting mModeSetting; - private final GlobalSetting mConfigSetting; + private final SettingObserver mModeSetting; + private final SettingObserver mConfigSetting; private final NotificationManager mNoMan; private final AlarmManager mAlarmManager; private final SetupObserver mSetupObserver; @@ -85,19 +86,20 @@ public class ZenModeControllerImpl extends CurrentUserTracker Context context, @Main Handler handler, BroadcastDispatcher broadcastDispatcher, - DumpManager dumpManager) { + DumpManager dumpManager, + GlobalSettings globalSettings) { super(broadcastDispatcher); mContext = context; - mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) { + mModeSetting = new SettingObserver(globalSettings, handler, Global.ZEN_MODE) { @Override - protected void handleValueChanged(int value) { + protected void handleValueChanged(int value, boolean observedChange) { updateZenMode(value); fireZenChanged(value); } }; - mConfigSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE_CONFIG_ETAG) { + mConfigSetting = new SettingObserver(globalSettings, handler, Global.ZEN_MODE_CONFIG_ETAG) { @Override - protected void handleValueChanged(int value) { + protected void handleValueChanged(int value, boolean observedChange) { updateZenModeConfig(); } }; diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index 66c70edbc3fc..63ca94cde7cf 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -65,6 +65,7 @@ import com.android.wm.shell.onehanded.OneHandedTransitionCallback; import com.android.wm.shell.onehanded.OneHandedUiEventLogger; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.protolog.ShellProtoLogImpl; +import com.android.wm.shell.sizecompatui.SizeCompatUI; import com.android.wm.shell.splitscreen.SplitScreen; import java.io.FileDescriptor; @@ -112,6 +113,7 @@ public final class WMShell extends CoreStartable private final Optional<OneHanded> mOneHandedOptional; private final Optional<HideDisplayCutout> mHideDisplayCutoutOptional; private final Optional<ShellCommandHandler> mShellCommandHandler; + private final Optional<SizeCompatUI> mSizeCompatUIOptional; private final CommandQueue mCommandQueue; private final ConfigurationController mConfigurationController; @@ -128,6 +130,7 @@ public final class WMShell extends CoreStartable private KeyguardUpdateMonitorCallback mSplitScreenKeyguardCallback; private KeyguardUpdateMonitorCallback mPipKeyguardCallback; private KeyguardUpdateMonitorCallback mOneHandedKeyguardCallback; + private KeyguardUpdateMonitorCallback mSizeCompatUIKeyguardCallback; private WakefulnessLifecycle.Observer mWakefulnessObserver; @Inject @@ -138,6 +141,7 @@ public final class WMShell extends CoreStartable Optional<OneHanded> oneHandedOptional, Optional<HideDisplayCutout> hideDisplayCutoutOptional, Optional<ShellCommandHandler> shellCommandHandler, + Optional<SizeCompatUI> sizeCompatUIOptional, CommandQueue commandQueue, ConfigurationController configurationController, KeyguardUpdateMonitor keyguardUpdateMonitor, @@ -162,6 +166,7 @@ public final class WMShell extends CoreStartable mWakefulnessLifecycle = wakefulnessLifecycle; mProtoTracer = protoTracer; mShellCommandHandler = shellCommandHandler; + mSizeCompatUIOptional = sizeCompatUIOptional; mSysUiMainExecutor = sysUiMainExecutor; } @@ -176,6 +181,7 @@ public final class WMShell extends CoreStartable mSplitScreenOptional.ifPresent(this::initSplitScreen); mOneHandedOptional.ifPresent(this::initOneHanded); mHideDisplayCutoutOptional.ifPresent(this::initHideDisplayCutout); + mSizeCompatUIOptional.ifPresent(this::initSizeCompatUi); } @VisibleForTesting @@ -254,6 +260,18 @@ public final class WMShell extends CoreStartable } }; mKeyguardUpdateMonitor.registerCallback(mSplitScreenKeyguardCallback); + + mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() { + @Override + public void onFinishedWakingUp() { + splitScreen.onFinishedWakingUp(); + } + + @Override + public void onFinishedGoingToSleep() { + splitScreen.onFinishedGoingToSleep(); + } + }); } @VisibleForTesting @@ -367,6 +385,17 @@ public final class WMShell extends CoreStartable }); } + @VisibleForTesting + void initSizeCompatUi(SizeCompatUI sizeCompatUI) { + mSizeCompatUIKeyguardCallback = new KeyguardUpdateMonitorCallback() { + @Override + public void onKeyguardOccludedChanged(boolean occluded) { + sizeCompatUI.onKeyguardOccludedChanged(occluded); + } + }; + mKeyguardUpdateMonitor.registerCallback(mSizeCompatUIKeyguardCallback); + } + @Override public void writeToProto(SystemUiTraceProto proto) { if (proto.wmShell == null) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java index 77286b11f652..326d90260137 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java @@ -64,7 +64,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { @Mock private IWindowMagnificationConnectionCallback mConnectionCallback; @Mock - private WindowMagnificationAnimationController mWindowMagnificationAnimationController; + private WindowMagnificationController mWindowMagnificationController; @Mock private ModeSwitchesController mModeSwitchesController; @Mock @@ -89,7 +89,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { mWindowMagnification = new WindowMagnification(getContext(), getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController, mSysUiState, mOverviewProxyService); - mWindowMagnification.mAnimationControllerSupplier = new FakeAnimationControllerSupplier( + mWindowMagnification.mMagnificationControllerSupplier = new FakeControllerSupplier( mContext.getSystemService(DisplayManager.class)); mWindowMagnification.requestWindowMagnificationConnection(true); @@ -103,7 +103,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { Float.NaN, mAnimationCallback); waitForIdleSync(); - verify(mWindowMagnificationAnimationController).enableWindowMagnification(eq(3.0f), + verify(mWindowMagnificationController).enableWindowMagnification(eq(3.0f), eq(Float.NaN), eq(Float.NaN), eq(mAnimationCallback)); } @@ -113,7 +113,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { mAnimationCallback); waitForIdleSync(); - verify(mWindowMagnificationAnimationController).deleteWindowMagnification( + verify(mWindowMagnificationController).deleteWindowMagnification( mAnimationCallback); } @@ -122,7 +122,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { mIWindowMagnificationConnection.setScale(TEST_DISPLAY, 3.0f); waitForIdleSync(); - verify(mWindowMagnificationAnimationController).setScale(3.0f); + verify(mWindowMagnificationController).setScale(3.0f); } @Test @@ -130,7 +130,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { mIWindowMagnificationConnection.moveWindowMagnifier(TEST_DISPLAY, 100f, 200f); waitForIdleSync(); - verify(mWindowMagnificationAnimationController).moveWindowMagnifier(100f, 200f); + verify(mWindowMagnificationController).moveWindowMagnifier(100f, 200f); } @Test @@ -151,16 +151,16 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { verify(mModeSwitchesController).removeButton(TEST_DISPLAY); } - private class FakeAnimationControllerSupplier extends - DisplayIdIndexSupplier<WindowMagnificationAnimationController> { + private class FakeControllerSupplier extends + DisplayIdIndexSupplier<WindowMagnificationController> { - FakeAnimationControllerSupplier(DisplayManager displayManager) { + FakeControllerSupplier(DisplayManager displayManager) { super(displayManager); } @Override - protected WindowMagnificationAnimationController createInstance(Display display) { - return mWindowMagnificationAnimationController; + protected WindowMagnificationController createInstance(Display display) { + return mWindowMagnificationController; } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java index 148c6ef0be53..854fc33d768d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java @@ -100,12 +100,13 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { mInstrumentation = InstrumentationRegistry.getInstrumentation(); mWaitingAnimationPeriod = 2 * ANIMATION_DURATION_MS; mWaitIntermediateAnimationPeriod = ANIMATION_DURATION_MS / 2; + mWindowMagnificationAnimationController = new WindowMagnificationAnimationController( + mContext, newValueAnimator()); mController = new SpyWindowMagnificationController(mContext, mHandler, + mWindowMagnificationAnimationController, mSfVsyncFrameProvider, null, new SurfaceControl.Transaction(), mWindowMagnifierCallback, mSysUiState); mSpyController = mController.getSpyController(); - mWindowMagnificationAnimationController = new WindowMagnificationAnimationController( - mContext, mController, newValueAnimator()); } @After @@ -383,17 +384,6 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { } @Test - public void setScale_enabled_expectedScale() { - enableWindowMagnificationWithoutAnimation(); - - mInstrumentation.runOnMainSync( - () -> mWindowMagnificationAnimationController.setScale(DEFAULT_SCALE + 1)); - - verify(mSpyController).setScale(DEFAULT_SCALE + 1); - verifyFinalSpec(DEFAULT_SCALE + 1, DEFAULT_CENTER_X, DEFAULT_CENTER_Y); - } - - @Test public void deleteWindowMagnification_enabled_expectedValuesAndInvokeCallback() throws RemoteException { enableWindowMagnificationWithoutAnimation(); @@ -508,26 +498,12 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { enableWindowMagnificationWithoutAnimation(); mInstrumentation.runOnMainSync( - () -> mWindowMagnificationAnimationController.moveWindowMagnifier(100f, 200f)); + () -> mController.moveWindowMagnifier(100f, 200f)); verify(mSpyController).moveWindowMagnifier(100f, 200f); verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + 100f, DEFAULT_CENTER_Y + 100f); } - @Test - public void onConfigurationChanged_passThrough() { - mWindowMagnificationAnimationController.onConfigurationChanged(100); - - verify(mSpyController).onConfigurationChanged(100); - } - - @Test - public void updateSysUiStateFlag_passThrough() { - mWindowMagnificationAnimationController.updateSysUiStateFlag(); - - verify(mSpyController).updateSysUIStateFlag(); - } - private void verifyFinalSpec(float expectedScale, float expectedCenterX, float expectedCenterY) { assertEquals(expectedScale, mController.getScale(), 0f); @@ -581,11 +557,12 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { private WindowMagnificationController mSpyController; SpyWindowMagnificationController(Context context, Handler handler, + WindowMagnificationAnimationController animationController, SfVsyncFrameCallbackProvider sfVsyncFrameProvider, MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction, WindowMagnifierCallback callback, SysUiState sysUiState) { - super(context, handler, sfVsyncFrameProvider, mirrorWindowControl, transaction, - callback, sysUiState); + super(context, handler, animationController, sfVsyncFrameProvider, mirrorWindowControl, + transaction, callback, sysUiState); mSpyController = Mockito.mock(WindowMagnificationController.class); } @@ -622,12 +599,6 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { super.updateSysUIStateFlag(); mSpyController.updateSysUIStateFlag(); } - - @Override - void onConfigurationChanged(int configDiff) { - super.onConfigurationChanged(configDiff); - mSpyController.onConfigurationChanged(configDiff); - } } private static ValueAnimator newValueAnimator() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index 70457cf46e0d..9a3046554e0c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -89,6 +89,8 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Mock private Handler mHandler; @Mock + private WindowMagnificationAnimationController mWindowMagnificationAnimationController; + @Mock private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; @Mock private MirrorWindowControl mMirrorWindowControl; @@ -128,7 +130,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { mResources = getContext().getOrCreateTestableResources().getResources(); mWindowMagnificationController = new WindowMagnificationController(mContext, - mHandler, mSfVsyncFrameProvider, + mHandler, mWindowMagnificationAnimationController, mSfVsyncFrameProvider, mMirrorWindowControl, mTransaction, mWindowMagnifierCallback, mSysUiState); verify(mMirrorWindowControl).setWindowDelegate( @@ -174,7 +176,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { mWindowManager.setWindowBounds(new Rect(0, 0, screenSize, screenSize)); //We need to initialize new one because the window size is determined when initialization. final WindowMagnificationController controller = new WindowMagnificationController(mContext, - mHandler, mSfVsyncFrameProvider, + mHandler, mWindowMagnificationAnimationController, mSfVsyncFrameProvider, mMirrorWindowControl, mTransaction, mWindowMagnifierCallback, mSysUiState); mInstrumentation.runOnMainSync(() -> { diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java index fb1716aed474..c898150d857c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java @@ -167,30 +167,29 @@ public class WindowMagnificationTest extends SysuiTestCase { @Test public void overviewProxyIsConnected_controllerIsAvailable_updateSysUiStateFlag() { - final WindowMagnificationAnimationController mController = mock( - WindowMagnificationAnimationController.class); - mWindowMagnification.mAnimationControllerSupplier = new FakeAnimationControllerSupplier( + final WindowMagnificationController mController = mock(WindowMagnificationController.class); + mWindowMagnification.mMagnificationControllerSupplier = new FakeControllerSupplier( mContext.getSystemService(DisplayManager.class), mController); - mWindowMagnification.mAnimationControllerSupplier.get(TEST_DISPLAY); + mWindowMagnification.mMagnificationControllerSupplier.get(TEST_DISPLAY); mOverviewProxyListener.onConnectionChanged(true); - verify(mController).updateSysUiStateFlag(); + verify(mController).updateSysUIStateFlag(); } - private static class FakeAnimationControllerSupplier extends - DisplayIdIndexSupplier<WindowMagnificationAnimationController> { + private static class FakeControllerSupplier extends + DisplayIdIndexSupplier<WindowMagnificationController> { - private final WindowMagnificationAnimationController mController; + private final WindowMagnificationController mController; - FakeAnimationControllerSupplier(DisplayManager displayManager, - WindowMagnificationAnimationController controller) { + FakeControllerSupplier(DisplayManager displayManager, + WindowMagnificationController controller) { super(displayManager); mController = controller; } @Override - protected WindowMagnificationAnimationController createInstance(Display display) { + protected WindowMagnificationController createInstance(Display display) { return mController; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java index 0e86964147d7..1cf21ac40e31 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java @@ -351,9 +351,8 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase { mSystemClock.advanceTime(205); mController.onTouchOutsideView(); - // THEN show the bouncer and reset alt auth + // THEN show the bouncer verify(mStatusBarKeyguardViewManager).showBouncer(eq(true)); - verify(mStatusBarKeyguardViewManager).resetAlternateAuth(anyBoolean()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalSourcePrimerTest.java b/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalSourcePrimerTest.java new file mode 100644 index 000000000000..659b1a31a7a7 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalSourcePrimerTest.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.communal; + +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.res.Resources; +import android.testing.AndroidTestingRunner; + +import androidx.concurrent.futures.CallbackToFutureAdapter; +import androidx.test.filters.SmallTest; + +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import java.util.Optional; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class CommunalSourcePrimerTest extends SysuiTestCase { + private static final String TEST_COMPONENT_NAME = "com.google.tests/.CommunalService"; + private static final int MAX_RETRIES = 5; + private static final int RETRY_DELAY_MS = 1000; + + @Mock + private Context mContext; + + @Mock + private Resources mResources; + + private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); + + @Mock + private CommunalSource mSource; + + @Mock + private CommunalSourceMonitor mCommunalSourceMonitor; + + @Mock + private CommunalSource.Connector mConnector; + + @Mock + private CommunalSource.Observer mObserver; + + private CommunalSourcePrimer mPrimer; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + when(mResources.getInteger(R.integer.config_communalSourceMaxReconnectAttempts)) + .thenReturn(MAX_RETRIES); + when(mResources.getInteger(R.integer.config_communalSourceReconnectBaseDelay)) + .thenReturn(RETRY_DELAY_MS); + when(mResources.getString(R.string.config_communalSourceComponent)) + .thenReturn(TEST_COMPONENT_NAME); + + mPrimer = new CommunalSourcePrimer(mContext, mResources, mFakeExecutor, + mCommunalSourceMonitor, Optional.of(mConnector), Optional.of(mObserver)); + } + + @Test + public void testConnect() { + when(mConnector.connect()).thenReturn( + CallbackToFutureAdapter.getFuture(completer -> { + completer.set(Optional.of(mSource)); + return "test"; + })); + + mPrimer.onBootCompleted(); + mFakeExecutor.runAllReady(); + verify(mCommunalSourceMonitor).setSource(mSource); + } + + @Test + public void testRetryOnBindFailure() throws Exception { + when(mConnector.connect()).thenReturn( + CallbackToFutureAdapter.getFuture(completer -> { + completer.set(Optional.empty()); + return "test"; + })); + + mPrimer.onBootCompleted(); + mFakeExecutor.runAllReady(); + + // Verify attempts happen. Note that we account for the retries plus initial attempt, which + // is not scheduled. + for (int attemptCount = 0; attemptCount < MAX_RETRIES + 1; attemptCount++) { + verify(mConnector, times(1)).connect(); + clearInvocations(mConnector); + mFakeExecutor.advanceClockToNext(); + mFakeExecutor.runAllReady(); + } + + verify(mCommunalSourceMonitor, never()).setSource(Mockito.notNull()); + } + + @Test + public void testAttemptOnPackageChange() { + when(mConnector.connect()).thenReturn( + CallbackToFutureAdapter.getFuture(completer -> { + completer.set(Optional.empty()); + return "test"; + })); + + mPrimer.onBootCompleted(); + mFakeExecutor.runAllReady(); + + final ArgumentCaptor<CommunalSource.Observer.Callback> callbackCaptor = + ArgumentCaptor.forClass(CommunalSource.Observer.Callback.class); + verify(mObserver).addCallback(callbackCaptor.capture()); + + clearInvocations(mConnector); + callbackCaptor.getValue().onSourceChanged(); + + verify(mConnector, times(1)).connect(); + } + + @Test + public void testDisconnect() { + final ArgumentCaptor<CommunalSource.Callback> callbackCaptor = + ArgumentCaptor.forClass(CommunalSource.Callback.class); + + when(mConnector.connect()).thenReturn( + CallbackToFutureAdapter.getFuture(completer -> { + completer.set(Optional.of(mSource)); + return "test"; + })); + + mPrimer.onBootCompleted(); + mFakeExecutor.runAllReady(); + verify(mCommunalSourceMonitor).setSource(mSource); + verify(mSource).addCallback(callbackCaptor.capture()); + + clearInvocations(mConnector); + callbackCaptor.getValue().onDisconnected(); + mFakeExecutor.runAllReady(); + + verify(mConnector).connect(); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java index f525fee27e20..f207b9eb7e54 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java @@ -17,6 +17,7 @@ package com.android.systemui.doze; import static com.android.systemui.doze.DozeLog.REASON_SENSOR_TAP; +import static com.android.systemui.doze.DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS; import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN; import static org.junit.Assert.assertEquals; @@ -37,6 +38,7 @@ import static org.mockito.Mockito.when; import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.display.AmbientDisplayConfiguration; +import android.os.UserHandle; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; @@ -57,6 +59,8 @@ import com.android.systemui.util.wakelock.WakeLock; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -94,6 +98,13 @@ public class DozeSensorsTest extends SysuiTestCase { private DevicePostureController mDevicePostureController; @Mock private ProximitySensor mProximitySensor; + + // Capture listeners so that they can be used to send events + @Captor + private ArgumentCaptor<AuthController.Callback> mAuthControllerCallbackCaptor = + ArgumentCaptor.forClass(AuthController.Callback.class); + private AuthController.Callback mAuthControllerCallback; + private FakeSettings mFakeSettings = new FakeSettings(); private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener; private TestableLooper mTestableLooper; @@ -105,14 +116,18 @@ public class DozeSensorsTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mTestableLooper = TestableLooper.get(this); when(mAmbientDisplayConfiguration.tapSensorTypeMapping()) - .thenReturn(new String[]{"tapSEnsor"}); + .thenReturn(new String[]{"tapSensor"}); when(mAmbientDisplayConfiguration.getWakeLockScreenDebounce()).thenReturn(5000L); when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true); + when(mAmbientDisplayConfiguration.enabled(UserHandle.USER_CURRENT)).thenReturn(true); doAnswer(invocation -> { ((Runnable) invocation.getArgument(0)).run(); return null; }).when(mWakeLock).wrap(any(Runnable.class)); mDozeSensors = new TestableDozeSensors(); + + verify(mAuthController).addCallback(mAuthControllerCallbackCaptor.capture()); + mAuthControllerCallback = mAuthControllerCallbackCaptor.getValue(); } @Test @@ -375,6 +390,47 @@ public class DozeSensorsTest extends SysuiTestCase { "some other name")); } + @Test + public void testUdfpsEnrollmentChanged() throws Exception { + // GIVEN a UDFPS_LONG_PRESS trigger sensor that's not configured + Sensor mockSensor = mock(Sensor.class); + TriggerSensor triggerSensor = mDozeSensors.createDozeSensor( + mockSensor, + REASON_SENSOR_UDFPS_LONG_PRESS, + /* configured */ false); + mDozeSensors.addSensor(triggerSensor); + when(mSensorManager.requestTriggerSensor(eq(triggerSensor), eq(mockSensor))) + .thenReturn(true); + + // WHEN listening state is set to TRUE + mDozeSensors.setListening(true, true); + + // THEN mRegistered is still false b/c !mConfigured + assertFalse(triggerSensor.mConfigured); + assertFalse(triggerSensor.mRegistered); + + // WHEN enrollment changes to TRUE + when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true); + mAuthControllerCallback.onEnrollmentsChanged(); + + // THEN mConfigured = TRUE + assertTrue(triggerSensor.mConfigured); + + // THEN mRegistered = TRUE + assertTrue(triggerSensor.mRegistered); + } + + @Test + public void testGesturesAllInitiallyRespectSettings() { + DozeSensors dozeSensors = new DozeSensors(getContext(), mSensorManager, mDozeParameters, + mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog, + mProximitySensor, mFakeSettings, mAuthController, + mDevicePostureController); + + for (TriggerSensor sensor : dozeSensors.mTriggerSensors) { + assertFalse(sensor.mIgnoresSetting); + } + } private class TestableDozeSensors extends DozeSensors { TestableDozeSensors() { @@ -407,6 +463,22 @@ public class DozeSensorsTest extends SysuiTestCase { requiresTouchScreen); } + public TriggerSensor createDozeSensor( + Sensor sensor, + int pulseReason, + boolean configured + ) { + return new TriggerSensor(/* sensor */ sensor, + /* setting name */ "test_setting", + /* settingDefault */ true, + /* configured */ configured, + /* pulseReason*/ pulseReason, + /* reportsTouchCoordinate*/ false, + /* requiresTouchscreen */ false, + /* ignoresSetting */ false, + /* requiresTouchScreen */false); + } + /** * create a doze sensor that supports postures and is enabled */ @@ -422,6 +494,15 @@ public class DozeSensorsTest extends SysuiTestCase { /* requiresProx */false, posture); } + + public void addSensor(TriggerSensor sensor) { + TriggerSensor[] newArray = new TriggerSensor[mTriggerSensors.length + 1]; + for (int i = 0; i < mTriggerSensors.length; i++) { + newArray[i] = mTriggerSensors[i]; + } + newArray[mTriggerSensors.length] = sensor; + mTriggerSensors = newArray; + } } public static void setSensorType(Sensor sensor, int type, String strType) throws Exception { diff --git a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt new file mode 100644 index 000000000000..77c837b803af --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt @@ -0,0 +1,82 @@ +package com.android.systemui.fragments + +import android.app.Fragment +import android.os.Looper +import android.test.suitebuilder.annotation.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager +import com.android.systemui.qs.QSFragment +import com.android.systemui.util.mockito.mock +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test + +@SmallTest +class FragmentServiceTest : SysuiTestCase() { + private val fragmentCreator = TestFragmentCreator() + private val fragmentCreatorFactory = FragmentService.FragmentCreator.Factory { fragmentCreator } + + private lateinit var fragmentService: FragmentService + + @Before + fun setUp() { + if (Looper.myLooper() == null) { + Looper.prepare() + } + + fragmentService = FragmentService(fragmentCreatorFactory, mock(), DumpManager()) + } + + @Test + fun constructor_addsFragmentCreatorMethodsToMap() { + val map = fragmentService.injectionMap + assertThat(map).hasSize(2) + assertThat(map.keys).contains(QSFragment::class.java.name) + assertThat(map.keys).contains(TestFragmentInCreator::class.java.name) + } + + @Test + fun addFragmentInstantiationProvider_objectHasNoFragmentMethods_nothingAdded() { + fragmentService.addFragmentInstantiationProvider(Object()) + + assertThat(fragmentService.injectionMap).hasSize(2) + } + + @Test + fun addFragmentInstantiationProvider_objectHasFragmentMethods_methodsAdded() { + fragmentService.addFragmentInstantiationProvider( + @Suppress("unused") + object : Any() { + fun createTestFragment2() = TestFragment2() + fun createTestFragment3() = TestFragment3() + } + ) + + val map = fragmentService.injectionMap + assertThat(map).hasSize(4) + assertThat(map.keys).contains(TestFragment2::class.java.name) + assertThat(map.keys).contains(TestFragment3::class.java.name) + } + + @Test + fun addFragmentInstantiationProvider_objectFragmentMethodsAlreadyProvided_nothingAdded() { + fragmentService.addFragmentInstantiationProvider( + @Suppress("unused") + object : Any() { + fun createTestFragment() = TestFragmentInCreator() + } + ) + + assertThat(fragmentService.injectionMap).hasSize(2) + } + + class TestFragmentCreator : FragmentService.FragmentCreator { + override fun createQSFragment(): QSFragment = mock() + @Suppress("unused") + fun createTestFragment(): TestFragmentInCreator = TestFragmentInCreator() + } + + class TestFragmentInCreator : Fragment() + class TestFragment2 : Fragment() + class TestFragment3 : Fragment() +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt index 175ec87fd943..a6e567ea8b5a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt @@ -104,37 +104,54 @@ class MediaCarouselControllerTest : SysuiTestCase() { fun testPlayerOrdering() { // Test values: key, data, last active time val playingLocal = Triple("playing local", - DATA.copy(active = true, isPlaying = true, isLocalSession = true, resumption = false), + DATA.copy(active = true, isPlaying = true, + playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false), 4500L) - val playingRemote = Triple("playing remote", - DATA.copy(active = true, isPlaying = true, isLocalSession = false, resumption = false), + val playingCast = Triple("playing cast", + DATA.copy(active = true, isPlaying = true, + playbackLocation = MediaData.PLAYBACK_CAST_LOCAL, resumption = false), 5000L) val pausedLocal = Triple("paused local", - DATA.copy(active = true, isPlaying = false, isLocalSession = true, resumption = false), + DATA.copy(active = true, isPlaying = false, + playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false), 1000L) - val pausedRemote = Triple("paused remote", - DATA.copy(active = true, isPlaying = false, isLocalSession = false, resumption = false), + val pausedCast = Triple("paused cast", + DATA.copy(active = true, isPlaying = false, + playbackLocation = MediaData.PLAYBACK_CAST_LOCAL, resumption = false), 2000L) + val playingRcn = Triple("playing RCN", + DATA.copy(active = true, isPlaying = true, + playbackLocation = MediaData.PLAYBACK_CAST_REMOTE, resumption = false), + 5000L) + + val pausedRcn = Triple("paused RCN", + DATA.copy(active = true, isPlaying = false, + playbackLocation = MediaData.PLAYBACK_CAST_REMOTE, resumption = false), + 5000L) + val resume1 = Triple("resume 1", - DATA.copy(active = false, isPlaying = false, isLocalSession = true, resumption = true), + DATA.copy(active = false, isPlaying = false, + playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = true), 500L) val resume2 = Triple("resume 2", - DATA.copy(active = false, isPlaying = false, isLocalSession = true, resumption = true), + DATA.copy(active = false, isPlaying = false, + playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = true), 1000L) // Expected ordering for media players: // Actively playing local sessions - // Actively playing remote sessions - // Paused sessions, by last active + // Actively playing cast sessions + // Paused local and cast sessions, by last active + // RCNs // Resume controls, by last active - val expected = listOf(playingLocal, playingRemote, pausedRemote, pausedLocal, resume2, - resume1) + val expected = listOf(playingLocal, playingCast, pausedCast, pausedLocal, playingRcn, + pausedRcn, resume2, resume1) expected.forEach { clock.setCurrentTimeMillis(it.third) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java index 66b64708ad24..f870da3e68d9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java @@ -74,8 +74,8 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { mManager.addListener(mListener); mMediaData = new MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, - new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, true, null, true, - false, KEY, false, false, false, 0L); + new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, true, null, + MediaData.PLAYBACK_LOCAL, false, KEY, false, false, false, 0L); mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt index 2b2fc513d03c..f44cc38c78c0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -1,5 +1,6 @@ package com.android.systemui.media +import android.app.Notification import android.app.Notification.MediaStyle import android.app.PendingIntent import android.app.smartspace.SmartspaceAction @@ -229,6 +230,30 @@ class MediaDataManagerTest : SysuiTestCase() { } @Test + fun testOnNotificationAdded_isRcn_markedRemote() { + val bundle = Bundle().apply { + putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, "Remote Cast Notification") + } + val rcn = SbnBuilder().run { + setPkg("com.android.systemui") // System package + modifyNotification(context).also { + it.setSmallIcon(android.R.drawable.ic_media_pause) + it.setStyle(MediaStyle().apply { setMediaSession(session.sessionToken) }) + it.addExtras(bundle) + } + build() + } + + mediaDataManager.onNotificationAdded(KEY, rcn) + assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) + assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) + verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), + eq(false)) + assertThat(mediaDataCaptor.value!!.playbackLocation).isEqualTo( + MediaData.PLAYBACK_CAST_REMOTE) + } + + @Test fun testOnNotificationRemoved_callsListener() { mediaDataManager.onNotificationAdded(KEY, mediaNotification) mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java)) @@ -306,7 +331,8 @@ class MediaDataManagerTest : SysuiTestCase() { verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), eq(false)) val data = mediaDataCaptor.value - val dataRemoteWithResume = data.copy(resumeAction = Runnable {}, isLocalSession = false) + val dataRemoteWithResume = data.copy(resumeAction = Runnable {}, + playbackLocation = MediaData.PLAYBACK_CAST_LOCAL) mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume) // WHEN the notification is removed diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt index 8dc9eff97ab9..421f9bee78fa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt @@ -42,7 +42,8 @@ public class MediaPlayerDataTest : SysuiTestCase() { val mockito = MockitoJUnit.rule() companion object { - val LOCAL = true + val LOCAL = MediaData.PLAYBACK_LOCAL + val REMOTE = MediaData.PLAYBACK_CAST_LOCAL val RESUMPTION = true val PLAYING = true val UNDETERMINED = null @@ -58,7 +59,7 @@ public class MediaPlayerDataTest : SysuiTestCase() { val dataIsPlaying = createMediaData("app1", PLAYING, LOCAL, !RESUMPTION) val playerIsRemote = mock(MediaControlPanel::class.java) - val dataIsRemote = createMediaData("app2", PLAYING, !LOCAL, !RESUMPTION) + val dataIsRemote = createMediaData("app2", PLAYING, REMOTE, !RESUMPTION) MediaPlayerData.addMediaPlayer("2", dataIsRemote, playerIsRemote, systemClock) MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying, systemClock) @@ -100,13 +101,13 @@ public class MediaPlayerDataTest : SysuiTestCase() { val dataIsPlaying = createMediaData("app1", PLAYING, LOCAL, !RESUMPTION) val playerIsPlayingAndRemote = mock(MediaControlPanel::class.java) - val dataIsPlayingAndRemote = createMediaData("app2", PLAYING, !LOCAL, !RESUMPTION) + val dataIsPlayingAndRemote = createMediaData("app2", PLAYING, REMOTE, !RESUMPTION) val playerIsStoppedAndLocal = mock(MediaControlPanel::class.java) val dataIsStoppedAndLocal = createMediaData("app3", !PLAYING, LOCAL, !RESUMPTION) val playerIsStoppedAndRemote = mock(MediaControlPanel::class.java) - val dataIsStoppedAndRemote = createMediaData("app4", !PLAYING, !LOCAL, !RESUMPTION) + val dataIsStoppedAndRemote = createMediaData("app4", !PLAYING, REMOTE, !RESUMPTION) val playerCanResume = mock(MediaControlPanel::class.java) val dataCanResume = createMediaData("app5", !PLAYING, LOCAL, RESUMPTION) @@ -127,8 +128,8 @@ public class MediaPlayerDataTest : SysuiTestCase() { val players = MediaPlayerData.players() assertThat(players).hasSize(6) assertThat(players).containsExactly(playerIsPlaying, playerIsPlayingAndRemote, - playerIsStoppedAndRemote, playerIsStoppedAndLocal, playerCanResume, - playerUndetermined).inOrder() + playerIsStoppedAndRemote, playerIsStoppedAndLocal, playerUndetermined, + playerCanResume).inOrder() } @Test @@ -160,9 +161,10 @@ public class MediaPlayerDataTest : SysuiTestCase() { private fun createMediaData( app: String, isPlaying: Boolean?, - isLocalSession: Boolean, + location: Int, resumption: Boolean ) = - MediaData(0, false, 0, app, null, null, null, null, emptyList(), emptyList<Int>(), "", - null, null, null, true, null, isLocalSession, resumption, null, false, isPlaying) + MediaData(0, false, 0, app, null, null, null, null, emptyList(), emptyList<Int>(), + "package:" + app, null, null, null, true, null, location, resumption, "key:" + app, + false, isPlaying) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt index a17a03daba5b..30ee2e4d3431 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt @@ -211,10 +211,20 @@ class MediaResumeListenerTest : SysuiTestCase() { } @Test - fun testOnLoad_remotePlayback_doesNotCheck() { - // When media data is loaded that has not been checked yet, and is not local - val dataRemote = data.copy(isLocalSession = false) - resumeListener.onMediaDataLoaded(KEY, null, dataRemote) + fun testOnLoad_localCast_doesNotCheck() { + // When media data is loaded that has not been checked yet, and is a local cast + val dataCast = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_LOCAL) + resumeListener.onMediaDataLoaded(KEY, null, dataCast) + + // Then we do not take action + verify(mediaDataManager, never()).setResumeAction(any(), any()) + } + + @Test + fun testOnload_remoteCast_doesNotCheck() { + // When media data is loaded that has not been checked yet, and is a remote cast + val dataRcn = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_REMOTE) + resumeListener.onMediaDataLoaded(KEY, null, dataRcn) // Then we do not take action verify(mediaDataManager, never()).setResumeAction(any(), any()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java index f7e60caa2624..09ec4ca0e1df 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java @@ -469,7 +469,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(entry.getSbn()).thenReturn(sbn); when(sbn.getNotification()).thenReturn(notification); when(sbn.getPackageName()).thenReturn(TEST_PACKAGE_NAME); - when(notification.hasMediaSession()).thenReturn(true); + when(notification.isMediaNotification()).thenReturn(true); when(notification.getLargeIcon()).thenReturn(null); assertThat(mMediaOutputController.getNotificationIcon()).isNull(); @@ -489,7 +489,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(entry.getSbn()).thenReturn(sbn); when(sbn.getNotification()).thenReturn(notification); when(sbn.getPackageName()).thenReturn(TEST_PACKAGE_NAME); - when(notification.hasMediaSession()).thenReturn(true); + when(notification.isMediaNotification()).thenReturn(true); when(notification.getLargeIcon()).thenReturn(icon); assertThat(mMediaOutputController.getNotificationIcon() instanceof IconCompat).isTrue(); @@ -509,7 +509,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { when(entry.getSbn()).thenReturn(sbn); when(sbn.getNotification()).thenReturn(notification); when(sbn.getPackageName()).thenReturn(TEST_PACKAGE_NAME); - when(notification.hasMediaSession()).thenReturn(false); + when(notification.isMediaNotification()).thenReturn(false); when(notification.getLargeIcon()).thenReturn(icon); assertThat(mMediaOutputController.getNotificationIcon()).isNull(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java new file mode 100644 index 000000000000..734faec4ec74 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.navigationbar; + +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.ComponentName; +import android.view.accessibility.AccessibilityManager; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.accessibility.AccessibilityButtonModeObserver; +import com.android.systemui.assist.AssistManager; +import com.android.systemui.dump.DumpManager; +import com.android.systemui.recents.OverviewProxyService; +import com.android.systemui.settings.UserTracker; +import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import dagger.Lazy; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class NavBarHelperTest extends SysuiTestCase { + + @Mock + AccessibilityManager mAccessibilityManager; + @Mock + AccessibilityManagerWrapper mAccessibilityManagerWrapper; + @Mock + AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; + @Mock + OverviewProxyService mOverviewProxyService; + @Mock + Lazy<AssistManager> mAssistManagerLazy; + @Mock + AssistManager mAssistManager; + @Mock + NavigationModeController mNavigationModeController; + @Mock + UserTracker mUserTracker; + @Mock + ComponentName mAssistantComponent; + @Mock + DumpManager mDumpManager; + @Mock + NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater; + + private NavBarHelper mNavBarHelper; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + when(mAssistManagerLazy.get()).thenReturn(mAssistManager); + when(mAssistManager.getAssistInfoForUser(anyInt())).thenReturn(mAssistantComponent); + when(mUserTracker.getUserId()).thenReturn(1); + + mNavBarHelper = new NavBarHelper(mAccessibilityManager, + mAccessibilityManagerWrapper, mAccessibilityButtonModeObserver, + mOverviewProxyService, mAssistManagerLazy, mNavigationModeController, + mUserTracker, mDumpManager); + + } + + @Test + public void registerListenersInCtor() { + verify(mAccessibilityButtonModeObserver, times(1)).addListener(mNavBarHelper); + verify(mNavigationModeController, times(1)).addListener(mNavBarHelper); + verify(mOverviewProxyService, times(1)).addCallback(mNavBarHelper); + } + + @Test + public void registerAssistantContentObserver() { + mNavBarHelper.init(mContext); + verify(mAssistManager, times(1)).getAssistInfoForUser(anyInt()); + } + + @Test + public void callbacksFiredWhenRegistering() { + mNavBarHelper.init(mContext); + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + verify(mNavbarTaskbarStateUpdater, times(1)) + .updateAccessibilityServicesState(); + verify(mNavbarTaskbarStateUpdater, times(1)) + .updateAssistantAvailable(anyBoolean()); + } + + @Test + public void assistantCallbacksFiredAfterConnecting() { + mNavBarHelper.init(mContext); + // 1st set of callbacks get called when registering + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + + mNavBarHelper.onConnectionChanged(false); + // assert no more callbacks fired + verify(mNavbarTaskbarStateUpdater, times(1)) + .updateAccessibilityServicesState(); + verify(mNavbarTaskbarStateUpdater, times(1)) + .updateAssistantAvailable(anyBoolean()); + + mNavBarHelper.onConnectionChanged(true); + // assert no more callbacks fired + verify(mNavbarTaskbarStateUpdater, times(1)) + .updateAccessibilityServicesState(); + verify(mNavbarTaskbarStateUpdater, times(2)) + .updateAssistantAvailable(anyBoolean()); + } + + @Test + public void a11yCallbacksFiredAfterModeChange() { + mNavBarHelper.init(mContext); + // 1st set of callbacks get called when registering + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + + mNavBarHelper.onAccessibilityButtonModeChanged(0); + verify(mNavbarTaskbarStateUpdater, times(2)) + .updateAccessibilityServicesState(); + verify(mNavbarTaskbarStateUpdater, times(1)) + .updateAssistantAvailable(anyBoolean()); + } + + @Test + public void assistantCallbacksFiredAfterNavModeChange() { + mNavBarHelper.init(mContext); + // 1st set of callbacks get called when registering + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + + mNavBarHelper.onNavigationModeChanged(0); + verify(mNavbarTaskbarStateUpdater, times(1)) + .updateAccessibilityServicesState(); + verify(mNavbarTaskbarStateUpdater, times(2)) + .updateAssistantAvailable(anyBoolean()); + } + + @Test + public void removeListenerNoCallbacksFired() { + mNavBarHelper.init(mContext); + // 1st set of callbacks get called when registering + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + + // Remove listener + mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + + // Would have fired 2nd callback if not removed + mNavBarHelper.onAccessibilityButtonModeChanged(0); + + // assert no more callbacks fired + verify(mNavbarTaskbarStateUpdater, times(1)) + .updateAccessibilityServicesState(); + verify(mNavbarTaskbarStateUpdater, times(1)) + .updateAssistantAvailable(anyBoolean()); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java index 4fc329ffc7af..31d88303485c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java @@ -82,7 +82,7 @@ public class NavigationBarControllerTest extends SysuiTestCase { mCommandQueue, Dependency.get(Dependency.MAIN_HANDLER), mock(ConfigurationController.class), - mock(NavigationBarA11yHelper.class), + mock(NavBarHelper.class), mock(TaskbarDelegate.class), mNavigationBarFactory, mock(DumpManager.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java index 50b717181dc2..e038b6e6dfb3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -136,7 +136,7 @@ public class NavigationBarTest extends SysuiTestCase { @Mock EdgeBackGestureHandler mEdgeBackGestureHandler; @Mock - NavigationBarA11yHelper mNavigationBarA11yHelper; + NavBarHelper mNavBarHelper; @Mock private LightBarController mLightBarController; @Mock @@ -227,6 +227,7 @@ public class NavigationBarTest extends SysuiTestCase { new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_SYSTEMUI) .setLong(HOME_BUTTON_LONG_PRESS_DURATION_MS, 100) .build()); + when(mNavBarHelper.getLongPressHomeEnabled()).thenReturn(true); mNavigationBar.onViewAttachedToWindow(mNavigationBar.createView(null)); mNavigationBar.onHomeTouch(mNavigationBar.getView(), MotionEvent.obtain( @@ -330,14 +331,14 @@ public class NavigationBarTest extends SysuiTestCase { public void testA11yEventAfterDetach() { View v = mNavigationBar.createView(null); mNavigationBar.onViewAttachedToWindow(v); - verify(mNavigationBarA11yHelper).registerA11yEventListener(any( - NavigationBarA11yHelper.NavA11yEventListener.class)); + verify(mNavBarHelper).registerNavTaskStateUpdater(any( + NavBarHelper.NavbarTaskbarStateUpdater.class)); mNavigationBar.onViewDetachedFromWindow(v); - verify(mNavigationBarA11yHelper).removeA11yEventListener(any( - NavigationBarA11yHelper.NavA11yEventListener.class)); + verify(mNavBarHelper).removeNavTaskStateUpdater(any( + NavBarHelper.NavbarTaskbarStateUpdater.class)); // Should be safe even though the internal view is now null. - mNavigationBar.updateAccessibilityServicesState(); + mNavigationBar.updateAcessibilityStateFlags(); } private NavigationBar createNavBar(Context context) { @@ -367,7 +368,7 @@ public class NavigationBarTest extends SysuiTestCase { mHandler, mock(NavigationBarOverlayController.class), mUiEventLogger, - mNavigationBarA11yHelper, + mNavBarHelper, mock(UserTracker.class), mLightBarController, mLightBarcontrollerFactory, diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt index f41d7b127a9e..e2a0626d9849 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt @@ -1,7 +1,6 @@ package com.android.systemui.qs import android.testing.AndroidTestingRunner -import android.view.ViewGroup import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import org.junit.Before @@ -9,7 +8,6 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock -import org.mockito.Mockito.`when` import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit @@ -18,13 +16,9 @@ import org.mockito.junit.MockitoJUnit @SmallTest class QSSquishinessControllerTest : SysuiTestCase() { - @Mock private lateinit var qqsFooterActionsView: FooterActionsView - @Mock private lateinit var qqsFooterActionsViewLP: ViewGroup.MarginLayoutParams @Mock private lateinit var qsAnimator: QSAnimator @Mock private lateinit var qsPanelController: QSPanelController @Mock private lateinit var quickQsPanelController: QuickQSPanelController - @Mock private lateinit var tileLayout: TileLayout - @Mock private lateinit var pagedTileLayout: PagedTileLayout @JvmField @Rule val mockitoRule = MockitoJUnit.rule() @@ -32,11 +26,8 @@ class QSSquishinessControllerTest : SysuiTestCase() { @Before fun setup() { - qsSquishinessController = QSSquishinessController(qqsFooterActionsView, qsAnimator, + qsSquishinessController = QSSquishinessController(qsAnimator, qsPanelController, quickQsPanelController) - `when`(quickQsPanelController.tileLayout).thenReturn(tileLayout) - `when`(qsPanelController.tileLayout).thenReturn(pagedTileLayout) - `when`(qqsFooterActionsView.layoutParams).thenReturn(qqsFooterActionsViewLP) } @Test @@ -51,7 +42,7 @@ class QSSquishinessControllerTest : SysuiTestCase() { @Test fun setSquishiness_updatesTiles() { qsSquishinessController.squishiness = 0.5f - verify(tileLayout).setSquishinessFraction(0.5f) - verify(pagedTileLayout).setSquishinessFraction(0.5f) + verify(qsPanelController).setSquishinessFraction(0.5f) + verify(quickQsPanelController).setSquishinessFraction(0.5f) } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/SecureSettingTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/SettingObserverTest.kt index 6af8402d8aff..4be689065d3f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/SecureSettingTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/SettingObserverTest.kt @@ -35,7 +35,7 @@ private typealias Callback = (Int, Boolean) -> Unit @SmallTest @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper -class SecureSettingTest : SysuiTestCase() { +class SettingObserverTest : SysuiTestCase() { companion object { private const val TEST_SETTING = "setting" @@ -46,7 +46,7 @@ class SecureSettingTest : SysuiTestCase() { } private lateinit var testableLooper: TestableLooper - private lateinit var setting: SecureSetting + private lateinit var setting: SettingObserver private lateinit var secureSettings: SecureSettings private lateinit var callback: Callback @@ -56,7 +56,7 @@ class SecureSettingTest : SysuiTestCase() { testableLooper = TestableLooper.get(this) secureSettings = FakeSettings() - setting = object : SecureSetting( + setting = object : SettingObserver( secureSettings, Handler(testableLooper.looper), TEST_SETTING, diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java new file mode 100644 index 000000000000..bf682a8d4e0a --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Intent; +import android.os.Handler; +import android.provider.Settings; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEventLogger; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.classifier.FalsingManagerFake; +import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.qs.QSTileHost; +import com.android.systemui.qs.logging.QSLogger; +import com.android.systemui.settings.UserTracker; +import com.android.systemui.util.settings.FakeSettings; +import com.android.systemui.util.settings.SecureSettings; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +@SmallTest +public class ColorInversionTileTest extends SysuiTestCase { + + @Mock + private QSTileHost mHost; + @Mock + private MetricsLogger mMetricsLogger; + @Mock + private StatusBarStateController mStatusBarStateController; + @Mock + private ActivityStarter mActivityStarter; + @Mock + private QSLogger mQSLogger; + @Mock + private UiEventLogger mUiEventLogger; + @Mock + private UserTracker mUserTracker; + + private TestableLooper mTestableLooper; + private SecureSettings mSecureSettings; + private ColorInversionTile mTile; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mSecureSettings = new FakeSettings(); + mTestableLooper = TestableLooper.get(this); + + when(mHost.getContext()).thenReturn(mContext); + when(mHost.getUiEventLogger()).thenReturn(mUiEventLogger); + + mTile = new ColorInversionTile( + mHost, + mTestableLooper.getLooper(), + new Handler(mTestableLooper.getLooper()), + new FalsingManagerFake(), + mMetricsLogger, + mStatusBarStateController, + mActivityStarter, + mQSLogger, + mUserTracker, + mSecureSettings + ); + + mTile.initialize(); + mTestableLooper.processAllMessages(); + } + + @Test + public void longClick_expectedAction() { + final ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class); + + mTile.longClick(/* view= */ null); + mTestableLooper.processAllMessages(); + + verify(mActivityStarter).postStartActivityDismissingKeyguard(IntentCaptor.capture(), + anyInt(), any()); + assertThat(IntentCaptor.getValue().getAction()).isEqualTo( + Settings.ACTION_COLOR_INVERSION_SETTINGS); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinatorTest.java index 01e4cce0cc30..f4452bc248b1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinatorTest.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.test.suitebuilder.annotation.SmallTest; @@ -29,6 +30,8 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Test; @@ -39,6 +42,8 @@ import org.mockito.MockitoAnnotations; @SmallTest public class CommunalCoordinatorTest extends SysuiTestCase { + private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); + @Mock CommunalStateController mCommunalStateController; @Mock @@ -57,7 +62,7 @@ public class CommunalCoordinatorTest extends SysuiTestCase { @Before public void setup() { MockitoAnnotations.initMocks(this); - mCoordinator = new CommunalCoordinator(mNotificationEntryManager, + mCoordinator = new CommunalCoordinator(mExecutor, mNotificationEntryManager, mNotificationLockscreenUserManager, mCommunalStateController); } @@ -84,6 +89,12 @@ public class CommunalCoordinatorTest extends SysuiTestCase { // Verify that notifications are filtered out when communal is showing and that the filter // pipeline is notified. stateCallback.onCommunalViewShowingChanged(); + // Make sure callback depends on executor to run. + verify(mFilterListener, never()).onPluggableInvalidated(any()); + verify(mNotificationEntryManager, never()).updateNotifications(any()); + + mExecutor.runAllReady(); + verify(mFilterListener).onPluggableInvalidated(any()); verify(mNotificationEntryManager).updateNotifications(any()); assert (filter.shouldFilterOut(mNotificationEntry, 0)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java index 0faf5d478116..a0e91fc77148 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java @@ -438,8 +438,8 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { assertEquals("returns false when view is null", false, NotificationSwipeHelper.isTouchInView(mEvent, null)); - doReturn(5f).when(mEvent).getX(); - doReturn(10f).when(mEvent).getY(); + doReturn(5f).when(mEvent).getRawX(); + doReturn(10f).when(mEvent).getRawY(); doReturn(20).when(mView).getWidth(); doReturn(20).when(mView).getHeight(); @@ -455,7 +455,7 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { assertTrue("Touch is within the view", mSwipeHelper.isTouchInView(mEvent, mView)); - doReturn(50f).when(mEvent).getX(); + doReturn(50f).when(mEvent).getRawX(); assertFalse("Touch is not within the view", mSwipeHelper.isTouchInView(mEvent, mView)); @@ -466,8 +466,8 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { assertEquals("returns false when view is null", false, NotificationSwipeHelper.isTouchInView(mEvent, null)); - doReturn(5f).when(mEvent).getX(); - doReturn(10f).when(mEvent).getY(); + doReturn(5f).when(mEvent).getRawX(); + doReturn(10f).when(mEvent).getRawY(); doReturn(20).when(mNotificationRow).getWidth(); doReturn(20).when(mNotificationRow).getActualHeight(); @@ -483,7 +483,7 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { assertTrue("Touch is within the view", mSwipeHelper.isTouchInView(mEvent, mNotificationRow)); - doReturn(50f).when(mEvent).getX(); + doReturn(50f).when(mEvent).getRawX(); assertFalse("Touch is not within the view", mSwipeHelper.isTouchInView(mEvent, mNotificationRow)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java index 3f5d220957cd..22899367afce 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java @@ -51,7 +51,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.qs.AutoAddTracker; import com.android.systemui.qs.QSTileHost; import com.android.systemui.qs.ReduceBrightColorsController; -import com.android.systemui.qs.SecureSetting; +import com.android.systemui.qs.SettingObserver; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.CastController.CastDevice; import com.android.systemui.statusbar.policy.DataSaverController; @@ -249,7 +249,7 @@ public class AutoTileManagerTest extends SysuiTestCase { verify(mWalletController, times(2)).getWalletPosition(); - SecureSetting setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING); + SettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING); assertEquals(USER + 1, setting.getCurrentUser()); assertTrue(setting.isListening()); } @@ -299,7 +299,7 @@ public class AutoTileManagerTest extends SysuiTestCase { verify(mWalletController, times(2)).getWalletPosition(); - SecureSetting setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING); + SettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING); assertEquals(USER + 1, setting.getCurrentUser()); assertFalse(setting.isListening()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java index 25fd80133897..07debe68e224 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java @@ -45,6 +45,7 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -101,6 +102,8 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { private WakefulnessLifecycle mWakefulnessLifecycle; @Mock private ScreenLifecycle mScreenLifecycle; + @Mock + private StatusBarStateController mStatusBarStateController; private BiometricUnlockController mBiometricUnlockController; @Before @@ -123,7 +126,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { mUpdateMonitor, res.getResources(), mKeyguardBypassController, mDozeParameters, mMetricsLogger, mDumpManager, mPowerManager, mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle, - mAuthController); + mAuthController, mStatusBarStateController); mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager); mBiometricUnlockController.setBiometricModeListener(mBiometricModeListener); } @@ -378,6 +381,23 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { } @Test + public void onUdfpsConsecutivelyFailedThreeTimes_showBouncer() { + // GIVEN UDFPS is supported + when(mUpdateMonitor.isUdfpsSupported()).thenReturn(true); + + // WHEN udfps fails twice - then don't show the bouncer + mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT); + mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT); + verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean()); + + // WHEN udfps fails the third time + mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT); + + // THEN show the bouncer + verify(mStatusBarKeyguardViewManager).showBouncer(true); + } + + @Test public void onFinishedGoingToSleep_authenticatesWhenPending() { when(mUpdateMonitor.isGoingToSleep()).thenReturn(true); mBiometricUnlockController.onFinishedGoingToSleep(-1); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java index 81ddc670745b..270c64ddfa7a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java @@ -358,6 +358,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { private NotificationsQuickSettingsContainer mNotificationContainerParent; private List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners; private FalsingManagerFake mFalsingManager = new FalsingManagerFake(); + private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); @Before public void setup() { @@ -511,7 +512,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mQuickAccessWalletController, mQrCodeScannerController, mRecordingController, - new FakeExecutor(new FakeSystemClock()), + mExecutor, mSecureSettings, mSplitShadeHeaderController, mUnlockedScreenOffAnimationController, @@ -936,6 +937,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { ArgumentCaptor.forClass(WeakReference.class); monitorCallback.getValue().onSourceAvailable(new WeakReference<>(mCommunalSource)); + mExecutor.runAllReady(); verify(mCommunalHostViewController).show(sourceCapture.capture()); assertThat(sourceCapture.getValue().get()).isEqualTo(mCommunalSource); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index 6f174cbe0021..c5bdfed6082b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -374,6 +374,21 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { } @Test + public void testHideAltAuth_onShowBouncer() { + // GIVEN alt auth is showing + mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor); + when(mBouncer.isShowing()).thenReturn(false); + when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true); + reset(mAlternateAuthInterceptor); + + // WHEN showBouncer is called + mStatusBarKeyguardViewManager.showBouncer(true); + + // THEN alt bouncer should be hidden + verify(mAlternateAuthInterceptor).hideAlternateAuthBouncer(); + } + + @Test public void testUpdateResources_delegatesToBouncer() { mStatusBarKeyguardViewManager.updateResources(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 851bd343923d..1df576e3bd58 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -86,6 +86,7 @@ import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; @@ -135,7 +136,6 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger; -import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.BatteryController; @@ -210,6 +210,7 @@ public class StatusBarTest extends SysuiTestCase { @Mock private AmbientDisplayConfiguration mAmbientDisplayConfiguration; @Mock private NotificationLogger.ExpansionStateLogger mExpansionStateLogger; @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; + @Mock private StatusBarSignalPolicy mStatusBarSignalPolicy; @Mock private NotificationShadeWindowView mNotificationShadeWindowView; @Mock private BroadcastDispatcher mBroadcastDispatcher; @Mock private AssistManager mAssistManager; @@ -246,8 +247,6 @@ public class StatusBarTest extends SysuiTestCase { @Mock private CollapsedStatusBarFragmentLogger mCollapsedStatusBarFragmentLogger; @Mock private StatusBarComponent.Factory mStatusBarComponentFactory; @Mock private StatusBarComponent mStatusBarComponent; - @Mock private StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory; - @Mock private StatusBarFragmentComponent mStatusBarFragmentComponent; @Mock private PluginManager mPluginManager; @Mock private LegacySplitScreen mLegacySplitScreen; @Mock private LightsOutNotifController mLightsOutNotifController; @@ -362,8 +361,6 @@ public class StatusBarTest extends SysuiTestCase { when(mBiometricUnlockControllerLazy.get()).thenReturn(mBiometricUnlockController); when(mStatusBarComponentFactory.create()).thenReturn(mStatusBarComponent); - when(mStatusBarFragmentComponentFactory.create(any())) - .thenReturn(mStatusBarFragmentComponent); when(mStatusBarComponent.getNotificationShadeWindowViewController()).thenReturn( mNotificationShadeWindowViewController); @@ -378,10 +375,12 @@ public class StatusBarTest extends SysuiTestCase { mStatusBar = new StatusBar( mContext, mNotificationsController, + mock(FragmentService.class), mLightBarController, mAutoHideController, mStatusBarWindowController, mKeyguardUpdateMonitor, + mStatusBarSignalPolicy, mPulseExpansionHandler, mNotificationWakeUpCoordinator, mKeyguardBypassController, @@ -433,7 +432,6 @@ public class StatusBarTest extends SysuiTestCase { mCommandQueue, mCollapsedStatusBarFragmentLogger, mStatusBarComponentFactory, - mStatusBarFragmentComponentFactory, mPluginManager, Optional.of(mLegacySplitScreen), mLightsOutNotifController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java index 0ee4e7a2c585..609d69ce1204 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java @@ -294,6 +294,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { new StatusBarHideIconsForBouncerManager( mCommandQueue, new FakeExecutor(new FakeSystemClock()), new DumpManager()), mKeyguardStateController, + mock(NotificationPanelViewController.class), mNetworkController, mStatusBarStateController, () -> Optional.of(mStatusBar), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt index a39d580a3802..de2012af8599 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt @@ -31,6 +31,7 @@ import android.os.UserHandle import android.os.UserManager import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import android.view.ThreadedRenderer import androidx.test.filters.SmallTest import com.android.internal.jank.InteractionJankMonitor import com.android.internal.logging.testing.UiEventLoggerFake @@ -63,6 +64,8 @@ import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.any import org.mockito.Mockito.anyString +import org.mockito.Mockito.doNothing +import org.mockito.Mockito.doReturn import org.mockito.Mockito.mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -90,6 +93,7 @@ class UserSwitcherControllerTest : SysuiTestCase() { @Mock private lateinit var latencyTracker: LatencyTracker @Mock private lateinit var dialogShower: UserSwitchDialogController.DialogShower @Mock private lateinit var notificationShadeWindowView: NotificationShadeWindowView + @Mock private lateinit var threadedRenderer: ThreadedRenderer private lateinit var testableLooper: TestableLooper private lateinit var uiBgExecutor: FakeExecutor private lateinit var uiEventLogger: UiEventLoggerFake @@ -146,6 +150,16 @@ class UserSwitcherControllerTest : SysuiTestCase() { dumpManager) userSwitcherController.mPauseRefreshUsers = true + // Since userSwitcherController involves InteractionJankMonitor. + // Let's fulfill the dependencies. + val mockedContext = mock(Context::class.java) + doReturn(mockedContext).`when`(notificationShadeWindowView).context + doReturn(true).`when`(notificationShadeWindowView).isAttachedToWindow + doNothing().`when`(threadedRenderer).addObserver(any()) + doNothing().`when`(threadedRenderer).removeObserver(any()) + doReturn(threadedRenderer).`when`(notificationShadeWindowView).threadedRenderer + userSwitcherController.init(notificationShadeWindowView) + picture = UserIcons.convertToBitmap(context.getDrawable(R.drawable.ic_avatar_user)) userSwitcherController.init(notificationShadeWindowView) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java index 336f2b16aeb7..3fe1a9f6ed97 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java @@ -36,6 +36,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.policy.ZenModeController.Callback; +import com.android.systemui.util.settings.FakeSettings; import org.junit.Before; import org.junit.Test; @@ -70,7 +71,8 @@ public class ZenModeControllerImplTest extends SysuiTestCase { mContext, Handler.createAsync(Looper.myLooper()), mBroadcastDispatcher, - mDumpManager); + mDumpManager, + new FakeSettings()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java index 8480702c57c0..ae7afcef57a6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java @@ -41,6 +41,7 @@ import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.onehanded.OneHandedEventCallback; import com.android.wm.shell.onehanded.OneHandedTransitionCallback; import com.android.wm.shell.pip.Pip; +import com.android.wm.shell.sizecompatui.SizeCompatUI; import com.android.wm.shell.splitscreen.SplitScreen; import org.junit.Before; @@ -76,6 +77,7 @@ public class WMShellTest extends SysuiTestCase { @Mock WakefulnessLifecycle mWakefulnessLifecycle; @Mock ProtoTracer mProtoTracer; @Mock ShellCommandHandler mShellCommandHandler; + @Mock SizeCompatUI mSizeCompatUI; @Mock ShellExecutor mSysUiMainExecutor; @Before @@ -84,10 +86,10 @@ public class WMShellTest extends SysuiTestCase { mWMShell = new WMShell(mContext, Optional.of(mPip), Optional.of(mLegacySplitScreen), Optional.of(mSplitScreen), Optional.of(mOneHanded), Optional.of(mHideDisplayCutout), - Optional.of(mShellCommandHandler), mCommandQueue, mConfigurationController, - mKeyguardUpdateMonitor, mNavigationModeController, - mScreenLifecycle, mSysUiState, mProtoTracer, mWakefulnessLifecycle, - mSysUiMainExecutor); + Optional.of(mShellCommandHandler), Optional.of(mSizeCompatUI), + mCommandQueue, mConfigurationController, mKeyguardUpdateMonitor, + mNavigationModeController, mScreenLifecycle, mSysUiState, mProtoTracer, + mWakefulnessLifecycle, mSysUiMainExecutor); } @Test @@ -129,4 +131,11 @@ public class WMShellTest extends SysuiTestCase { verify(mConfigurationController).addCallback( any(ConfigurationController.ConfigurationListener.class)); } + + @Test + public void initSizeCompatUI_registersCallbacks() { + mWMShell.initSizeCompatUi(mSizeCompatUI); + + verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class)); + } } diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index c9608a55170e..3e0208411c21 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * 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. @@ -20,24 +20,27 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.ContentObserver; -import android.net.NetworkStack; import android.net.Uri; import android.net.nsd.INsdManager; +import android.net.nsd.INsdManagerCallback; +import android.net.nsd.INsdServiceConnector; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; import android.os.Handler; import android.os.HandlerThread; +import android.os.IBinder; import android.os.Message; -import android.os.Messenger; +import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.util.Base64; +import android.util.Log; +import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.AsyncChannel; import com.android.internal.util.DumpUtils; import com.android.internal.util.State; import com.android.internal.util.StateMachine; @@ -72,12 +75,11 @@ public class NsdService extends INsdManager.Stub { /** * Clients receiving asynchronous messages */ - private final HashMap<Messenger, ClientInfo> mClients = new HashMap<>(); + private final HashMap<NsdServiceConnector, ClientInfo> mClients = new HashMap<>(); /* A map from unique id to client info */ private final SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<>(); - private final AsyncChannel mReplyChannel = new AsyncChannel(); private final long mCleanupDelayMs; private static final int INVALID_ID = 0; @@ -149,65 +151,66 @@ public class NsdService extends INsdManager.Stub { class DefaultState extends State { @Override public boolean processMessage(Message msg) { - ClientInfo cInfo = null; + final ClientInfo cInfo; + final int clientId = msg.arg2; switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { - AsyncChannel c = (AsyncChannel) msg.obj; - if (DBG) Slog.d(TAG, "New client listening to asynchronous messages"); - c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED); - cInfo = new ClientInfo(c, msg.replyTo); - mClients.put(msg.replyTo, cInfo); - } else { - Slog.e(TAG, "Client connection failure, error=" + msg.arg1); + case NsdManager.REGISTER_CLIENT: + final Pair<NsdServiceConnector, INsdManagerCallback> arg = + (Pair<NsdServiceConnector, INsdManagerCallback>) msg.obj; + final INsdManagerCallback cb = arg.second; + try { + cb.asBinder().linkToDeath(arg.first, 0); + cInfo = new ClientInfo(cb); + mClients.put(arg.first, cInfo); + } catch (RemoteException e) { + Log.w(TAG, "Client " + clientId + " has already died"); } break; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - switch (msg.arg1) { - case AsyncChannel.STATUS_SEND_UNSUCCESSFUL: - Slog.e(TAG, "Send failed, client connection lost"); - break; - case AsyncChannel.STATUS_REMOTE_DISCONNECTION: - if (DBG) Slog.d(TAG, "Client disconnected"); - break; - default: - if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); - break; - } - - cInfo = mClients.get(msg.replyTo); + case NsdManager.UNREGISTER_CLIENT: + final NsdServiceConnector connector = (NsdServiceConnector) msg.obj; + cInfo = mClients.remove(connector); if (cInfo != null) { cInfo.expungeAllRequests(); - mClients.remove(msg.replyTo); if (cInfo.isLegacy()) { mLegacyClientCount -= 1; } } maybeScheduleStop(); break; - case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: - AsyncChannel ac = new AsyncChannel(); - ac.connect(mContext, getHandler(), msg.replyTo); - break; case NsdManager.DISCOVER_SERVICES: - replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + cInfo = getClientInfoForReply(msg); + if (cInfo != null) { + cInfo.onDiscoverServicesFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + } break; case NsdManager.STOP_DISCOVERY: - replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + cInfo = getClientInfoForReply(msg); + if (cInfo != null) { + cInfo.onStopDiscoveryFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + } break; case NsdManager.REGISTER_SERVICE: - replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + cInfo = getClientInfoForReply(msg); + if (cInfo != null) { + cInfo.onRegisterServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + } break; case NsdManager.UNREGISTER_SERVICE: - replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + cInfo = getClientInfoForReply(msg); + if (cInfo != null) { + cInfo.onUnregisterServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + } break; case NsdManager.RESOLVE_SERVICE: - replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + cInfo = getClientInfoForReply(msg); + if (cInfo != null) { + cInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + } break; case NsdManager.DAEMON_CLEANUP: mDaemon.maybeStop(); @@ -215,7 +218,7 @@ public class NsdService extends INsdManager.Stub { // This event should be only sent by the legacy (target SDK < S) clients. // Mark the sending client as legacy. case NsdManager.DAEMON_STARTUP: - cInfo = mClients.get(msg.replyTo); + cInfo = getClientInfoForReply(msg); if (cInfo != null) { cancelStop(); cInfo.setLegacy(); @@ -230,6 +233,11 @@ public class NsdService extends INsdManager.Stub { } return HANDLED; } + + private ClientInfo getClientInfoForReply(Message msg) { + final ListenerArgs args = (ListenerArgs) msg.obj; + return mClients.get(args.connector); + } } class DisabledState extends State { @@ -289,122 +297,119 @@ public class NsdService extends INsdManager.Stub { @Override public boolean processMessage(Message msg) { - ClientInfo clientInfo; - NsdServiceInfo servInfo; - int id; + final ClientInfo clientInfo; + final int id; + final int clientId = msg.arg2; + final ListenerArgs args; switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - return NOT_HANDLED; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - return NOT_HANDLED; case NsdManager.DISABLE: //TODO: cleanup clients transitionTo(mDisabledState); break; case NsdManager.DISCOVER_SERVICES: if (DBG) Slog.d(TAG, "Discover services"); - servInfo = (NsdServiceInfo) msg.obj; - clientInfo = mClients.get(msg.replyTo); + args = (ListenerArgs) msg.obj; + clientInfo = mClients.get(args.connector); if (requestLimitReached(clientInfo)) { - replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.FAILURE_MAX_LIMIT); + clientInfo.onDiscoverServicesFailed( + clientId, NsdManager.FAILURE_MAX_LIMIT); break; } maybeStartDaemon(); id = getUniqueId(); - if (discoverServices(id, servInfo.getServiceType())) { + if (discoverServices(id, args.serviceInfo.getServiceType())) { if (DBG) { Slog.d(TAG, "Discover " + msg.arg2 + " " + id + - servInfo.getServiceType()); + args.serviceInfo.getServiceType()); } - storeRequestMap(msg.arg2, id, clientInfo, msg.what); - replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED, servInfo); + storeRequestMap(clientId, id, clientInfo, msg.what); + clientInfo.onDiscoverServicesStarted(clientId, args.serviceInfo); } else { stopServiceDiscovery(id); - replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + clientInfo.onDiscoverServicesFailed(clientId, NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.STOP_DISCOVERY: if (DBG) Slog.d(TAG, "Stop service discovery"); - clientInfo = mClients.get(msg.replyTo); + args = (ListenerArgs) msg.obj; + clientInfo = mClients.get(args.connector); try { - id = clientInfo.mClientIds.get(msg.arg2); + id = clientInfo.mClientIds.get(clientId); } catch (NullPointerException e) { - replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.onStopDiscoveryFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); break; } - removeRequestMap(msg.arg2, id, clientInfo); + removeRequestMap(clientId, id, clientInfo); if (stopServiceDiscovery(id)) { - replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED); + clientInfo.onStopDiscoverySucceeded(clientId); } else { - replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.onStopDiscoveryFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.REGISTER_SERVICE: if (DBG) Slog.d(TAG, "Register service"); - clientInfo = mClients.get(msg.replyTo); + args = (ListenerArgs) msg.obj; + clientInfo = mClients.get(args.connector); if (requestLimitReached(clientInfo)) { - replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.FAILURE_MAX_LIMIT); + clientInfo.onRegisterServiceFailed( + clientId, NsdManager.FAILURE_MAX_LIMIT); break; } maybeStartDaemon(); id = getUniqueId(); - if (registerService(id, (NsdServiceInfo) msg.obj)) { - if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id); - storeRequestMap(msg.arg2, id, clientInfo, msg.what); + if (registerService(id, args.serviceInfo)) { + if (DBG) Slog.d(TAG, "Register " + clientId + " " + id); + storeRequestMap(clientId, id, clientInfo, msg.what); // Return success after mDns reports success } else { unregisterService(id); - replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.onRegisterServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.UNREGISTER_SERVICE: if (DBG) Slog.d(TAG, "unregister service"); - clientInfo = mClients.get(msg.replyTo); - try { - id = clientInfo.mClientIds.get(msg.arg2); - } catch (NullPointerException e) { - replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + args = (ListenerArgs) msg.obj; + clientInfo = mClients.get(args.connector); + if (clientInfo == null) { + Slog.e(TAG, "Unknown connector in unregistration"); break; } - removeRequestMap(msg.arg2, id, clientInfo); + id = clientInfo.mClientIds.get(clientId); + removeRequestMap(clientId, id, clientInfo); if (unregisterService(id)) { - replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED); + clientInfo.onUnregisterServiceSucceeded(clientId); } else { - replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.onUnregisterServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.RESOLVE_SERVICE: if (DBG) Slog.d(TAG, "Resolve service"); - servInfo = (NsdServiceInfo) msg.obj; - clientInfo = mClients.get(msg.replyTo); - + args = (ListenerArgs) msg.obj; + clientInfo = mClients.get(args.connector); if (clientInfo.mResolvedService != null) { - replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_ALREADY_ACTIVE); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_ALREADY_ACTIVE); break; } maybeStartDaemon(); id = getUniqueId(); - if (resolveService(id, servInfo)) { + if (resolveService(id, args.serviceInfo)) { clientInfo.mResolvedService = new NsdServiceInfo(); - storeRequestMap(msg.arg2, id, clientInfo, msg.what); + storeRequestMap(clientId, id, clientInfo, msg.what); } else { - replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.NATIVE_DAEMON_EVENT: @@ -449,30 +454,27 @@ public class NsdService extends INsdManager.Stub { case NativeResponseCode.SERVICE_FOUND: /* NNN uniqueId serviceName regType domain */ servInfo = new NsdServiceInfo(cooked[2], cooked[3]); - clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0, - clientId, servInfo); + clientInfo.onServiceFound(clientId, servInfo); break; case NativeResponseCode.SERVICE_LOST: /* NNN uniqueId serviceName regType domain */ servInfo = new NsdServiceInfo(cooked[2], cooked[3]); - clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0, - clientId, servInfo); + clientInfo.onServiceLost(clientId, servInfo); break; case NativeResponseCode.SERVICE_DISCOVERY_FAILED: /* NNN uniqueId errorCode */ - clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR, clientId); + clientInfo.onDiscoverServicesFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); break; case NativeResponseCode.SERVICE_REGISTERED: /* NNN regId serviceName regType */ servInfo = new NsdServiceInfo(cooked[2], null); - clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED, - id, clientId, servInfo); + clientInfo.onRegisterServiceSucceeded(clientId, servInfo); break; case NativeResponseCode.SERVICE_REGISTRATION_FAILED: /* NNN regId errorCode */ - clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR, clientId); + clientInfo.onRegisterServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); break; case NativeResponseCode.SERVICE_UPDATED: /* NNN regId */ @@ -511,8 +513,8 @@ public class NsdService extends INsdManager.Stub { if (getAddrInfo(id2, cooked[3])) { storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE); } else { - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR, clientId); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); clientInfo.mResolvedService = null; } break; @@ -521,26 +523,26 @@ public class NsdService extends INsdManager.Stub { stopResolveService(id); removeRequestMap(clientId, id, clientInfo); clientInfo.mResolvedService = null; - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR, clientId); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); break; case NativeResponseCode.SERVICE_GET_ADDR_FAILED: /* NNN resolveId errorCode */ stopGetAddrInfo(id); removeRequestMap(clientId, id, clientInfo); clientInfo.mResolvedService = null; - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR, clientId); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); break; case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: /* NNN resolveId hostname ttl addr */ try { clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED, - 0, clientId, clientInfo.mResolvedService); + clientInfo.onResolveServiceSucceeded( + clientId, clientInfo.mResolvedService); } catch (java.net.UnknownHostException e) { - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR, clientId); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); } stopGetAddrInfo(id); removeRequestMap(clientId, id, clientInfo); @@ -601,15 +603,71 @@ public class NsdService extends INsdManager.Stub { return service; } - public Messenger getMessenger() { + @Override + public INsdServiceConnector connect(INsdManagerCallback cb) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "NsdService"); - return new Messenger(mNsdStateMachine.getHandler()); + final INsdServiceConnector connector = new NsdServiceConnector(); + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.REGISTER_CLIENT, new Pair<>(connector, cb))); + return connector; + } + + private static class ListenerArgs { + public final NsdServiceConnector connector; + public final NsdServiceInfo serviceInfo; + ListenerArgs(NsdServiceConnector connector, NsdServiceInfo serviceInfo) { + this.connector = connector; + this.serviceInfo = serviceInfo; + } } - public void setEnabled(boolean isEnabled) { - NetworkStack.checkNetworkStackPermission(mContext); - mNsdSettings.putEnabledStatus(isEnabled); - notifyEnabled(isEnabled); + private class NsdServiceConnector extends INsdServiceConnector.Stub + implements IBinder.DeathRecipient { + @Override + public void registerService(int listenerKey, NsdServiceInfo serviceInfo) { + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.REGISTER_SERVICE, 0, listenerKey, + new ListenerArgs(this, serviceInfo))); + } + + @Override + public void unregisterService(int listenerKey) { + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.UNREGISTER_SERVICE, 0, listenerKey, + new ListenerArgs(this, null))); + } + + @Override + public void discoverServices(int listenerKey, NsdServiceInfo serviceInfo) { + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.DISCOVER_SERVICES, 0, listenerKey, + new ListenerArgs(this, serviceInfo))); + } + + @Override + public void stopDiscovery(int listenerKey) { + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.STOP_DISCOVERY, 0, listenerKey, new ListenerArgs(this, null))); + } + + @Override + public void resolveService(int listenerKey, NsdServiceInfo serviceInfo) { + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.RESOLVE_SERVICE, 0, listenerKey, + new ListenerArgs(this, serviceInfo))); + } + + @Override + public void startDaemon() { + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.DAEMON_STARTUP, new ListenerArgs(this, null))); + } + + @Override + public void binderDied() { + mNsdStateMachine.sendMessage( + mNsdStateMachine.obtainMessage(NsdManager.UNREGISTER_CLIENT, this)); + } } private void notifyEnabled(boolean isEnabled) { @@ -832,43 +890,11 @@ public class NsdService extends INsdManager.Stub { mNsdStateMachine.dump(fd, pw, args); } - /* arg2 on the source message has an id that needs to be retained in replies - * see NsdManager for details */ - private Message obtainMessage(Message srcMsg) { - Message msg = Message.obtain(); - msg.arg2 = srcMsg.arg2; - return msg; - } - - private void replyToMessage(Message msg, int what) { - if (msg.replyTo == null) return; - Message dstMsg = obtainMessage(msg); - dstMsg.what = what; - mReplyChannel.replyToMessage(msg, dstMsg); - } - - private void replyToMessage(Message msg, int what, int arg1) { - if (msg.replyTo == null) return; - Message dstMsg = obtainMessage(msg); - dstMsg.what = what; - dstMsg.arg1 = arg1; - mReplyChannel.replyToMessage(msg, dstMsg); - } - - private void replyToMessage(Message msg, int what, Object obj) { - if (msg.replyTo == null) return; - Message dstMsg = obtainMessage(msg); - dstMsg.what = what; - dstMsg.obj = obj; - mReplyChannel.replyToMessage(msg, dstMsg); - } - /* Information tracked per client */ private class ClientInfo { private static final int MAX_LIMIT = 10; - private final AsyncChannel mChannel; - private final Messenger mMessenger; + private final INsdManagerCallback mCb; /* Remembers a resolved service until getaddrinfo completes */ private NsdServiceInfo mResolvedService; @@ -881,17 +907,14 @@ public class NsdService extends INsdManager.Stub { // The target SDK of this client < Build.VERSION_CODES.S private boolean mIsLegacy = false; - private ClientInfo(AsyncChannel c, Messenger m) { - mChannel = c; - mMessenger = m; - if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m); + private ClientInfo(INsdManagerCallback cb) { + mCb = cb; + if (DBG) Slog.d(TAG, "New client"); } @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("mChannel ").append(mChannel).append("\n"); - sb.append("mMessenger ").append(mMessenger).append("\n"); sb.append("mResolvedService ").append(mResolvedService).append("\n"); sb.append("mIsLegacy ").append(mIsLegacy).append("\n"); for(int i = 0; i< mClientIds.size(); i++) { @@ -949,6 +972,102 @@ public class NsdService extends INsdManager.Stub { } return mClientIds.keyAt(idx); } + + void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) { + try { + mCb.onDiscoverServicesStarted(listenerKey, info); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onDiscoverServicesStarted", e); + } + } + + void onDiscoverServicesFailed(int listenerKey, int error) { + try { + mCb.onDiscoverServicesFailed(listenerKey, error); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onDiscoverServicesFailed", e); + } + } + + void onServiceFound(int listenerKey, NsdServiceInfo info) { + try { + mCb.onServiceFound(listenerKey, info); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onServiceFound(", e); + } + } + + void onServiceLost(int listenerKey, NsdServiceInfo info) { + try { + mCb.onServiceLost(listenerKey, info); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onServiceLost(", e); + } + } + + void onStopDiscoveryFailed(int listenerKey, int error) { + try { + mCb.onStopDiscoveryFailed(listenerKey, error); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onStopDiscoveryFailed", e); + } + } + + void onStopDiscoverySucceeded(int listenerKey) { + try { + mCb.onStopDiscoverySucceeded(listenerKey); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onStopDiscoverySucceeded", e); + } + } + + void onRegisterServiceFailed(int listenerKey, int error) { + try { + mCb.onRegisterServiceFailed(listenerKey, error); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onRegisterServiceFailed", e); + } + } + + void onRegisterServiceSucceeded(int listenerKey, NsdServiceInfo info) { + try { + mCb.onRegisterServiceSucceeded(listenerKey, info); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onRegisterServiceSucceeded", e); + } + } + + void onUnregisterServiceFailed(int listenerKey, int error) { + try { + mCb.onUnregisterServiceFailed(listenerKey, error); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onUnregisterServiceFailed", e); + } + } + + void onUnregisterServiceSucceeded(int listenerKey) { + try { + mCb.onUnregisterServiceSucceeded(listenerKey); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onUnregisterServiceSucceeded", e); + } + } + + void onResolveServiceFailed(int listenerKey, int error) { + try { + mCb.onResolveServiceFailed(listenerKey, error); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onResolveServiceFailed", e); + } + } + + void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info) { + try { + mCb.onResolveServiceSucceeded(listenerKey, info); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onResolveServiceSucceeded", e); + } + } } /** diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index ded115bbbcb4..1fe4d1405dca 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -642,10 +642,11 @@ public class ActivityManagerService extends IActivityManager.Stub final BroadcastQueue mFgBroadcastQueue; final BroadcastQueue mBgBroadcastQueue; - final BroadcastQueue mOffloadBroadcastQueue; + final BroadcastQueue mBgOffloadBroadcastQueue; + final BroadcastQueue mFgOffloadBroadcastQueue; // Convenient for easy iteration over the queues. Foreground is first // so that dispatch of foreground broadcasts gets precedence. - final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[3]; + final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[4]; @GuardedBy("this") BroadcastStats mLastBroadcastStats; @@ -656,12 +657,20 @@ public class ActivityManagerService extends IActivityManager.Stub TraceErrorLogger mTraceErrorLogger; BroadcastQueue broadcastQueueForIntent(Intent intent) { - if (isOnOffloadQueue(intent.getFlags())) { + if (isOnFgOffloadQueue(intent.getFlags())) { if (DEBUG_BROADCAST_BACKGROUND) { Slog.i(TAG_BROADCAST, - "Broadcast intent " + intent + " on offload queue"); + "Broadcast intent " + intent + " on foreground offload queue"); } - return mOffloadBroadcastQueue; + return mFgOffloadBroadcastQueue; + } + + if (isOnBgOffloadQueue(intent.getFlags())) { + if (DEBUG_BROADCAST_BACKGROUND) { + Slog.i(TAG_BROADCAST, + "Broadcast intent " + intent + " on background offload queue"); + } + return mBgOffloadBroadcastQueue; } final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0; @@ -2263,7 +2272,8 @@ public class ActivityManagerService extends IActivityManager.Stub mPendingStartActivityUids = new PendingStartActivityUids(mContext); mUseFifoUiScheduling = false; mEnableOffloadQueue = false; - mFgBroadcastQueue = mBgBroadcastQueue = mOffloadBroadcastQueue = null; + mFgBroadcastQueue = mBgBroadcastQueue = mBgOffloadBroadcastQueue = + mFgOffloadBroadcastQueue = null; mComponentAliasResolver = new ComponentAliasResolver(this); } @@ -2324,11 +2334,14 @@ public class ActivityManagerService extends IActivityManager.Stub "foreground", foreConstants, false); mBgBroadcastQueue = new BroadcastQueue(this, mHandler, "background", backConstants, true); - mOffloadBroadcastQueue = new BroadcastQueue(this, mHandler, - "offload", offloadConstants, true); + mBgOffloadBroadcastQueue = new BroadcastQueue(this, mHandler, + "offload_bg", offloadConstants, true); + mFgOffloadBroadcastQueue = new BroadcastQueue(this, mHandler, + "offload_fg", foreConstants, true); mBroadcastQueues[0] = mFgBroadcastQueue; mBroadcastQueues[1] = mBgBroadcastQueue; - mBroadcastQueues[2] = mOffloadBroadcastQueue; + mBroadcastQueues[2] = mBgOffloadBroadcastQueue; + mBroadcastQueues[3] = mFgOffloadBroadcastQueue; mServices = new ActiveServices(this); mCpHelper = new ContentProviderHelper(this, true); @@ -12552,13 +12565,15 @@ public class ActivityManagerService extends IActivityManager.Stub boolean isPendingBroadcastProcessLocked(int pid) { return mFgBroadcastQueue.isPendingBroadcastProcessLocked(pid) || mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid) - || mOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid); + || mBgOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid) + || mFgOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid); } boolean isPendingBroadcastProcessLocked(ProcessRecord app) { return mFgBroadcastQueue.isPendingBroadcastProcessLocked(app) || mBgBroadcastQueue.isPendingBroadcastProcessLocked(app) - || mOffloadBroadcastQueue.isPendingBroadcastProcessLocked(app); + || mBgOffloadBroadcastQueue.isPendingBroadcastProcessLocked(app) + || mFgOffloadBroadcastQueue.isPendingBroadcastProcessLocked(app); } void skipPendingBroadcastLocked(int pid) { @@ -14007,8 +14022,10 @@ public class ActivityManagerService extends IActivityManager.Stub BroadcastQueue queue; synchronized(this) { - if (isOnOffloadQueue(flags)) { - queue = mOffloadBroadcastQueue; + if (isOnFgOffloadQueue(flags)) { + queue = mFgOffloadBroadcastQueue; + } else if (isOnBgOffloadQueue(flags)) { + queue = mBgOffloadBroadcastQueue; } else { queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0 ? mFgBroadcastQueue : mBgBroadcastQueue; @@ -16302,7 +16319,7 @@ public class ActivityManagerService extends IActivityManager.Stub Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL); if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) { intent = new Intent(Intent.ACTION_LOCALE_CHANGED); - intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND + intent.addFlags(Intent.FLAG_RECEIVER_OFFLOAD_FOREGROUND | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); if (initLocale || !mProcessesReady) { @@ -17479,7 +17496,11 @@ public class ActivityManagerService extends IActivityManager.Stub } } - private boolean isOnOffloadQueue(int flags) { + private boolean isOnFgOffloadQueue(int flags) { + return ((flags & Intent.FLAG_RECEIVER_OFFLOAD_FOREGROUND) != 0); + } + + private boolean isOnBgOffloadQueue(int flags) { return (mEnableOffloadQueue && ((flags & Intent.FLAG_RECEIVER_OFFLOAD) != 0)); } diff --git a/services/core/java/com/android/server/app/OWNERS b/services/core/java/com/android/server/app/OWNERS new file mode 100644 index 000000000000..aaebbfa8e253 --- /dev/null +++ b/services/core/java/com/android/server/app/OWNERS @@ -0,0 +1 @@ +per-file GameManager* = file:/GAME_MANAGER_OWNERS diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java new file mode 100644 index 000000000000..05e1bdd11db6 --- /dev/null +++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java @@ -0,0 +1,476 @@ +/* + * 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.inputmethod; + +import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; + +import static com.android.server.inputmethod.InputMethodManagerService.MSG_INITIALIZE_IME; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.PendingIntent; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.PackageManagerInternal; +import android.content.res.Resources; +import android.inputmethodservice.InputMethodService; +import android.os.Binder; +import android.os.IBinder; +import android.os.Process; +import android.os.RemoteException; +import android.os.SystemClock; +import android.os.Trace; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.ArrayMap; +import android.util.Slog; +import android.view.IWindowManager; +import android.view.WindowManager; +import android.view.inputmethod.InputMethod; +import android.view.inputmethod.InputMethodInfo; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.inputmethod.InputBindResult; +import com.android.internal.inputmethod.UnbindReason; +import com.android.internal.view.IInputMethod; +import com.android.server.wm.WindowManagerInternal; + +/** + * A controller managing the state of the input method binding. + */ +final class InputMethodBindingController { + static final boolean DEBUG = false; + private static final String TAG = InputMethodBindingController.class.getSimpleName(); + + @NonNull private final InputMethodManagerService mService; + @NonNull private final Context mContext; + @NonNull private final ArrayMap<String, InputMethodInfo> mMethodMap; + @NonNull private final InputMethodUtils.InputMethodSettings mSettings; + @NonNull private final PackageManagerInternal mPackageManagerInternal; + @NonNull private final IWindowManager mIWindowManager; + @NonNull private final WindowManagerInternal mWindowManagerInternal; + @NonNull private final Resources mRes; + + private long mLastBindTime; + private boolean mHasConnection; + @Nullable private String mCurId; + @Nullable private String mSelectedMethodId; + @Nullable private Intent mCurIntent; + @Nullable private IInputMethod mCurMethod; + private int mCurMethodUid = Process.INVALID_UID; + private IBinder mCurToken; + private int mCurSeq; + private boolean mVisibleBound; + + /** + * Binding flags for establishing connection to the {@link InputMethodService}. + */ + private static final int IME_CONNECTION_BIND_FLAGS = + Context.BIND_AUTO_CREATE + | Context.BIND_NOT_VISIBLE + | Context.BIND_NOT_FOREGROUND + | Context.BIND_IMPORTANT_BACKGROUND; + /** + * Binding flags for establishing connection to the {@link InputMethodService} when + * config_killableInputMethods is enabled. + */ + private static final int IME_CONNECTION_LOW_PRIORITY_BIND_FLAGS = + Context.BIND_AUTO_CREATE + | Context.BIND_REDUCTION_FLAGS; + /** + * Binding flags used only while the {@link InputMethodService} is showing window. + */ + private static final int IME_VISIBLE_BIND_FLAGS = + Context.BIND_AUTO_CREATE + | Context.BIND_TREAT_LIKE_ACTIVITY + | Context.BIND_FOREGROUND_SERVICE + | Context.BIND_INCLUDE_CAPABILITIES + | Context.BIND_SHOWING_UI + | Context.BIND_SCHEDULE_LIKE_TOP_APP; + + /** + * Binding flags for establishing connection to the {@link InputMethodService}. + * + * <p> + * This defaults to {@link InputMethodBindingController#IME_CONNECTION_BIND_FLAGS} unless + * config_killableInputMethods is enabled, in which case this takes the value of + * {@link InputMethodBindingController#IME_CONNECTION_LOW_PRIORITY_BIND_FLAGS}. + */ + private final int mImeConnectionBindFlags; + + InputMethodBindingController(@NonNull InputMethodManagerService service) { + mService = service; + mContext = mService.mContext; + mMethodMap = mService.mMethodMap; + mSettings = mService.mSettings; + mPackageManagerInternal = mService.mPackageManagerInternal; + mIWindowManager = mService.mIWindowManager; + mWindowManagerInternal = mService.mWindowManagerInternal; + mRes = mService.mRes; + + // If configured, use low priority flags to make the IME killable by the lowmemorykiller + final boolean lowerIMEPriority = mRes.getBoolean( + com.android.internal.R.bool.config_killableInputMethods); + + if (lowerIMEPriority) { + mImeConnectionBindFlags = + InputMethodBindingController.IME_CONNECTION_LOW_PRIORITY_BIND_FLAGS; + } else { + mImeConnectionBindFlags = InputMethodBindingController.IME_CONNECTION_BIND_FLAGS; + } + } + + /** + * Time that we last initiated a bind to the input method, to determine + * if we should try to disconnect and reconnect to it. + */ + long getLastBindTime() { + return mLastBindTime; + } + + /** + * Set to true if our ServiceConnection is currently actively bound to + * a service (whether or not we have gotten its IBinder back yet). + */ + boolean hasConnection() { + return mHasConnection; + } + + /** + * Id obtained with {@link InputMethodInfo#getId()} for the input method that we are currently + * connected to or in the process of connecting to. + * + * <p>This can be {@code null} when no input method is connected.</p> + * + * @see #getSelectedMethodId() + */ + @Nullable + String getCurId() { + return mCurId; + } + + /** + * Id obtained with {@link InputMethodInfo#getId()} for the currently selected input method. + * This is to be synchronized with the secure settings keyed with + * {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD}. + * + * <p>This can be transiently {@code null} when the system is re-initializing input method + * settings, e.g., the system locale is just changed.</p> + * + * <p>Note that {@link #getCurId()} is used to track which IME is being connected to + * {@link com.android.server.inputmethod.InputMethodManagerService}.</p> + * + * @see #getCurId() + */ + @Nullable + String getSelectedMethodId() { + return mSelectedMethodId; + } + + void setSelectedMethodId(@Nullable String selectedMethodId) { + mSelectedMethodId = selectedMethodId; + } + + /** + * The token we have made for the currently active input method, to + * identify it in the future. + */ + IBinder getCurToken() { + return mCurToken; + } + + /** + * The Intent used to connect to the current input method. + */ + @Nullable + Intent getCurIntent() { + return mCurIntent; + } + + /** + * The current binding sequence number, incremented every time there is + * a new bind performed. + */ + int getSequenceNumber() { + return mCurSeq; + } + + /** + * Increase the current binding sequence number by one. + * Reset to 1 on overflow. + */ + void advanceSequenceNumber() { + mCurSeq += 1; + if (mCurSeq <= 0) { + mCurSeq = 1; + } + } + + /** + * If non-null, this is the input method service we are currently connected + * to. + */ + @Nullable + IInputMethod getCurMethod() { + return mCurMethod; + } + + /** + * If not {@link Process#INVALID_UID}, then the UID of {@link #getCurIntent()}. + */ + int getCurMethodUid() { + return mCurMethodUid; + } + + /** + * Indicates whether {@link #getVisibleConnection} is currently in use. + */ + boolean isVisibleBound() { + return mVisibleBound; + } + + /** + * Used to bring IME service up to visible adjustment while it is being shown. + */ + @NonNull + ServiceConnection getVisibleConnection() { + return mVisibleConnection; + } + + private final ServiceConnection mVisibleConnection = new ServiceConnection() { + @Override public void onBindingDied(ComponentName name) { + synchronized (mMethodMap) { + if (mVisibleBound) { + unbindVisibleConnectionLocked(); + } + } + } + + @Override public void onServiceConnected(ComponentName name, IBinder service) { + } + + @Override public void onServiceDisconnected(ComponentName name) { + } + }; + + /** + * Used to bind the IME while it is not currently being shown. + */ + private final ServiceConnection mMainConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.onServiceConnected"); + synchronized (mMethodMap) { + if (mCurIntent != null && name.equals(mCurIntent.getComponent())) { + mCurMethod = IInputMethod.Stub.asInterface(service); + updateCurrentMethodUidLocked(); + if (mCurToken == null) { + Slog.w(TAG, "Service connected without a token!"); + unbindCurrentMethodLocked(); + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); + return; + } + if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken); + // Dispatch display id for InputMethodService to update context display. + mService.executeOrSendMessage(mCurMethod, + mService.mCaller.obtainMessageIOO(MSG_INITIALIZE_IME, + mMethodMap.get(mSelectedMethodId).getConfigChanges(), + mCurMethod, mCurToken)); + mService.scheduleNotifyImeUidToAudioService(mCurMethodUid); + mService.reRequestCurrentClientSessionLocked(); + } + } + Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); + } + + @GuardedBy("mMethodMap") + private void updateCurrentMethodUidLocked() { + final String curMethodPackage = mCurIntent.getComponent().getPackageName(); + final int curMethodUid = mPackageManagerInternal.getPackageUid( + curMethodPackage, 0 /* flags */, mSettings.getCurrentUserId()); + if (curMethodUid < 0) { + Slog.e(TAG, "Failed to get UID for package=" + curMethodPackage); + mCurMethodUid = Process.INVALID_UID; + } else { + mCurMethodUid = curMethodUid; + } + } + + @Override + public void onServiceDisconnected(@NonNull ComponentName name) { + // Note that mContext.unbindService(this) does not trigger this. Hence if we are + // here the + // disconnection is not intended by IMMS (e.g. triggered because the current IMS + // crashed), + // which is irregular but can eventually happen for everyone just by continuing + // using the + // device. Thus it is important to make sure that all the internal states are + // properly + // refreshed when this method is called back. Running + // adb install -r <APK that implements the current IME> + // would be a good way to trigger such a situation. + synchronized (mMethodMap) { + if (DEBUG) { + Slog.v(TAG, "Service disconnected: " + name + " mCurIntent=" + mCurIntent); + } + if (mCurMethod != null && mCurIntent != null + && name.equals(mCurIntent.getComponent())) { + // We consider this to be a new bind attempt, since the system + // should now try to restart the service for us. + mLastBindTime = SystemClock.uptimeMillis(); + mService.clearClientSessionsLocked(); + mService.clearInputShowRequestLocked(); + mService.unbindCurrentClientLocked(UnbindReason.DISCONNECT_IME); + } + } + } + }; + + @GuardedBy("mMethodMap") + void unbindCurrentMethodLocked() { + if (mVisibleBound) { + unbindVisibleConnectionLocked(); + } + + if (mHasConnection) { + unbindMainConnectionLocked(); + } + + if (mCurToken != null) { + removeCurrentTokenLocked(); + mService.resetSystemUiLocked(); + } + + mCurId = null; + mService.clearClientSessionsLocked(); + } + + @GuardedBy("mMethodMap") + void clearCurMethodLocked() { + mCurMethod = null; + mCurMethodUid = Process.INVALID_UID; + } + + @GuardedBy("mMethodMap") + private void removeCurrentTokenLocked() { + int curTokenDisplayId = mService.getCurTokenDisplayId(); + + if (DEBUG) { + Slog.v(TAG, + "Removing window token: " + mCurToken + " for display: " + curTokenDisplayId); + } + mWindowManagerInternal.removeWindowToken(mCurToken, false /* removeWindows */, + false /* animateExit */, curTokenDisplayId); + mCurToken = null; + } + + @GuardedBy("mMethodMap") + @NonNull + InputBindResult bindCurrentMethodLocked(int displayIdToShowIme) { + InputMethodInfo info = mMethodMap.get(mSelectedMethodId); + if (info == null) { + throw new IllegalArgumentException("Unknown id: " + mSelectedMethodId); + } + + mCurIntent = createImeBindingIntent(info.getComponent()); + + if (bindCurrentInputMethodServiceMainConnectionLocked()) { + mCurId = info.getId(); + mLastBindTime = SystemClock.uptimeMillis(); + + addFreshWindowTokenLocked(displayIdToShowIme); + return new InputBindResult( + InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING, + null, null, mCurId, mCurSeq, false); + } + + Slog.w(InputMethodManagerService.TAG, + "Failure connecting to input method service: " + mCurIntent); + mCurIntent = null; + return InputBindResult.IME_NOT_CONNECTED; + } + + @NonNull + private Intent createImeBindingIntent(ComponentName component) { + Intent intent = new Intent(InputMethod.SERVICE_INTERFACE); + intent.setComponent(component); + intent.putExtra(Intent.EXTRA_CLIENT_LABEL, + com.android.internal.R.string.input_method_binding_label); + intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( + mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), + PendingIntent.FLAG_IMMUTABLE)); + return intent; + } + + @GuardedBy("mMethodMap") + private void addFreshWindowTokenLocked(int displayIdToShowIme) { + mCurToken = new Binder(); + + mService.setCurTokenDisplayId(displayIdToShowIme); + + try { + if (DEBUG) { + Slog.v(TAG, "Adding window token: " + mCurToken + " for display: " + + displayIdToShowIme); + } + mIWindowManager.addWindowToken(mCurToken, WindowManager.LayoutParams.TYPE_INPUT_METHOD, + displayIdToShowIme, null /* options */); + } catch (RemoteException e) { + Slog.e(TAG, "Could not add window token " + mCurToken + " for display " + + displayIdToShowIme, e); + } + } + + @GuardedBy("mMethodMap") + void unbindMainConnectionLocked() { + mContext.unbindService(mMainConnection); + mHasConnection = false; + } + + @GuardedBy("mMethodMap") + void unbindVisibleConnectionLocked() { + mContext.unbindService(mVisibleConnection); + mVisibleBound = false; + } + + @GuardedBy("mMethodMap") + private boolean bindCurrentInputMethodServiceLocked(ServiceConnection conn, int flags) { + if (mCurIntent == null || conn == null) { + Slog.e(TAG, "--- bind failed: service = " + mCurIntent + ", conn = " + conn); + return false; + } + return mContext.bindServiceAsUser(mCurIntent, conn, flags, + new UserHandle(mSettings.getCurrentUserId())); + } + + @GuardedBy("mMethodMap") + boolean bindCurrentInputMethodServiceVisibleConnectionLocked() { + mVisibleBound = bindCurrentInputMethodServiceLocked(mVisibleConnection, + IME_VISIBLE_BIND_FLAGS); + return mVisibleBound; + } + + @GuardedBy("mMethodMap") + boolean bindCurrentInputMethodServiceMainConnectionLocked() { + mHasConnection = bindCurrentInputMethodServiceLocked(mMainConnection, + mImeConnectionBindFlags); + return mHasConnection; + } + +} diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index cb76d8325c4b..c879e3d792f9 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -72,13 +72,11 @@ import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; -import android.content.ComponentName; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; @@ -208,7 +206,7 @@ import java.util.concurrent.atomic.AtomicInteger; * This class provides a system service that manages input methods. */ public class InputMethodManagerService extends IInputMethodManager.Stub - implements ServiceConnection, Handler.Callback { + implements Handler.Callback { static final boolean DEBUG = false; static final String TAG = "InputMethodManagerService"; public static final String PROTO_ARG = "--proto"; @@ -261,44 +259,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private static final String HANDLER_THREAD_NAME = "android.imms"; /** - * Binding flags for establishing connection to the {@link InputMethodService}. - */ - private static final int IME_CONNECTION_BIND_FLAGS = - Context.BIND_AUTO_CREATE - | Context.BIND_NOT_VISIBLE - | Context.BIND_NOT_FOREGROUND - | Context.BIND_IMPORTANT_BACKGROUND; - - /** - * Binding flags for establishing connection to the {@link InputMethodService} when - * config_killableInputMethods is enabled. - */ - private static final int IME_CONNECTION_LOW_PRIORITY_BIND_FLAGS = - Context.BIND_AUTO_CREATE - | Context.BIND_REDUCTION_FLAGS; - - /** - * Binding flags for establishing connection to the {@link InputMethodService}. - * - * <p> - * This defaults to {@link #IME_CONNECTION_BIND_FLAGS} unless config_killableInputMethods is - * enabled, in which case this takes the value of - * {@link #IME_CONNECTION_LOW_PRIORITY_BIND_FLAGS}. - */ - private final int mImeConnectionBindFlags; - - /** - * Binding flags used only while the {@link InputMethodService} is showing window. - */ - private static final int IME_VISIBLE_BIND_FLAGS = - Context.BIND_AUTO_CREATE - | Context.BIND_TREAT_LIKE_ACTIVITY - | Context.BIND_FOREGROUND_SERVICE - | Context.BIND_INCLUDE_CAPABILITIES - | Context.BIND_SHOWING_UI - | Context.BIND_SCHEDULE_LIKE_TOP_APP; - - /** * A protected broadcast intent action for internal use for {@link PendingIntent} in * the notification. */ @@ -321,11 +281,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final boolean mHasFeature; private final ArrayMap<String, List<InputMethodSubtype>> mAdditionalSubtypeMap = new ArrayMap<>(); - private final boolean mIsLowRam; private final AppOpsManager mAppOpsManager; private final UserManager mUserManager; private final UserManagerInternal mUserManagerInternal; private final InputMethodMenuController mMenuController; + private final InputMethodBindingController mBindingController; /** * Cache the result of {@code LocalServices.getService(AudioManagerInternal.class)}. @@ -351,31 +311,20 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("mMethodMap") private int mMethodMapUpdateCount = 0; - // Used to bring IME service up to visible adjustment while it is being shown. - final ServiceConnection mVisibleConnection = new ServiceConnection() { - @Override public void onBindingDied(ComponentName name) { - synchronized (mMethodMap) { - if (mVisibleBound) { - mContext.unbindService(mVisibleConnection); - mVisibleBound = false; - } - } - } - - @Override public void onServiceConnected(ComponentName name, IBinder service) { - } - - @Override public void onServiceDisconnected(ComponentName name) { - } - }; - boolean mVisibleBound = false; + /** + * Indicates whether {@link InputMethodBindingController#getVisibleConnection} is currently + * in use. + */ + private boolean isVisibleBound() { + return mBindingController.isVisibleBound(); + } // Ongoing notification private NotificationManager mNotificationManager; KeyguardManager mKeyguardManager; private @Nullable StatusBarManagerService mStatusBar; - private Notification.Builder mImeSwitcherNotification; - private PendingIntent mImeSwitchPendingIntent; + private final Notification.Builder mImeSwitcherNotification; + private final PendingIntent mImeSwitchPendingIntent; private boolean mShowOngoingImeSwitcherForPhones; private boolean mNotificationShown; @@ -463,25 +412,41 @@ public class InputMethodManagerService extends IInputMethodManager.Stub /** * Id obtained with {@link InputMethodInfo#getId()} for the currently selected input method. - * method. This is to be synchronized with the secure settings keyed with + * This is to be synchronized with the secure settings keyed with * {@link Settings.Secure#DEFAULT_INPUT_METHOD}. * * <p>This can be transiently {@code null} when the system is re-initializing input method * settings, e.g., the system locale is just changed.</p> * - * <p>Note that {@link #mCurId} is used to track which IME is being connected to - * {@link InputMethodManagerService}.</p> + * <p>Note that {@link InputMethodBindingController#getCurId()} is used to track which IME is + * being connected to {@link InputMethodManagerService}.</p> * - * @see #mCurId + * @see InputMethodBindingController#getCurId() */ @Nullable - String mCurMethodId; + private String getSelectedMethodId() { + return mBindingController.getSelectedMethodId(); + } + + private void setSelectedMethodId(@Nullable String selectedMethodId) { + mBindingController.setSelectedMethodId(selectedMethodId); + } /** * The current binding sequence number, incremented every time there is * a new bind performed. */ - int mCurSeq; + private int getSequenceNumber() { + return mBindingController.getSequenceNumber(); + } + + /** + * Increase the current binding sequence number by one. + * Reset to 1 on overflow. + */ + private void advanceSequenceNumber() { + mBindingController.advanceSequenceNumber(); + } /** * {@code true} if the Ime policy has been set to {@link WindowManager#DISPLAY_IME_POLICY_HIDE}. @@ -493,7 +458,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub /** * The client that is currently bound to an input method. */ - ClientState mCurClient; + private ClientState mCurClient; /** * The last window token that we confirmed to be focused. This is always updated upon reports @@ -538,10 +503,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub * * <p>This can be {@code null} when no input method is connected.</p> * - * @see #mCurMethodId + * @see #getSelectedMethodId() */ @Nullable - String mCurId; + private String getCurId() { + return mBindingController.getCurId(); + } /** * The current subtype of the current input method. @@ -557,12 +524,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub * Set to true if our ServiceConnection is currently actively bound to * a service (whether or not we have gotten its IBinder back yet). */ - boolean mHaveConnection; + private boolean hasConnection() { + return mBindingController.hasConnection(); + } /** * Set if the client has asked for the input method to be shown. */ - boolean mShowRequested; + private boolean mShowRequested; /** * Set if we were explicitly told to show the input method. @@ -577,7 +546,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub /** * Set if we last told the input method to show itself. */ - boolean mInputShown; + private boolean mInputShown; /** * {@code true} if the current input method is in fullscreen mode. @@ -587,17 +556,30 @@ public class InputMethodManagerService extends IInputMethodManager.Stub /** * The Intent used to connect to the current input method. */ - Intent mCurIntent; + @Nullable + private Intent getCurIntent() { + return mBindingController.getCurIntent(); + } /** * The token we have made for the currently active input method, to * identify it in the future. */ - IBinder mCurToken; + private IBinder getCurToken() { + return mBindingController.getCurToken(); + } /** * The displayId of current active input method. */ + int getCurTokenDisplayId() { + return mCurTokenDisplayId; + } + + void setCurTokenDisplayId(int curTokenDisplayId) { + mCurTokenDisplayId = curTokenDisplayId; + } + int mCurTokenDisplayId = INVALID_DISPLAY; /** @@ -619,18 +601,25 @@ public class InputMethodManagerService extends IInputMethodManager.Stub * If non-null, this is the input method service we are currently connected * to. */ - IInputMethod mCurMethod; + @Nullable + private IInputMethod getCurMethod() { + return mBindingController.getCurMethod(); + } /** - * If not {@link Process#INVALID_UID}, then the UID of {@link #mCurIntent}. + * If not {@link Process#INVALID_UID}, then the UID of {@link #getCurIntent()}. */ - int mCurMethodUid = Process.INVALID_UID; + private int getCurMethodUid() { + return mBindingController.getCurMethodUid(); + } /** * Time that we last initiated a bind to the input method, to determine * if we should try to disconnect and reconnect to it. */ - long mLastBindTime; + private long getLastBindTime() { + return mBindingController.getLastBindTime(); + } /** * Have we called mCurMethod.bindInput()? @@ -648,7 +637,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub */ boolean mIsInteractive = true; - private IPlatformCompat mPlatformCompat; + private final IPlatformCompat mPlatformCompat; int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT; @@ -671,7 +660,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub * </dd> * </dl> * <em>Do not update this value outside of {@link #setImeWindowStatus(IBinder, int, int)} and - * {@link #unbindCurrentMethodLocked()}.</em> + * {@link InputMethodBindingController#unbindCurrentMethodLocked()}.</em> */ int mImeWindowVis; @@ -758,7 +747,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private final WeakHashMap<IBinder, IBinder> mImeTargetWindowMap = new WeakHashMap<>(); private static final class SoftInputShowHideHistory { - private Entry[] mEntries = new Entry[16]; + private final Entry[] mEntries = new Entry[16]; private int mNextIndex = 0; private static final AtomicInteger sSequenceNumber = new AtomicInteger(0); @@ -1512,7 +1501,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private UserSwitchHandlerTask mUserSwitchHandlerTask; public static final class Lifecycle extends SystemService { - private InputMethodManagerService mService; + private final InputMethodManagerService mService; public Lifecycle(Context context) { super(context); @@ -1610,13 +1599,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); - mImeDisplayValidator = displayId -> mWindowManagerInternal.getDisplayImePolicy(displayId); - mCaller = new HandlerCaller(context, thread.getLooper(), new HandlerCaller.Callback() { - @Override - public void executeMessage(Message msg) { - handleMessage(msg); - } - }, true /*asyncHandler*/); + mImeDisplayValidator = mWindowManagerInternal::getDisplayImePolicy; + mCaller = new HandlerCaller(context, thread.getLooper(), this::handleMessage, + true /*asyncHandler*/); mAppOpsManager = mContext.getSystemService(AppOpsManager.class); mUserManager = mContext.getSystemService(UserManager.class); mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); @@ -1625,7 +1610,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mPlatformCompat = IPlatformCompat.Stub.asInterface( ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime); - mIsLowRam = ActivityManager.isLowRamDeviceStatic(); Bundle extras = new Bundle(); extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true); @@ -1666,22 +1650,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( mSettings, context); mMenuController = new InputMethodMenuController(this); - - // If configured, use low priority flags to make the IME killable by the lowmemorykiller - final boolean lowerIMEPriority = mRes.getBoolean( - com.android.internal.R.bool.config_killableInputMethods); - - if (lowerIMEPriority) { - mImeConnectionBindFlags = IME_CONNECTION_LOW_PRIORITY_BIND_FLAGS; - } else { - mImeConnectionBindFlags = IME_CONNECTION_BIND_FLAGS; - } + mBindingController = new InputMethodBindingController(this); } @GuardedBy("mMethodMap") private void resetDefaultImeLocked(Context context) { // Do not reset the default (current) IME when it is a 3rd-party IME - if (mCurMethodId != null && !mMethodMap.get(mCurMethodId).isSystem()) { + String selectedMethodId = getSelectedMethodId(); + if (selectedMethodId != null && !mMethodMap.get(selectedMethodId).isSystem()) { return; } final List<InputMethodInfo> suitableImes = InputMethodUtils.getDefaultEnabledImes( @@ -1796,9 +1772,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mKeyguardManager = mContext.getSystemService(KeyguardManager.class); mNotificationManager = mContext.getSystemService(NotificationManager.class); mStatusBar = statusBar; - if (mStatusBar != null) { - mStatusBar.setIconVisibility(mSlotIme, false); - } + hideStatusBarIconLocked(); updateSystemUiLocked(mImeWindowVis, mBackDisposition); mShowOngoingImeSwitcherForPhones = mRes.getBoolean( com.android.internal.R.bool.show_ongoing_ime_switcher); @@ -1890,7 +1864,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (token == null) { throw new InvalidParameterException("token must not be null."); } - if (token != mCurToken) { + if (token != getCurToken()) { Slog.e(TAG, "Ignoring " + Debug.getCaller() + " due to an invalid token." + " uid:" + Binder.getCallingUid() + " token:" + token); return false; @@ -1898,17 +1872,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return true; } - @GuardedBy("mMethodMap") - private boolean bindCurrentInputMethodServiceLocked( - Intent service, ServiceConnection conn, int flags) { - if (service == null || conn == null) { - Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn); - return false; - } - return mContext.bindServiceAsUser(service, conn, flags, - new UserHandle(mSettings.getCurrentUserId())); - } - @Override public List<InputMethodInfo> getInputMethodList(@UserIdInt int userId) { if (UserHandle.getCallingUserId() != userId) { @@ -1989,14 +1952,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("mMethodMap") private void onCreateInlineSuggestionsRequestLocked(@UserIdInt int userId, InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback callback) { - final InputMethodInfo imi = mMethodMap.get(mCurMethodId); + final InputMethodInfo imi = mMethodMap.get(getSelectedMethodId()); try { + IInputMethod curMethod = getCurMethod(); if (userId == mSettings.getCurrentUserId() && imi != null - && imi.isInlineSuggestionsEnabled() && mCurMethod != null) { - executeOrSendMessage(mCurMethod, - mCaller.obtainMessageOOO(MSG_INLINE_SUGGESTIONS_REQUEST, mCurMethod, + && imi.isInlineSuggestionsEnabled() && curMethod != null) { + executeOrSendMessage(curMethod, + mCaller.obtainMessageOOO(MSG_INLINE_SUGGESTIONS_REQUEST, curMethod, requestInfo, new InlineSuggestionsRequestCallbackDecorator(callback, - imi.getPackageName(), mCurTokenDisplayId, mCurToken, + imi.getPackageName(), mCurTokenDisplayId, getCurToken(), this))); } else { callback.onInlineSuggestionsUnsupported(); @@ -2132,8 +2096,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub boolean allowsImplicitlySelectedSubtypes, @UserIdInt int userId) { if (userId == mSettings.getCurrentUserId()) { final InputMethodInfo imi; - if (imiId == null && mCurMethodId != null) { - imi = mMethodMap.get(mCurMethodId); + String selectedMethodId = getSelectedMethodId(); + if (imiId == null && selectedMethodId != null) { + imi = mMethodMap.get(selectedMethodId); } else { imi = mMethodMap.get(imiId); } @@ -2230,9 +2195,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mCurFocusedWindow, 0, null, SoftInputShowHideReason.HIDE_REMOVE_CLIENT); if (mBoundToMethod) { mBoundToMethod = false; - if (mCurMethod != null) { - executeOrSendMessage(mCurMethod, mCaller.obtainMessageO( - MSG_UNBIND_INPUT, mCurMethod)); + IInputMethod curMethod = getCurMethod(); + if (curMethod != null) { + executeOrSendMessage(curMethod, mCaller.obtainMessageO( + MSG_UNBIND_INPUT, curMethod)); } } mCurClient = null; @@ -2260,16 +2226,17 @@ public class InputMethodManagerService extends IInputMethodManager.Stub + mCurClient.client.asBinder()); if (mBoundToMethod) { mBoundToMethod = false; - if (mCurMethod != null) { - executeOrSendMessage(mCurMethod, mCaller.obtainMessageO( - MSG_UNBIND_INPUT, mCurMethod)); + IInputMethod curMethod = getCurMethod(); + if (curMethod != null) { + executeOrSendMessage(curMethod, mCaller.obtainMessageO( + MSG_UNBIND_INPUT, curMethod)); } } scheduleSetActiveToClient(mCurClient, false /* active */, false /* fullscreen */, false /* reportToImeController */); executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIIO( - MSG_UNBIND_CLIENT, mCurSeq, unbindClientReason, mCurClient.client)); + MSG_UNBIND_CLIENT, getSequenceNumber(), unbindClientReason, mCurClient.client)); mCurClient.sessionRequested = false; mCurClient = null; @@ -2278,6 +2245,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @GuardedBy("mMethodMap") + void clearInputShowRequestLocked() { + mShowRequested = mInputShown; + mInputShown = false; + } + + @GuardedBy("mMethodMap") private int getImeShowFlagsLocked() { int flags = 0; if (mShowForced) { @@ -2304,16 +2277,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @NonNull InputBindResult attachNewInputLocked(@StartInputReason int startInputReason, boolean initial) { if (!mBoundToMethod) { - executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO( - MSG_BIND_INPUT, mCurMethod, mCurClient.binding)); + IInputMethod curMethod = getCurMethod(); + executeOrSendMessage(curMethod, mCaller.obtainMessageOO( + MSG_BIND_INPUT, curMethod, mCurClient.binding)); mBoundToMethod = true; } final Binder startInputToken = new Binder(); - final StartInputInfo info = new StartInputInfo(mSettings.getCurrentUserId(), mCurToken, - mCurTokenDisplayId, mCurId, startInputReason, !initial, + final StartInputInfo info = new StartInputInfo(mSettings.getCurrentUserId(), getCurToken(), + mCurTokenDisplayId, getCurId(), startInputReason, !initial, UserHandle.getUserId(mCurClient.uid), mCurClient.selfReportedDisplayId, - mCurFocusedWindow, mCurAttribute, mCurFocusedWindowSoftInputMode, mCurSeq); + mCurFocusedWindow, mCurAttribute, mCurFocusedWindowSoftInputMode, + getSequenceNumber()); mImeTargetWindowMap.put(startInputToken, mCurFocusedWindow); mStartInputHistory.addEntry(info); @@ -2324,7 +2299,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // INTERACT_ACROSS_USERS(_FULL) permissions, which is actually almost always the case. if (mSettings.getCurrentUserId() == UserHandle.getUserId(mCurClient.uid)) { mPackageManagerInternal.grantImplicitAccess(mSettings.getCurrentUserId(), - null /* intent */, UserHandle.getAppId(mCurMethodUid), mCurClient.uid, true); + null /* intent */, UserHandle.getAppId(getCurMethodUid()), mCurClient.uid, + true /* direct */); } final SessionState session = mCurClient.curSession; @@ -2336,12 +2312,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub showCurrentInputLocked(mCurFocusedWindow, getAppShowFlagsLocked(), null, SoftInputShowHideReason.ATTACH_NEW_INPUT); } - final InputMethodInfo curInputMethodInfo = mMethodMap.get(mCurId); + + String curId = getCurId(); + final InputMethodInfo curInputMethodInfo = mMethodMap.get(curId); final boolean suppressesSpellChecker = curInputMethodInfo != null && curInputMethodInfo.suppressesSpellChecker(); return new InputBindResult(InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION, session.session, (session.channel != null ? session.channel.dup() : null), - mCurId, mCurSeq, suppressesSpellChecker); + curId, getSequenceNumber(), suppressesSpellChecker); } @GuardedBy("mMethodMap") @@ -2350,7 +2328,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @NonNull EditorInfo attribute, @StartInputFlags int startInputFlags, @StartInputReason int startInputReason) { // If no method is currently selected, do nothing. - if (mCurMethodId == null) { + String selectedMethodId = getSelectedMethodId(); + if (selectedMethodId == null) { return InputBindResult.NO_IME; } @@ -2359,7 +2338,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // party code. return new InputBindResult( InputBindResult.ResultCode.ERROR_SYSTEM_NOT_READY, - null, null, mCurMethodId, mCurSeq, false); + null, null, selectedMethodId, getSequenceNumber(), false); } if (!InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, cs.uid, @@ -2387,19 +2366,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mImeHiddenByDisplayPolicy = false; if (mCurClient != cs) { - // If the client is changing, we need to switch over to the new - // one. - unbindCurrentClientLocked(UnbindReason.SWITCH_CLIENT); - // If the screen is on, inform the new client it is active - if (mIsInteractive) { - scheduleSetActiveToClient(cs, true /* active */, false /* fullscreen */, - false /* reportToImeController */); - } + prepareClientSwitchLocked(cs); } // Bump up the sequence for this client and attach it. - mCurSeq++; - if (mCurSeq <= 0) mCurSeq = 1; + advanceSequenceNumber(); mCurClient = cs; mCurInputContext = inputContext; mCurAttribute = attribute; @@ -2407,24 +2378,57 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Check if the input method is changing. // We expect the caller has already verified that the client is allowed to access this // display ID. - if (mCurId != null && mCurId.equals(mCurMethodId) - && displayIdToShowIme == mCurTokenDisplayId) { + if (isSelectedMethodBound(displayIdToShowIme)) { if (cs.curSession != null) { // Fast case: if we are already connected to the input method, // then just return it. return attachNewInputLocked(startInputReason, (startInputFlags & StartInputFlags.INITIAL_CONNECTION) != 0); } - if (mHaveConnection) { - if (mCurMethod != null) { - // Return to client, and we will get back with it when - // we have had a session made for it. - requestClientSessionLocked(cs); - return new InputBindResult( - InputBindResult.ResultCode.SUCCESS_WAITING_IME_SESSION, - null, null, mCurId, mCurSeq, false); - } else if (SystemClock.uptimeMillis() - < (mLastBindTime+TIME_TO_RECONNECT)) { + + InputBindResult bindResult = tryReuseConnectionLocked(cs); + if (bindResult != null) { + return bindResult; + } + } + + mBindingController.unbindCurrentMethodLocked(); + + return mBindingController.bindCurrentMethodLocked(displayIdToShowIme); + } + + private boolean isSelectedMethodBound(int displayIdToShowIme) { + String curId = getCurId(); + return curId != null && curId.equals(getSelectedMethodId()) + && displayIdToShowIme == mCurTokenDisplayId; + } + + @GuardedBy("mMethodMap") + private void prepareClientSwitchLocked(ClientState cs) { + // If the client is changing, we need to switch over to the new + // one. + unbindCurrentClientLocked(UnbindReason.SWITCH_CLIENT); + // If the screen is on, inform the new client it is active + if (mIsInteractive) { + scheduleSetActiveToClient(cs, true /* active */, false /* fullscreen */, + false /* reportToImeController */); + } + } + + @GuardedBy("mMethodMap") + @Nullable + private InputBindResult tryReuseConnectionLocked(@NonNull ClientState cs) { + if (hasConnection()) { + if (getCurMethod() != null) { + // Return to client, and we will get back with it when + // we have had a session made for it. + requestClientSessionLocked(cs); + return new InputBindResult( + InputBindResult.ResultCode.SUCCESS_WAITING_IME_SESSION, + null, null, getCurId(), getSequenceNumber(), false); + } else { + long bindingDuration = SystemClock.uptimeMillis() - getLastBindTime(); + if (bindingDuration < TIME_TO_RECONNECT) { // In this case we have connected to the service, but // don't yet have its interface. If it hasn't been too // long since we did the connection, we'll return to @@ -2434,51 +2438,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // to see if we can get back in touch with the service. return new InputBindResult( InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING, - null, null, mCurId, mCurSeq, false); + null, null, getCurId(), getSequenceNumber(), false); } else { EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, - mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0); + getSelectedMethodId(), bindingDuration, 0); } } } - - InputMethodInfo info = mMethodMap.get(mCurMethodId); - if (info == null) { - throw new IllegalArgumentException("Unknown id: " + mCurMethodId); - } - - unbindCurrentMethodLocked(); - - mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE); - mCurIntent.setComponent(info.getComponent()); - mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, - com.android.internal.R.string.input_method_binding_label); - mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( - mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), - PendingIntent.FLAG_IMMUTABLE)); - - if (bindCurrentInputMethodServiceLocked(mCurIntent, this, mImeConnectionBindFlags)) { - mLastBindTime = SystemClock.uptimeMillis(); - mHaveConnection = true; - mCurId = info.getId(); - mCurToken = new Binder(); - mCurTokenDisplayId = displayIdToShowIme; - try { - if (DEBUG) { - Slog.v(TAG, "Adding window token: " + mCurToken + " for display: " - + mCurTokenDisplayId); - } - mIWindowManager.addWindowToken(mCurToken, LayoutParams.TYPE_INPUT_METHOD, - mCurTokenDisplayId, null /* options */); - } catch (RemoteException e) { - } - return new InputBindResult( - InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING, - null, null, mCurId, mCurSeq, false); - } - mCurIntent = null; - Slog.w(TAG, "Failure connecting to input method service: " + mCurIntent); - return InputBindResult.IME_NOT_CONNECTED; + return null; } @FunctionalInterface @@ -2514,46 +2481,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @AnyThread - private void scheduleNotifyImeUidToAudioService(int uid) { + void scheduleNotifyImeUidToAudioService(int uid) { mCaller.removeMessages(MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE); mCaller.obtainMessageI(MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE, uid).sendToTarget(); } - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.onServiceConnected"); - synchronized (mMethodMap) { - if (mCurIntent != null && name.equals(mCurIntent.getComponent())) { - mCurMethod = IInputMethod.Stub.asInterface(service); - final String curMethodPackage = mCurIntent.getComponent().getPackageName(); - final int curMethodUid = mPackageManagerInternal.getPackageUid( - curMethodPackage, 0 /* flags */, mSettings.getCurrentUserId()); - if (curMethodUid < 0) { - Slog.e(TAG, "Failed to get UID for package=" + curMethodPackage); - mCurMethodUid = Process.INVALID_UID; - } else { - mCurMethodUid = curMethodUid; - } - if (mCurToken == null) { - Slog.w(TAG, "Service connected without a token!"); - unbindCurrentMethodLocked(); - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - return; - } - if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken); - // Dispatch display id for InputMethodService to update context display. - executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(MSG_INITIALIZE_IME, - mMethodMap.get(mCurMethodId).getConfigChanges(), mCurMethod, mCurToken)); - scheduleNotifyImeUidToAudioService(mCurMethodUid); - if (mCurClient != null) { - clearClientSessionLocked(mCurClient); - requestClientSessionLocked(mCurClient); - } - } - } - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - } - void onSessionCreated(IInputMethod method, IInputMethodSession session, InputChannel channel) { synchronized (mMethodMap) { @@ -2562,8 +2494,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub channel.dispose(); return; } - if (mCurMethod != null && method != null - && mCurMethod.asBinder() == method.asBinder()) { + IInputMethod curMethod = getCurMethod(); + if (curMethod != null && method != null + && curMethod.asBinder() == method.asBinder()) { if (mCurClient != null) { clearClientSessionLocked(mCurClient); mCurClient.curSession = new SessionState(mCurClient, @@ -2584,53 +2517,40 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @GuardedBy("mMethodMap") - void unbindCurrentMethodLocked() { - if (mVisibleBound) { - mContext.unbindService(mVisibleConnection); - mVisibleBound = false; - } - - if (mHaveConnection) { - mContext.unbindService(this); - mHaveConnection = false; - } - - if (mCurToken != null) { - if (DEBUG) { - Slog.v(TAG, "Removing window token: " + mCurToken + " for display: " - + mCurTokenDisplayId); - } - mWindowManagerInternal.removeWindowToken(mCurToken, false /* removeWindows */, - false /* animateExit */, mCurTokenDisplayId); - // Set IME window status as invisible when unbind current method. - mImeWindowVis = 0; - mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT; - updateSystemUiLocked(mImeWindowVis, mBackDisposition); - mCurToken = null; - mCurTokenDisplayId = INVALID_DISPLAY; - mCurHostInputToken = null; - } - - mCurId = null; - clearCurMethodLocked(); + void resetSystemUiLocked() { + // Set IME window status as invisible when unbinding current method. + mImeWindowVis = 0; + mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT; + updateSystemUiLocked(mImeWindowVis, mBackDisposition); + mCurTokenDisplayId = INVALID_DISPLAY; + mCurHostInputToken = null; } @GuardedBy("mMethodMap") void resetCurrentMethodAndClientLocked(@UnbindReason int unbindClientReason) { - mCurMethodId = null; - unbindCurrentMethodLocked(); + setSelectedMethodId(null); + mBindingController.unbindCurrentMethodLocked(); unbindCurrentClientLocked(unbindClientReason); } @GuardedBy("mMethodMap") + void reRequestCurrentClientSessionLocked() { + if (mCurClient != null) { + clearClientSessionLocked(mCurClient); + requestClientSessionLocked(mCurClient); + } + } + + @GuardedBy("mMethodMap") void requestClientSessionLocked(ClientState cs) { if (!cs.sessionRequested) { if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs); InputChannel[] channels = InputChannel.openInputChannelPair(cs.toString()); cs.sessionRequested = true; - executeOrSendMessage(mCurMethod, mCaller.obtainMessageOOO( - MSG_CREATE_SESSION, mCurMethod, channels[1], - new MethodCallback(this, mCurMethod, channels[0]))); + IInputMethod curMethod = getCurMethod(); + executeOrSendMessage(curMethod, mCaller.obtainMessageOOO( + MSG_CREATE_SESSION, curMethod, channels[1], + new MethodCallback(this, curMethod, channels[0]))); } } @@ -2661,8 +2581,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @GuardedBy("mMethodMap") - void clearCurMethodLocked() { - if (mCurMethod != null) { + void clearClientSessionsLocked() { + if (getCurMethod() != null) { final int numClients = mClients.size(); for (int i = 0; i < numClients; ++i) { clearClientSessionLocked(mClients.valueAt(i)); @@ -2670,41 +2590,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub finishSessionLocked(mEnabledSession); mEnabledSession = null; - mCurMethod = null; - mCurMethodUid = Process.INVALID_UID; - scheduleNotifyImeUidToAudioService(mCurMethodUid); - } - if (mStatusBar != null) { - mStatusBar.setIconVisibility(mSlotIme, false); + mBindingController.clearCurMethodLocked(); + scheduleNotifyImeUidToAudioService(Process.INVALID_UID); } + hideStatusBarIconLocked(); mInFullscreenMode = false; } - @Override - public void onServiceDisconnected(ComponentName name) { - // Note that mContext.unbindService(this) does not trigger this. Hence if we are here the - // disconnection is not intended by IMMS (e.g. triggered because the current IMS crashed), - // which is irregular but can eventually happen for everyone just by continuing using the - // device. Thus it is important to make sure that all the internal states are properly - // refreshed when this method is called back. Running - // adb install -r <APK that implements the current IME> - // would be a good way to trigger such a situation. - synchronized (mMethodMap) { - if (DEBUG) Slog.v(TAG, "Service disconnected: " + name - + " mCurIntent=" + mCurIntent); - if (mCurMethod != null && mCurIntent != null - && name.equals(mCurIntent.getComponent())) { - clearCurMethodLocked(); - // We consider this to be a new bind attempt, since the system - // should now try to restart the service for us. - mLastBindTime = SystemClock.uptimeMillis(); - mShowRequested = mInputShown; - mInputShown = false; - unbindCurrentClientLocked(UnbindReason.DISCONNECT_IME); - } - } - } - @BinderThread private void updateStatusIcon(@NonNull IBinder token, String packageName, @DrawableRes int iconId) { @@ -2716,9 +2608,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub try { if (iconId == 0) { if (DEBUG) Slog.d(TAG, "hide the small icon for the input method"); - if (mStatusBar != null) { - mStatusBar.setIconVisibility(mSlotIme, false); - } + hideStatusBarIconLocked(); } else if (packageName != null) { if (DEBUG) Slog.d(TAG, "show a small icon for the input method"); CharSequence contentDescription = null; @@ -2745,6 +2635,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @GuardedBy("mMethodMap") + private void hideStatusBarIconLocked() { + if (mStatusBar != null) { + mStatusBar.setIconVisibility(mSlotIme, false); + } + } + + @GuardedBy("mMethodMap") private boolean shouldShowImeSwitcherLocked(int visibility) { if (!mShowOngoingImeSwitcherForPhones) return false; if (mMenuController.getSwitchingDialogLocked() != null) return false; @@ -2808,11 +2705,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return false; } - @GuardedBy("mMethodMap") - private boolean isKeyguardLocked() { - return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked(); - } - @BinderThread @SuppressWarnings("deprecation") private void setImeWindowStatus(@NonNull IBinder token, int vis, int backDisposition) { @@ -2883,7 +2775,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Caution! This method is called in this class. Handle multi-user carefully @GuardedBy("mMethodMap") private void updateSystemUiLocked(int vis, int backDisposition) { - if (mCurToken == null) { + if (getCurToken() == null) { return; } if (DEBUG) { @@ -2903,10 +2795,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // mImeWindowVis should be updated before calling shouldShowImeSwitcherLocked(). final boolean needsToShowImeSwitcher = shouldShowImeSwitcherLocked(vis); if (mStatusBar != null) { - mStatusBar.setImeWindowStatus(mCurTokenDisplayId, mCurToken, vis, backDisposition, - needsToShowImeSwitcher); + mStatusBar.setImeWindowStatus(mCurTokenDisplayId, getCurToken(), vis, + backDisposition, needsToShowImeSwitcher); } - final InputMethodInfo imi = mMethodMap.get(mCurMethodId); + final InputMethodInfo imi = mMethodMap.get(getSelectedMethodId()); if (imi != null && needsToShowImeSwitcher) { // Used to load label final CharSequence title = mRes.getText( @@ -3014,7 +2906,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } // See if we need to notify a subtype change within the same IME. - if (id.equals(mCurMethodId)) { + if (id.equals(getSelectedMethodId())) { final int subtypeCount = info.getSubtypeCount(); if (subtypeCount <= 0) { return; @@ -3035,10 +2927,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } if (newSubtype != oldSubtype) { setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true); - if (mCurMethod != null) { + IInputMethod curMethod = getCurMethod(); + if (curMethod != null) { try { updateSystemUiLocked(mImeWindowVis, mBackDisposition); - mCurMethod.changeInputMethodSubtype(newSubtype); + curMethod.changeInputMethodSubtype(newSubtype); } catch (RemoteException e) { Slog.w(TAG, "Failed to call changeInputMethodSubtype"); } @@ -3056,7 +2949,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // mCurMethodId should be updated after setSelectedInputMethodAndSubtypeLocked() // because mCurMethodId is stored as a history in // setSelectedInputMethodAndSubtypeLocked(). - mCurMethodId = id; + setSelectedMethodId(id); if (LocalServices.getService(ActivityManagerInternal.class).isSystemReady()) { Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED); @@ -3150,35 +3043,37 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } boolean res = false; - if (mCurMethod != null) { - if (DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + mCurToken); + IInputMethod curMethod = getCurMethod(); + if (curMethod != null) { + if (DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + getCurToken()); // create a placeholder token for IMS so that IMS cannot inject windows into client app. Binder showInputToken = new Binder(); mShowRequestWindowMap.put(showInputToken, windowToken); - executeOrSendMessage(mCurMethod, mCaller.obtainMessageIIOOO(MSG_SHOW_SOFT_INPUT, - getImeShowFlagsLocked(), reason, mCurMethod, resultReceiver, showInputToken)); + executeOrSendMessage(curMethod, mCaller.obtainMessageIIOOO(MSG_SHOW_SOFT_INPUT, + getImeShowFlagsLocked(), reason, curMethod, resultReceiver, + showInputToken)); mInputShown = true; - if (mHaveConnection && !mVisibleBound) { - bindCurrentInputMethodServiceLocked( - mCurIntent, mVisibleConnection, IME_VISIBLE_BIND_FLAGS); - mVisibleBound = true; + if (hasConnection() && !isVisibleBound()) { + mBindingController.bindCurrentInputMethodServiceVisibleConnectionLocked(); } res = true; - } else if (mHaveConnection && SystemClock.uptimeMillis() - >= (mLastBindTime+TIME_TO_RECONNECT)) { - // The client has asked to have the input method shown, but - // we have been sitting here too long with a connection to the - // service and no interface received, so let's disconnect/connect - // to try to prod things along. - EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId, - SystemClock.uptimeMillis()-mLastBindTime,1); - Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()"); - mContext.unbindService(this); - bindCurrentInputMethodServiceLocked(mCurIntent, this, mImeConnectionBindFlags); } else { - if (DEBUG) { - Slog.d(TAG, "Can't show input: connection = " + mHaveConnection + ", time = " - + ((mLastBindTime+TIME_TO_RECONNECT) - SystemClock.uptimeMillis())); + long bindingDuration = SystemClock.uptimeMillis() - getLastBindTime(); + if (hasConnection() && bindingDuration >= TIME_TO_RECONNECT) { + // The client has asked to have the input method shown, but + // we have been sitting here too long with a connection to the + // service and no interface received, so let's disconnect/connect + // to try to prod things along. + EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, getSelectedMethodId(), + bindingDuration, 1); + Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()"); + mBindingController.unbindMainConnectionLocked(); + mBindingController.bindCurrentInputMethodServiceMainConnectionLocked(); + } else { + if (DEBUG) { + Slog.d(TAG, "Can't show input: connection = " + hasConnection() + ", time = " + + (TIME_TO_RECONNECT - bindingDuration)); + } } } @@ -3249,7 +3144,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // since Android Eclair. That's why we need to accept IMM#hideSoftInput() even when only // IMMS#InputShown indicates that the software keyboard is shown. // TODO: Clean up, IMMS#mInputShown, IMMS#mImeWindowVis and mShowRequested. - final boolean shouldHideSoftInput = (mCurMethod != null) && (mInputShown + IInputMethod curMethod = getCurMethod(); + final boolean shouldHideSoftInput = (curMethod != null) && (mInputShown || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0); boolean res; if (shouldHideSoftInput) { @@ -3259,15 +3155,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // delivered to the IME process as an IPC. Hence the inconsistency between // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in // the final state. - executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOOO(MSG_HIDE_SOFT_INPUT, - reason, mCurMethod, resultReceiver, hideInputToken)); + executeOrSendMessage(curMethod, mCaller.obtainMessageIOOO(MSG_HIDE_SOFT_INPUT, + reason, curMethod, resultReceiver, hideInputToken)); res = true; } else { res = false; } - if (mHaveConnection && mVisibleBound) { - mContext.unbindService(mVisibleConnection); - mVisibleBound = false; + if (hasConnection() && isVisibleBound()) { + mBindingController.unbindVisibleConnectionLocked(); } mInputShown = false; mShowRequested = false; @@ -3507,7 +3402,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Note that we can trust client's display ID as long as it matches // to the display ID obtained from the window. if (cs.selfReportedDisplayId != mCurTokenDisplayId) { - unbindCurrentMethodLocked(); + mBindingController.unbindCurrentMethodLocked(); } } } else if (isTextEditor && doAutoShow @@ -3633,10 +3528,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (mCurFocusedWindowClient != null && client != null && mCurFocusedWindowClient.client.asBinder() == client.asBinder()) { return true; - } else if (mCurIntent != null && InputMethodUtils.checkIfPackageBelongsToUid( + } else if (getCurIntent() != null && InputMethodUtils.checkIfPackageBelongsToUid( mAppOpsManager, uid, - mCurIntent.getComponent().getPackageName())) { + getCurIntent().getComponent().getPackageName())) { return true; } return false; @@ -3722,7 +3617,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (!calledFromValidUserLocked()) { return; } - executeOrSendMessage(mCurMethod, mCaller.obtainMessageO( + executeOrSendMessage(getCurMethod(), mCaller.obtainMessageO( MSG_SHOW_IM_SUBTYPE_ENABLER, inputMethodId)); } } @@ -3743,7 +3638,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub String targetLastImiId = null; int subtypeId = NOT_A_SUBTYPE_ID; if (lastIme != null && lastImi != null) { - final boolean imiIdIsSame = lastImi.getId().equals(mCurMethodId); + final boolean imiIdIsSame = lastImi.getId().equals(getSelectedMethodId()); final int lastSubtypeHash = Integer.parseInt(lastIme.second); final int currentSubtypeHash = mCurrentSubtype == null ? NOT_A_SUBTYPE_ID : mCurrentSubtype.hashCode(); @@ -3789,7 +3684,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (!TextUtils.isEmpty(targetLastImiId)) { if (DEBUG) { Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second - + ", from: " + mCurMethodId + ", " + subtypeId); + + ", from: " + getSelectedMethodId() + ", " + subtypeId); } setInputMethodWithSubtypeIdLocked(token, targetLastImiId, subtypeId); return true; @@ -3806,7 +3701,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return false; } final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked( - onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype); + onlyCurrentIme, mMethodMap.get(getSelectedMethodId()), mCurrentSubtype); if (nextSubtype == null) { return false; } @@ -3823,7 +3718,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return false; } final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked( - false /* onlyCurrentIme */, mMethodMap.get(mCurMethodId), mCurrentSubtype); + false /* onlyCurrentIme */, mMethodMap.get(getSelectedMethodId()), + mCurrentSubtype); if (nextSubtype == null) { return false; } @@ -4037,8 +3933,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private void dumpDebug(ProtoOutputStream proto, long fieldId) { synchronized (mMethodMap) { final long token = proto.start(fieldId); - proto.write(CUR_METHOD_ID, mCurMethodId); - proto.write(CUR_SEQ, mCurSeq); + proto.write(CUR_METHOD_ID, getSelectedMethodId()); + proto.write(CUR_SEQ, getSequenceNumber()); proto.write(CUR_CLIENT, Objects.toString(mCurClient)); proto.write(CUR_FOCUSED_WINDOW_NAME, mWindowManagerInternal.getWindowName(mCurFocusedWindow)); @@ -4049,17 +3945,17 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (mCurAttribute != null) { mCurAttribute.dumpDebug(proto, CUR_ATTRIBUTE); } - proto.write(CUR_ID, mCurId); + proto.write(CUR_ID, getCurId()); proto.write(SHOW_REQUESTED, mShowRequested); proto.write(SHOW_EXPLICITLY_REQUESTED, mShowExplicitlyRequested); proto.write(SHOW_FORCED, mShowForced); proto.write(INPUT_SHOWN, mInputShown); proto.write(IN_FULLSCREEN_MODE, mInFullscreenMode); - proto.write(CUR_TOKEN, Objects.toString(mCurToken)); + proto.write(CUR_TOKEN, Objects.toString(getCurToken())); proto.write(CUR_TOKEN_DISPLAY_ID, mCurTokenDisplayId); proto.write(SYSTEM_READY, mSystemReady); proto.write(LAST_SWITCH_USER_ID, mLastSwitchUserId); - proto.write(HAVE_CONNECTION, mHaveConnection); + proto.write(HAVE_CONNECTION, hasConnection()); proto.write(BOUND_TO_METHOD, mBoundToMethod); proto.write(IS_INTERACTIVE, mIsInteractive); proto.write(BACK_DISPOSITION, mBackDisposition); @@ -4077,14 +3973,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Slog.d(TAG, "Got the notification of a user action."); } synchronized (mMethodMap) { - if (mCurToken != token) { + if (getCurToken() != token) { if (DEBUG) { Slog.d(TAG, "Ignoring the user action notification from IMEs that are no longer" + " active."); } return; } - final InputMethodInfo imi = mMethodMap.get(mCurMethodId); + final InputMethodInfo imi = mMethodMap.get(getSelectedMethodId()); if (imi != null) { mSwitchingController.onUserActionLocked(imi, mCurrentSubtype); } @@ -4128,7 +4024,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub "Using null token requires permission " + android.Manifest.permission.WRITE_SECURE_SETTINGS); } - } else if (mCurToken != token) { + } else if (getCurToken() != token) { Slog.w(TAG, "Ignoring setInputMethod of uid " + Binder.getCallingUid() + " token: " + token); return; @@ -4500,7 +4396,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub boolean reportToImeController = false; try { reportToImeController = mPlatformCompat.isChangeEnabledByUid( - FINISH_INPUT_NO_FALLBACK_CONNECTION, mCurMethodUid); + FINISH_INPUT_NO_FALLBACK_CONNECTION, getCurMethodUid()); } catch (RemoteException e) { } scheduleSetActiveToClient(mCurClient, mIsInteractive, mInFullscreenMode, @@ -4790,7 +4686,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("mMethodMap") private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId, boolean setSubtypeOnly) { - mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype); + mSettings.saveCurrentInputMethodAndSubtypeToHistory(getSelectedMethodId(), mCurrentSubtype); // Set Subtype here if (imi == null || subtypeId < 0) { @@ -4849,17 +4745,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("mMethodMap") InputMethodSubtype getCurrentInputMethodSubtypeLocked() { - if (mCurMethodId == null) { + String selectedMethodId = getSelectedMethodId(); + if (selectedMethodId == null) { return null; } final boolean subtypeIsSelected = mSettings.isSubtypeSelected(); - final InputMethodInfo imi = mMethodMap.get(mCurMethodId); + final InputMethodInfo imi = mMethodMap.get(selectedMethodId); if (imi == null || imi.getSubtypeCount() == 0) { return null; } if (!subtypeIsSelected || mCurrentSubtype == null || !InputMethodUtils.isValidSubtypeId(imi, mCurrentSubtype.hashCode())) { - int subtypeId = mSettings.getSelectedInputMethodSubtypeId(mCurMethodId); + int subtypeId = mSettings.getSelectedInputMethodSubtypeId(selectedMethodId); if (subtypeId == NOT_A_SUBTYPE_ID) { // If there are no selected subtypes, the framework will try to find // the most applicable subtype from explicitly or implicitly enabled @@ -4889,7 +4786,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @Nullable String getCurrentMethodId() { - return mCurMethodId; + return getSelectedMethodId(); } private List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) { @@ -5063,11 +4960,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub synchronized (mMethodMap) { final int uid = Binder.getCallingUid(); - if (mCurMethodId == null) { + if (getSelectedMethodId() == null) { return null; } - if (mCurToken != token) { - Slog.e(TAG, "Ignoring createInputContentUriToken mCurToken=" + mCurToken + if (getCurToken() != token) { + Slog.e(TAG, "Ignoring createInputContentUriToken mCurToken=" + getCurToken() + " token=" + token); return null; } @@ -5202,23 +5099,23 @@ public class InputMethodManagerService extends IInputMethodManager.Stub p.println(" sessionRequested=" + ci.sessionRequested); p.println(" curSession=" + ci.curSession); } - p.println(" mCurMethodId=" + mCurMethodId); + p.println(" mCurMethodId=" + getSelectedMethodId()); client = mCurClient; - p.println(" mCurClient=" + client + " mCurSeq=" + mCurSeq); + p.println(" mCurClient=" + client + " mCurSeq=" + getSequenceNumber()); p.println(" mCurPerceptible=" + mCurPerceptible); p.println(" mCurFocusedWindow=" + mCurFocusedWindow + " softInputMode=" + InputMethodDebug.softInputModeToString(mCurFocusedWindowSoftInputMode) + " client=" + mCurFocusedWindowClient); focusedWindowClient = mCurFocusedWindowClient; - p.println(" mCurId=" + mCurId + " mHaveConnection=" + mHaveConnection - + " mBoundToMethod=" + mBoundToMethod + " mVisibleBound=" + mVisibleBound); - p.println(" mCurToken=" + mCurToken); + p.println(" mCurId=" + getCurId() + " mHaveConnection=" + hasConnection() + + " mBoundToMethod=" + mBoundToMethod + " mVisibleBound=" + isVisibleBound()); + p.println(" mCurToken=" + getCurToken()); p.println(" mCurTokenDisplayId=" + mCurTokenDisplayId); p.println(" mCurHostInputToken=" + mCurHostInputToken); - p.println(" mCurIntent=" + mCurIntent); - method = mCurMethod; - p.println(" mCurMethod=" + mCurMethod); + p.println(" mCurIntent=" + getCurIntent()); + method = getCurMethod(); + p.println(" mCurMethod=" + getCurMethod()); p.println(" mEnabledSession=" + mEnabledSession); p.println(" mShowRequested=" + mShowRequested + " mShowExplicitlyRequested=" + mShowExplicitlyRequested @@ -5724,7 +5621,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (userId == mSettings.getCurrentUserId()) { hideCurrentInputLocked(mCurFocusedWindow, 0, null, SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND); - unbindCurrentMethodLocked(); + mBindingController.unbindCurrentMethodLocked(); // Reset the current IME resetSelectedInputMethodAndSubtypeLocked(null); // Also reset the settings of the current IME diff --git a/services/core/java/com/android/server/locales/LocaleManagerService.java b/services/core/java/com/android/server/locales/LocaleManagerService.java index ffeaad173fca..457c2fd6fc41 100644 --- a/services/core/java/com/android/server/locales/LocaleManagerService.java +++ b/services/core/java/com/android/server/locales/LocaleManagerService.java @@ -154,10 +154,10 @@ public class LocaleManagerService extends SystemService { final ActivityTaskManagerInternal.PackageConfigurationUpdater updater = mActivityTaskManagerInternal.createPackageConfigurationUpdater(appPackageName, userId); - boolean isSuccess = updater.setLocales(locales).commit(); + boolean isConfigChanged = updater.setLocales(locales).commit(); //We want to send the broadcasts only if config was actually updated on commit. - if (isSuccess) { + if (isConfigChanged) { notifyAppWhoseLocaleChanged(appPackageName, userId, locales); notifyInstallerOfAppWhoseLocaleChanged(appPackageName, userId, locales); notifyRegisteredReceivers(appPackageName, userId, locales); diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index 14f521407774..d4af681b97b5 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -101,6 +101,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub // State guarded by mLock. private final Object mLock = new Object(); + private final SparseArray<UserRecord> mUserRecords = new SparseArray<>(); private final ArrayMap<IBinder, ClientRecord> mAllClientRecords = new ArrayMap<>(); private int mCurrentUserId = -1; @@ -351,9 +352,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub final long token = Binder.clearCallingIdentity(); try { - synchronized (mLock) { - mAudioService.setBluetoothA2dpOn(on); - } + mAudioService.setBluetoothA2dpOn(on); } catch (RemoteException ex) { Slog.w(TAG, "RemoteException while calling setBluetoothA2dpOn. on=" + on); } finally { diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index e4ed0e5d4186..4822d6a62ac7 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -291,35 +291,39 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR asSystemService, useSuggested, previousFlagPlaySound); } else { if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) { - // Nothing to do, the volume cannot be changed - return; - } - if (direction == AudioManager.ADJUST_TOGGLE_MUTE + if (DEBUG) { + Log.d(TAG, "Session does not support volume adjustment"); + } + } else if (direction == AudioManager.ADJUST_TOGGLE_MUTE || direction == AudioManager.ADJUST_MUTE || direction == AudioManager.ADJUST_UNMUTE) { Log.w(TAG, "Muting remote playback is not supported"); - return; - } - if (DEBUG) { - Log.w(TAG, "adjusting volume, pkg=" + packageName + ", asSystemService=" - + asSystemService + ", dir=" + direction); - } - mSessionCb.adjustVolume(packageName, pid, uid, asSystemService, direction); + } else { + if (DEBUG) { + Log.w(TAG, "adjusting volume, pkg=" + packageName + ", asSystemService=" + + asSystemService + ", dir=" + direction); + } + mSessionCb.adjustVolume(packageName, pid, uid, asSystemService, direction); + + int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume); + mOptimisticVolume = volumeBefore + direction; + mOptimisticVolume = Math.max(0, Math.min(mOptimisticVolume, mMaxVolume)); + mHandler.removeCallbacks(mClearOptimisticVolumeRunnable); + mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT); + if (volumeBefore != mOptimisticVolume) { + pushVolumeUpdate(); + } - int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume); - mOptimisticVolume = volumeBefore + direction; - mOptimisticVolume = Math.max(0, Math.min(mOptimisticVolume, mMaxVolume)); - mHandler.removeCallbacks(mClearOptimisticVolumeRunnable); - mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT); - if (volumeBefore != mOptimisticVolume) { - pushVolumeUpdate(); + if (DEBUG) { + Log.d(TAG, "Adjusted optimistic volume to " + mOptimisticVolume + " max is " + + mMaxVolume); + } } + // Always notify, even if the volume hasn't changed. This is important to ensure that + // System UI receives an event if a hardware volume key is pressed but the session that + // handles it does not allow volume adjustment. Without such an event, System UI would + // not show volume controls to the user. mService.notifyRemoteVolumeChanged(flags, this); - - if (DEBUG) { - Log.d(TAG, "Adjusted optimistic volume to " + mOptimisticVolume + " max is " - + mMaxVolume); - } } } @@ -343,25 +347,28 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR }); } else { if (mVolumeControlType != VolumeProvider.VOLUME_CONTROL_ABSOLUTE) { - // Nothing to do. The volume can't be set directly. - return; - } - value = Math.max(0, Math.min(value, mMaxVolume)); - mSessionCb.setVolumeTo(packageName, pid, uid, value); + if (DEBUG) { + Log.d(TAG, "Session does not support setting volume"); + } + } else { + value = Math.max(0, Math.min(value, mMaxVolume)); + mSessionCb.setVolumeTo(packageName, pid, uid, value); + + int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume); + mOptimisticVolume = Math.max(0, Math.min(value, mMaxVolume)); + mHandler.removeCallbacks(mClearOptimisticVolumeRunnable); + mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT); + if (volumeBefore != mOptimisticVolume) { + pushVolumeUpdate(); + } - int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume); - mOptimisticVolume = Math.max(0, Math.min(value, mMaxVolume)); - mHandler.removeCallbacks(mClearOptimisticVolumeRunnable); - mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT); - if (volumeBefore != mOptimisticVolume) { - pushVolumeUpdate(); + if (DEBUG) { + Log.d(TAG, "Set optimistic volume to " + mOptimisticVolume + " max is " + + mMaxVolume); + } } + // Always notify, even if the volume hasn't changed. mService.notifyRemoteVolumeChanged(flags, this); - - if (DEBUG) { - Log.d(TAG, "Set optimistic volume to " + mOptimisticVolume + " max is " - + mMaxVolume); - } } } diff --git a/services/core/java/com/android/server/notification/BadgeExtractor.java b/services/core/java/com/android/server/notification/BadgeExtractor.java index 70edfa171356..642cbb324229 100644 --- a/services/core/java/com/android/server/notification/BadgeExtractor.java +++ b/services/core/java/com/android/server/notification/BadgeExtractor.java @@ -69,11 +69,8 @@ public class BadgeExtractor implements NotificationSignalExtractor { if (mConfig.isMediaNotificationFilteringEnabled()) { final Notification notif = record.getNotification(); - if (notif.hasMediaSession()) { - if (notif.isStyle(Notification.DecoratedMediaCustomViewStyle.class) - || notif.isStyle(Notification.MediaStyle.class)) { - record.setShowBadge(false); - } + if (notif.isMediaNotification()) { + record.setShowBadge(false); } } return null; diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java index 8aae6e09bd31..583cdd599780 100644 --- a/services/core/java/com/android/server/notification/NotificationComparator.java +++ b/services/core/java/com/android/server/notification/NotificationComparator.java @@ -179,7 +179,7 @@ public class NotificationComparator } private boolean isMediaNotification(NotificationRecord record) { - return record.getNotification().hasMediaSession(); + return record.getNotification().isMediaNotification(); } private boolean isCallCategory(NotificationRecord record) { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index bde554323a73..e117cc6f7a22 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -6822,13 +6822,11 @@ public class NotificationManagerService extends SystemService { // blocked apps - boolean isMediaNotification = n.isMediaNotification() - && n.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) != null; boolean isBlocked = !areNotificationsEnabledForPackageInt(pkg, uid); synchronized (mNotificationLock) { isBlocked |= isRecordBlockedLocked(r); } - if (isBlocked && !isMediaNotification) { + if (isBlocked && !n.isMediaNotification()) { if (DBG) { Slog.e(TAG, "Suppressing notification from package " + r.getSbn().getPackageName() + " by user request."); @@ -7217,10 +7215,8 @@ public class NotificationManagerService extends SystemService { final StatusBarNotification n = r.getSbn(); final Notification notification = n.getNotification(); - boolean isMediaNotification = notification.isMediaNotification() - && notification.extras.getParcelable( - Notification.EXTRA_MEDIA_SESSION) != null; - if (!isMediaNotification && (appBanned || isRecordBlockedLocked(r))) { + if (!notification.isMediaNotification() + && (appBanned || isRecordBlockedLocked(r))) { mUsageStats.registerBlocked(r); if (DBG) { Slog.e(TAG, "Suppressing notification from package " + pkg); diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java index 6f619583b876..a9df4bab6fd8 100644 --- a/services/core/java/com/android/server/pm/Computer.java +++ b/services/core/java/com/android/server/pm/Computer.java @@ -514,6 +514,11 @@ public interface Computer { int getComponentEnabledSetting(@NonNull ComponentName component, int callingUid, @UserIdInt int userId); + @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) + @PackageManager.EnabledState + int getComponentEnabledSettingInternal(@NonNull ComponentName component, int callingUid, + @UserIdInt int userId); + /** * @return true if the runtime app user enabled state, runtime component user enabled state, * install-time app manifest enabled state, and install-time component manifest enabled state @@ -612,6 +617,10 @@ public interface Computer { @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) int getUidTargetSdkVersion(int uid); + /** + * @see PackageManagerInternal#getProcessesForUid(int) + */ + @Computer.LiveImplementation(override = LiveImplementation.MANDATORY) @Nullable ArrayMap<String, ProcessInfo> getProcessesForUid(int uid); // End block diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index 996509788637..887dfff41384 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -5015,20 +5015,26 @@ public class ComputerEngine implements Computer { @UserIdInt int userId) { enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/, false /*checkShell*/, "getComponentEnabled"); + return getComponentEnabledSettingInternal(component, callingUid, userId); + } + @PackageManager.EnabledState + @Override + public int getComponentEnabledSettingInternal(@NonNull ComponentName component, int callingUid, + @UserIdInt int userId) { if (component == null) return COMPONENT_ENABLED_STATE_DEFAULT; if (!mUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED; - try { - if (shouldFilterApplication( - mSettings.getPackage(component.getPackageName()), callingUid, - component, TYPE_UNKNOWN, userId)) { - throw new PackageManager.NameNotFoundException(component.getPackageName()); - } - return mSettings.getComponentEnabledSetting(component, userId); - } catch (PackageManager.NameNotFoundException e) { - throw new IllegalArgumentException("Unknown component: " + component); + try { + if (shouldFilterApplication( + mSettings.getPackage(component.getPackageName()), callingUid, + component, TYPE_UNKNOWN, userId)) { + throw new PackageManager.NameNotFoundException(component.getPackageName()); } + return mSettings.getComponentEnabledSetting(component, userId); + } catch (PackageManager.NameNotFoundException e) { + throw new IllegalArgumentException("Unknown component: " + component); + } } @Override diff --git a/services/core/java/com/android/server/pm/ComputerLocked.java b/services/core/java/com/android/server/pm/ComputerLocked.java index d234d4dde3f9..801aaeff8ada 100644 --- a/services/core/java/com/android/server/pm/ComputerLocked.java +++ b/services/core/java/com/android/server/pm/ComputerLocked.java @@ -650,6 +650,14 @@ public final class ComputerLocked extends ComputerEngine { } @Override + public int getComponentEnabledSettingInternal(@NonNull ComponentName component, int callingUid, + @UserIdInt int userId) { + synchronized (mLock) { + return super.getComponentEnabledSettingInternal(component, callingUid, userId); + } + } + + @Override public boolean isComponentEffectivelyEnabled(@NonNull ComponentInfo componentInfo, @UserIdInt int userId) { synchronized (mLock) { diff --git a/services/core/java/com/android/server/pm/ComputerTracker.java b/services/core/java/com/android/server/pm/ComputerTracker.java index 37298cd52f75..ca17d66f4e25 100644 --- a/services/core/java/com/android/server/pm/ComputerTracker.java +++ b/services/core/java/com/android/server/pm/ComputerTracker.java @@ -1090,6 +1090,15 @@ public final class ComputerTracker implements Computer { } @Override + public int getComponentEnabledSettingInternal(@NonNull ComponentName component, int callingUid, + @UserIdInt int userId) { + try (ThreadComputer current = snapshot()) { + return current.mComputer.getComponentEnabledSettingInternal( + component, callingUid, userId); + } + } + + @Override public boolean isComponentEffectivelyEnabled(@NonNull ComponentInfo componentInfo, @UserIdInt int userId) { try (ThreadComputer current = snapshot()) { diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 39ed9c2d51d3..861fec7cc236 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -2349,10 +2349,9 @@ final class InstallPackageHelper { // Set install reason for users that are having the package newly installed. final int[] allUsersList = mPm.mUserManager.getUserIds(); if (userId == UserHandle.USER_ALL) { - // TODO(b/152629990): It appears that the package doesn't actually get newly - // installed in this case, so the installReason shouldn't get modified? for (int currentUserId : allUsersList) { - if (!previousUserIds.contains(currentUserId)) { + if (!previousUserIds.contains(currentUserId) + && ps.getInstalled(currentUserId)) { ps.setInstallReason(installReason, currentUserId); } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index c47ca4b45ab3..803a2833dc3c 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -558,10 +558,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { Slog.d(TAG, "Marking session " + sessionId + " as failed: " + errorMessage); childSessions = getChildSessionsLocked(); } - destroyInternal(); - for (PackageInstallerSession child : childSessions) { - child.destroyInternal(); - } + destroy(); mCallback.onStagedSessionChanged(PackageInstallerSession.this); } @@ -579,10 +576,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { Slog.d(TAG, "Marking session " + sessionId + " as applied"); childSessions = getChildSessionsLocked(); } - destroyInternal(); - for (PackageInstallerSession child : childSessions) { - child.destroyInternal(); - } + destroy(); mCallback.onStagedSessionChanged(PackageInstallerSession.this); } @@ -2111,18 +2105,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private void onSessionVerificationFailure(int error, String msg) { final String msgWithErrorCode = PackageManager.installStatusToString(error, msg); Slog.e(TAG, "Failed to verify session " + sessionId + " [" + msgWithErrorCode + "]"); - // Session is sealed and committed but could not be verified, we need to destroy it. - destroyInternal(); - if (isMultiPackage()) { - for (PackageInstallerSession childSession : getChildSessions()) { - childSession.destroyInternal(); - } - } if (isStaged()) { + // This will clean up the session when it reaches the terminal state mStagedSession.setSessionFailed( SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, msgWithErrorCode); mStagedSession.notifyEndPreRebootVerification(); } else { + // Session is sealed and committed but could not be verified, we need to destroy it. + destroy(); // Dispatch message to remove session from PackageInstallerService. dispatchSessionFinished(error, msg, null); } @@ -4265,6 +4255,28 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return params.isStaged ? mStagedSession.getSessionErrorMessage() : ""; } + /** + * Free up storage used by this session and its children. + * Must not be called on a child session. + */ + private void destroy() { + // TODO(b/173194203): destroy() is called indirectly by + // PackageInstallerService#restoreAndApplyStagedSessionIfNeeded on an orphan child session. + // Enable this assertion when we figure out a better way to clean up orphan sessions. + // assertNotChild("destroy"); + + // TODO(b/173194203): destroyInternal() should be used by destroy() only. + // For the sake of consistency, a session should be destroyed as a whole. The caller + // should always call destroy() for cleanup without knowing it has child sessions or not. + destroyInternal(); + for (PackageInstallerSession child : getChildSessions()) { + child.destroyInternal(); + } + } + + /** + * Free up storage used by this session. + */ private void destroyInternal() { final IncrementalFileStorages incrementalFileStorages; synchronized (mLock) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 5f56d4e10036..747bbfa57bd1 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1500,16 +1500,19 @@ public class PackageManagerService extends IPackageManager.Stub final CompatChange.ChangeListener selinuxChangeListener = packageName -> { synchronized (m.mInstallLock) { final AndroidPackage pkg; + final PackageSetting ps; final SharedUserSetting sharedUser; final String oldSeInfo; - final PackageStateInternal packageState = m.getPackageStateInternal(packageName); - if (packageState == null) { - Slog.e(TAG, "Failed to find package setting " + packageName); - return; + synchronized (m.mLock) { + ps = m.mSettings.getPackageLPr(packageName); + if (ps == null) { + Slog.e(TAG, "Failed to find package setting " + packageName); + return; + } + pkg = ps.getPkg(); + sharedUser = ps.getSharedUser(); + oldSeInfo = AndroidPackageUtils.getSeInfo(pkg, ps); } - pkg = packageState.getPkg(); - sharedUser = packageState.getSharedUser(); - oldSeInfo = AndroidPackageUtils.getSeInfo(pkg, packageState); if (pkg == null) { Slog.e(TAG, "Failed to find package " + packageName); @@ -1521,7 +1524,7 @@ public class PackageManagerService extends IPackageManager.Stub if (!newSeInfo.equals(oldSeInfo)) { Slog.i(TAG, "Updating seInfo for package " + packageName + " from: " + oldSeInfo + " to: " + newSeInfo); - packageState.getTransientState().setOverrideSeInfo(newSeInfo); + ps.getPkgState().setOverrideSeInfo(newSeInfo); m.mAppDataHelper.prepareAppDataAfterInstallLIF(pkg); } } @@ -5646,6 +5649,9 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { mInstantAppRegistry.deleteInstantApplicationMetadataLPw( packageName, userId); + if (succeeded) { + resetComponentEnabledSettingsIfNeededLPw(packageName, userId); + } } } if (succeeded) { @@ -5722,6 +5728,62 @@ public class PackageManagerService extends IPackageManager.Stub } /** + * Update component enabled settings to {@link PackageManager#COMPONENT_ENABLED_STATE_DEFAULT} + * if the resetEnabledSettingsOnAppDataCleared is {@code true}. + */ + private void resetComponentEnabledSettingsIfNeededLPw(String packageName, int userId) { + final AndroidPackage pkg = packageName != null ? mPackages.get(packageName) : null; + if (pkg == null || !pkg.isResetEnabledSettingsOnAppDataCleared()) { + return; + } + final PackageSetting pkgSetting = mSettings.getPackageLPr(packageName); + if (pkgSetting == null) { + return; + } + final ArrayList<String> updatedComponents = new ArrayList<>(); + final Consumer<? super ParsedMainComponent> resetSettings = (component) -> { + if (pkgSetting.restoreComponentLPw(component.getClassName(), userId)) { + updatedComponents.add(component.getClassName()); + } + }; + for (int i = 0; i < pkg.getActivities().size(); i++) { + resetSettings.accept(pkg.getActivities().get(i)); + } + for (int i = 0; i < pkg.getReceivers().size(); i++) { + resetSettings.accept(pkg.getReceivers().get(i)); + } + for (int i = 0; i < pkg.getServices().size(); i++) { + resetSettings.accept(pkg.getServices().get(i)); + } + for (int i = 0; i < pkg.getProviders().size(); i++) { + resetSettings.accept(pkg.getProviders().get(i)); + } + if (ArrayUtils.isEmpty(updatedComponents)) { + // nothing changed + return; + } + + updateSequenceNumberLP(pkgSetting, new int[] { userId }); + updateInstantAppInstallerLocked(packageName); + scheduleWritePackageRestrictionsLocked(userId); + + final ArrayList<String> pendingComponents = mPendingBroadcasts.get(userId, packageName); + if (pendingComponents == null) { + mPendingBroadcasts.put(userId, packageName, updatedComponents); + } else { + for (int i = 0; i < updatedComponents.size(); i++) { + final String updatedComponent = updatedComponents.get(i); + if (!pendingComponents.contains(updatedComponent)) { + pendingComponents.add(updatedComponent); + } + } + } + if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) { + mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY); + } + } + + /** * Remove entries from the keystore daemon. Will only remove it if the * {@code appId} is valid. */ @@ -6789,24 +6851,24 @@ public class PackageManagerService extends IPackageManager.Stub } enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, true /* checkShell */, "stop package"); - boolean shouldUnhibernate = false; // writer synchronized (mLock) { final PackageSetting ps = mSettings.getPackageLPr(packageName); - if (ps != null && ps.getStopped(userId) && !stopped) { - shouldUnhibernate = true; - } if (!shouldFilterApplication(ps, callingUid, userId) && mSettings.setPackageStoppedStateLPw(this, packageName, stopped, userId)) { scheduleWritePackageRestrictionsLocked(userId); } } - if (shouldUnhibernate) { + // If this would cause the app to leave force-stop, then also make sure to unhibernate the + // app if needed. + if (!stopped) { mHandler.post(() -> { AppHibernationManagerInternal ah = mInjector.getLocalService(AppHibernationManagerInternal.class); - ah.setHibernatingForUser(packageName, userId, false); - ah.setHibernatingGlobally(packageName, false); + if (ah != null && ah.isHibernatingForUser(packageName, userId)) { + ah.setHibernatingForUser(packageName, userId, false); + ah.setHibernatingGlobally(packageName, false); + } }); } } @@ -8195,8 +8257,8 @@ public class PackageManagerService extends IPackageManager.Stub @Override public @PackageManager.EnabledState int getComponentEnabledSetting( @NonNull ComponentName componentName, int callingUid, int userId) { - return PackageManagerService.this.mComputer.getComponentEnabledSetting(componentName, - callingUid, userId); + return PackageManagerService.this.mComputer.getComponentEnabledSettingInternal( + componentName, callingUid, userId); } @Override diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index d2134696e861..6d031dd1c20d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -67,6 +67,7 @@ import android.stats.storage.StorageEnums; import android.system.ErrnoException; import android.system.Os; import android.util.ArraySet; +import android.util.AtomicFile; import android.util.Base64; import android.util.Log; import android.util.LogPrinter; @@ -100,7 +101,6 @@ import java.io.FileReader; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.io.PrintWriter; import java.nio.file.Path; import java.security.SecureRandom; @@ -679,17 +679,23 @@ public class PackageManagerServiceUtils { + "; src: " + srcFile.getAbsolutePath() + ", dst: " + dstFile.getAbsolutePath()); } + final AtomicFile atomicFile = new AtomicFile(dstFile); + FileOutputStream outputStream = null; try ( - InputStream fileIn = new GZIPInputStream(new FileInputStream(srcFile)); - OutputStream fileOut = new FileOutputStream(dstFile, false /*append*/); + InputStream fileIn = new GZIPInputStream(new FileInputStream(srcFile)) ) { - FileUtils.copy(fileIn, fileOut); - Os.chmod(dstFile.getAbsolutePath(), 0644); + outputStream = atomicFile.startWrite(); + FileUtils.copy(fileIn, outputStream); + // Flush anything in buffer before chmod, because any writes after chmod will fail. + outputStream.flush(); + Os.fchmod(outputStream.getFD(), 0644); + atomicFile.finishWrite(outputStream); return PackageManager.INSTALL_SUCCEEDED; } catch (IOException e) { logCriticalInfo(Log.ERROR, "Failed to decompress file" + "; src: " + srcFile.getAbsolutePath() + ", dst: " + dstFile.getAbsolutePath()); + atomicFile.failWrite(outputStream); } return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 302826ff1294..40d884598ceb 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -20,6 +20,8 @@ import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import android.Manifest; +import android.accounts.Account; +import android.accounts.AccountManager; import android.annotation.ColorRes; import android.annotation.DrawableRes; import android.annotation.NonNull; @@ -85,6 +87,7 @@ import android.provider.Settings; import android.security.GateKeeper; import android.service.gatekeeper.IGateKeeperService; import android.stats.devicepolicy.DevicePolicyEnums; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; @@ -3512,6 +3515,39 @@ public class UserManagerService extends IUserManager.Stub { } } + @Override + public UserHandle createUserWithAttributes( + String userName, String userType, @UserInfoFlag int flags, + Bitmap userIcon, + String accountName, String accountType, PersistableBundle accountOptions) { + checkManageOrCreateUsersPermission(flags); + + if (someUserHasAccountNoChecks(accountName, accountType)) { + throw new ServiceSpecificException( + UserManager.USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS); + } + + UserInfo userInfo; + try { + userInfo = createUserInternal(userName, userType, flags, + UserHandle.USER_NULL, null); + + if (userInfo == null) { + throw new ServiceSpecificException(UserManager.USER_OPERATION_ERROR_UNKNOWN); + } + } catch (UserManager.CheckedUserOperationException e) { + throw e.toServiceSpecificException(); + } + + if (userIcon != null) { + mLocalService.setUserIcon(userInfo.id, userIcon); + } + + setSeedAccountDataNoChecks(userInfo.id, accountName, accountType, accountOptions, true); + + return userInfo.getUserHandle(); + } + private UserInfo createUserInternal(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int parentId, @Nullable String[] disallowedPackages) @@ -4934,7 +4970,12 @@ public class UserManagerService extends IUserManager.Stub { @Override public void setSeedAccountData(@UserIdInt int userId, String accountName, String accountType, PersistableBundle accountOptions, boolean persist) { - checkManageUsersPermission("Require MANAGE_USERS permission to set user seed data"); + checkManageUsersPermission("set user seed account data"); + setSeedAccountDataNoChecks(userId, accountName, accountType, accountOptions, persist); + } + + private void setSeedAccountDataNoChecks(@UserIdInt int userId, String accountName, + String accountType, PersistableBundle accountOptions, boolean persist) { synchronized (mPackagesLock) { final UserData userData; synchronized (mUsersLock) { @@ -4996,14 +5037,18 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean someUserHasSeedAccount(String accountName, String accountType) - throws RemoteException { - checkManageUsersPermission("Cannot check seed account information"); + public boolean someUserHasSeedAccount(String accountName, String accountType) { + checkManageUsersPermission("check seed account information"); + return someUserHasSeedAccountNoChecks(accountName, accountType); + } + + private boolean someUserHasSeedAccountNoChecks(String accountName, String accountType) { synchronized (mUsersLock) { final int userSize = mUsers.size(); for (int i = 0; i < userSize; i++) { final UserData data = mUsers.valueAt(i); if (data.info.isInitialized()) continue; + if (mRemovingUserIds.get(data.info.id)) continue; if (data.seedAccountName == null || !data.seedAccountName.equals(accountName)) { continue; } @@ -5017,6 +5062,25 @@ public class UserManagerService extends IUserManager.Stub { } @Override + public boolean someUserHasAccount(String accountName, String accountType) { + checkManageOrCreateUsersPermission("check seed account information"); + return someUserHasAccountNoChecks(accountName, accountType); + } + + private boolean someUserHasAccountNoChecks( + String accountName, String accountType) { + if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) { + return false; + } + + final Account account = new Account(accountName, accountType); + + return Binder.withCleanCallingIdentity(() -> + AccountManager.get(mContext).someUserHasAccount(account) + || someUserHasSeedAccountNoChecks(accountName, accountType)); + } + + @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) { diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index ece0a62b7877..e207ff1d9092 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -702,6 +702,14 @@ final class DefaultPermissionGrantPolicy { DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, userId), userId, CONTACTS_PERMISSIONS); + // Maps + if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) { + grantPermissionsToSystemPackage(pm, + getDefaultSystemHandlerActivityPackageForCategory(pm, + Intent.CATEGORY_APP_MAPS, userId), + userId, FOREGROUND_LOCATION_PERMISSIONS); + } + // Email grantPermissionsToSystemPackage(pm, getDefaultSystemHandlerActivityPackageForCategory(pm, diff --git a/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java b/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java new file mode 100644 index 000000000000..0d420a535415 --- /dev/null +++ b/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java @@ -0,0 +1,98 @@ +/* + * 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.stats.bootstrap; + +import android.content.Context; +import android.os.IStatsBootstrapAtomService; +import android.os.StatsBootstrapAtom; +import android.os.StatsBootstrapAtomValue; +import android.util.Slog; +import android.util.StatsEvent; +import android.util.StatsLog; + +import com.android.server.SystemService; + +/** + * Proxy service for logging pushed atoms to statsd + * + * @hide + */ +public class StatsBootstrapAtomService extends IStatsBootstrapAtomService.Stub { + + private static final String TAG = "StatsBootstrapAtomService"; + private static final boolean DEBUG = false; + + @Override + public void reportBootstrapAtom(StatsBootstrapAtom atom) { + if (atom.atomId < 1 || atom.atomId >= 10000) { + Slog.e(TAG, "Atom ID " + atom.atomId + " is not a valid atom ID"); + return; + } + StatsEvent.Builder builder = StatsEvent.newBuilder().setAtomId(atom.atomId); + for (StatsBootstrapAtomValue value : atom.values) { + switch (value.getTag()) { + case StatsBootstrapAtomValue.boolValue: + builder.writeBoolean(value.getBoolValue()); + break; + case StatsBootstrapAtomValue.intValue: + builder.writeInt(value.getIntValue()); + break; + case StatsBootstrapAtomValue.longValue: + builder.writeLong(value.getLongValue()); + break; + case StatsBootstrapAtomValue.floatValue: + builder.writeFloat(value.getFloatValue()); + break; + case StatsBootstrapAtomValue.stringValue: + builder.writeString(value.getStringValue()); + break; + case StatsBootstrapAtomValue.bytesValue: + builder.writeByteArray(value.getBytesValue()); + break; + default: + Slog.e(TAG, "Unexpected value type " + value.getTag() + + " when logging atom " + atom.atomId); + return; + + } + } + StatsLog.write(builder.usePooledBuffer().build()); + } + + /** + * Lifecycle and related code + */ + public static final class Lifecycle extends SystemService { + private StatsBootstrapAtomService mStatsBootstrapAtomService; + + public Lifecycle(Context context) { + super(context); + } + + @Override + public void onStart() { + mStatsBootstrapAtomService = new StatsBootstrapAtomService(); + try { + publishBinderService(Context.STATS_BOOTSTRAP_ATOM_SERVICE, + mStatsBootstrapAtomService); + if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_BOOTSTRAP_ATOM_SERVICE); + } catch (Exception e) { + Slog.e(TAG, "Failed to publishBinderService", e); + } + } + } + +} diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index e9d5ad6f6d37..e69acc3071fb 100755 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -470,14 +470,16 @@ public final class TvInputManagerService extends SystemService { } private void stopUser(int userId) { - if (userId == mCurrentUserId) { - switchUser(ActivityManager.getCurrentUser()); - return; - } + synchronized (mLock) { + if (userId == mCurrentUserId) { + switchUser(ActivityManager.getCurrentUser()); + return; + } - releaseSessionOfUserLocked(userId); - unbindServiceOfUserLocked(userId); - mRunningProfiles.remove(userId); + releaseSessionOfUserLocked(userId); + unbindServiceOfUserLocked(userId); + mRunningProfiles.remove(userId); + } } private void startProfileLocked(int userId) { diff --git a/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java index 4d1ff9eb3f81..dfb07523d830 100644 --- a/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java +++ b/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java @@ -27,6 +27,7 @@ import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.pm.UserInfo; import android.media.tv.interactive.ITvIAppClient; import android.media.tv.interactive.ITvIAppManager; import android.media.tv.interactive.ITvIAppManagerCallback; @@ -42,6 +43,7 @@ import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; +import android.os.UserManager; import android.util.ArrayMap; import android.util.Slog; import android.util.SparseArray; @@ -58,10 +60,12 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; + /** * This class provides a system service that manages interactive TV applications. */ @@ -81,6 +85,8 @@ public class TvIAppManagerService extends SystemService { @GuardedBy("mLock") private final SparseArray<UserState> mUserStates = new SparseArray<>(); + private final UserManager mUserManager; + /** * Initializes the system service. * <p> @@ -93,6 +99,7 @@ public class TvIAppManagerService extends SystemService { public TvIAppManagerService(Context context) { super(context); mContext = context; + mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); } @GuardedBy("mLock") @@ -330,11 +337,188 @@ public class TvIAppManagerService extends SystemService { mContext.registerReceiverAsUser(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - // TODO: handle switch / start / stop user + String action = intent.getAction(); + if (Intent.ACTION_USER_SWITCHED.equals(action)) { + switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); + } else if (Intent.ACTION_USER_REMOVED.equals(action)) { + removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); + } else if (Intent.ACTION_USER_STARTED.equals(action)) { + int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); + startUser(userId); + } else if (Intent.ACTION_USER_STOPPED.equals(action)) { + int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); + stopUser(userId); + } } }, UserHandle.ALL, intentFilter, null, null); } + private void switchUser(int userId) { + synchronized (mLock) { + if (mCurrentUserId == userId) { + return; + } + UserInfo userInfo = mUserManager.getUserInfo(userId); + if (userInfo.isProfile()) { + Slog.w(TAG, "cannot switch to a profile!"); + return; + } + + for (int runningId : mRunningProfiles) { + releaseSessionOfUserLocked(runningId); + unbindServiceOfUserLocked(runningId); + } + mRunningProfiles.clear(); + releaseSessionOfUserLocked(mCurrentUserId); + unbindServiceOfUserLocked(mCurrentUserId); + + mCurrentUserId = userId; + buildTvIAppServiceListLocked(userId, null); + } + } + + private void removeUser(int userId) { + synchronized (mLock) { + UserState userState = getUserStateLocked(userId); + if (userState == null) { + return; + } + // Release all created sessions. + for (SessionState state : userState.mSessionStateMap.values()) { + if (state.mSession != null) { + try { + state.mSession.release(); + } catch (RemoteException e) { + Slog.e(TAG, "error in release", e); + } + } + } + userState.mSessionStateMap.clear(); + + // Unregister all callbacks and unbind all services. + for (ServiceState serviceState : userState.mServiceStateMap.values()) { + if (serviceState.mService != null) { + if (serviceState.mCallback != null) { + try { + serviceState.mService.unregisterCallback(serviceState.mCallback); + } catch (RemoteException e) { + Slog.e(TAG, "error in unregisterCallback", e); + } + } + mContext.unbindService(serviceState.mConnection); + } + } + userState.mServiceStateMap.clear(); + + // Clear everything else. + userState.mIAppMap.clear(); + userState.mPackageSet.clear(); + userState.mClientStateMap.clear(); + userState.mCallbacks.kill(); + + mRunningProfiles.remove(userId); + mUserStates.remove(userId); + + if (userId == mCurrentUserId) { + switchUser(UserHandle.USER_SYSTEM); + } + } + } + + private void startUser(int userId) { + synchronized (mLock) { + if (userId == mCurrentUserId || mRunningProfiles.contains(userId)) { + // user already started + return; + } + UserInfo userInfo = mUserManager.getUserInfo(userId); + UserInfo parentInfo = mUserManager.getProfileParent(userId); + if (userInfo.isProfile() + && parentInfo != null + && parentInfo.id == mCurrentUserId) { + // only the children of the current user can be started in background + startProfileLocked(userId); + } + } + } + + private void stopUser(int userId) { + synchronized (mLock) { + if (userId == mCurrentUserId) { + switchUser(ActivityManager.getCurrentUser()); + return; + } + + releaseSessionOfUserLocked(userId); + unbindServiceOfUserLocked(userId); + mRunningProfiles.remove(userId); + } + } + + @GuardedBy("mLock") + private void startProfileLocked(int userId) { + mRunningProfiles.add(userId); + buildTvIAppServiceListLocked(userId, null); + } + + @GuardedBy("mLock") + private void releaseSessionOfUserLocked(int userId) { + UserState userState = getUserStateLocked(userId); + if (userState == null) { + return; + } + List<SessionState> sessionStatesToRelease = new ArrayList<>(); + for (SessionState sessionState : userState.mSessionStateMap.values()) { + if (sessionState.mSession != null) { + sessionStatesToRelease.add(sessionState); + } + } + for (SessionState sessionState : sessionStatesToRelease) { + try { + sessionState.mSession.release(); + } catch (RemoteException e) { + Slog.e(TAG, "error in release", e); + } + clearSessionAndNotifyClientLocked(sessionState); + } + } + + @GuardedBy("mLock") + private void unbindServiceOfUserLocked(int userId) { + UserState userState = getUserStateLocked(userId); + if (userState == null) { + return; + } + for (Iterator<ComponentName> it = userState.mServiceStateMap.keySet().iterator(); + it.hasNext(); ) { + ComponentName component = it.next(); + ServiceState serviceState = userState.mServiceStateMap.get(component); + if (serviceState != null && serviceState.mSessionTokens.isEmpty()) { + if (serviceState.mCallback != null) { + try { + serviceState.mService.unregisterCallback(serviceState.mCallback); + } catch (RemoteException e) { + Slog.e(TAG, "error in unregisterCallback", e); + } + } + mContext.unbindService(serviceState.mConnection); + it.remove(); + } + } + } + + @GuardedBy("mLock") + private void clearSessionAndNotifyClientLocked(SessionState state) { + if (state.mClient != null) { + try { + state.mClient.onSessionReleased(state.mSeq); + } catch (RemoteException e) { + Slog.e(TAG, "error in onSessionReleased", e); + } + } + removeSessionStateLocked(state.mSessionToken, state.mUserId); + } + private SessionState getSessionState(IBinder sessionToken) { // TODO: implement user state and get session from it. return null; diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java index a3273823c42b..fdd991358154 100644 --- a/services/core/java/com/android/server/vibrator/VibrationThread.java +++ b/services/core/java/com/android/server/vibrator/VibrationThread.java @@ -287,6 +287,9 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient { } // If we waited, the queue may have changed, so let the loop run again. if (waitTime <= 0) { + if (DEBUG) { + Slog.d(TAG, "Play vibration consuming next step..."); + } mStepQueue.consumeNext(); } Vibration.Status status = mStop ? Vibration.Status.CANCELLED diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java index 4b7fd904e32d..4a1b95bd4596 100644 --- a/services/core/java/com/android/server/vibrator/VibratorController.java +++ b/services/core/java/com/android/server/vibrator/VibratorController.java @@ -40,21 +40,22 @@ final class VibratorController { private static final int SUGGESTED_FREQUENCY_SAFE_RANGE = 200; private final Object mLock = new Object(); - private final NativeWrapper mNativeWrapper; @GuardedBy("mLock") - private VibratorInfo mVibratorInfo; - @GuardedBy("mLock") - private boolean mVibratorInfoLoadSuccessful; - @GuardedBy("mLock") + private final NativeWrapper mNativeWrapper; + + // Vibrator state listeners that support concurrent updates and broadcasts, but should lock + // while broadcasting to guarantee delivery order. private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners = new RemoteCallbackList<>(); - @GuardedBy("mLock") - private boolean mIsVibrating; - @GuardedBy("mLock") - private boolean mIsUnderExternalControl; - @GuardedBy("mLock") - private float mCurrentAmplitude; + + // Vibrator state variables that are updated from synchronized blocks but can be read anytime + // for a snippet of the current known vibrator state/info. + private volatile VibratorInfo mVibratorInfo; + private volatile boolean mVibratorInfoLoadSuccessful; + private volatile boolean mIsVibrating; + private volatile boolean mIsUnderExternalControl; + private volatile float mCurrentAmplitude; /** Listener for vibration completion callbacks from native. */ public interface OnVibrationCompleteListener { @@ -86,35 +87,39 @@ final class VibratorController { /** Register state listener for this vibrator. */ public boolean registerVibratorStateListener(IVibratorStateListener listener) { - synchronized (mLock) { - final long token = Binder.clearCallingIdentity(); - try { + final long token = Binder.clearCallingIdentity(); + try { + // Register the listener and send the first state atomically, to avoid potentially + // out of order broadcasts in between. + synchronized (mLock) { if (!mVibratorStateListeners.register(listener)) { return false; } // Notify its callback after new client registered. - notifyStateListenerLocked(listener); - return true; - } finally { - Binder.restoreCallingIdentity(token); + notifyStateListener(listener, mIsVibrating); } + return true; + } finally { + Binder.restoreCallingIdentity(token); } } /** Remove registered state listener for this vibrator. */ public boolean unregisterVibratorStateListener(IVibratorStateListener listener) { - synchronized (mLock) { - final long token = Binder.clearCallingIdentity(); - try { - return mVibratorStateListeners.unregister(listener); - } finally { - Binder.restoreCallingIdentity(token); - } + final long token = Binder.clearCallingIdentity(); + try { + return mVibratorStateListeners.unregister(listener); + } finally { + Binder.restoreCallingIdentity(token); } } /** Reruns the query to the vibrator to load the {@link VibratorInfo}, if not yet successful. */ public void reloadVibratorInfoIfNeeded() { + // Early check outside lock, for quick return. + if (mVibratorInfoLoadSuccessful) { + return; + } synchronized (mLock) { if (mVibratorInfoLoadSuccessful) { return; @@ -132,16 +137,12 @@ final class VibratorController { /** Checks if the {@link VibratorInfo} was loaded from the vibrator hardware successfully. */ boolean isVibratorInfoLoadSuccessful() { - synchronized (mLock) { - return mVibratorInfoLoadSuccessful; - } + return mVibratorInfoLoadSuccessful; } /** Return the {@link VibratorInfo} representing the vibrator controlled by this instance. */ public VibratorInfo getVibratorInfo() { - synchronized (mLock) { - return mVibratorInfo; - } + return mVibratorInfo; } /** @@ -151,9 +152,7 @@ final class VibratorController { * automatically notified to any registered {@link IVibratorStateListener} on change. */ public boolean isVibrating() { - synchronized (mLock) { - return mIsVibrating; - } + return mIsVibrating; } /** @@ -168,16 +167,12 @@ final class VibratorController { * <p>If {@link #isVibrating()} is false then this will be zero. */ public float getCurrentAmplitude() { - synchronized (mLock) { - return mCurrentAmplitude; - } + return mCurrentAmplitude; } /** Return {@code true} if this vibrator is under external control, false otherwise. */ public boolean isUnderExternalControl() { - synchronized (mLock) { - return mIsUnderExternalControl; - } + return mIsUnderExternalControl; } /** @@ -187,14 +182,14 @@ final class VibratorController { * @return true if this vibrator has this capability, false otherwise */ public boolean hasCapability(long capability) { - synchronized (mLock) { - return mVibratorInfo.hasCapability(capability); - } + return mVibratorInfo.hasCapability(capability); } /** Return {@code true} if the underlying vibrator is currently available, false otherwise. */ public boolean isAvailable() { - return mNativeWrapper.isAvailable(); + synchronized (mLock) { + return mNativeWrapper.isAvailable(); + } } /** @@ -203,10 +198,10 @@ final class VibratorController { * <p>This will affect the state of {@link #isUnderExternalControl()}. */ public void setExternalControl(boolean externalControl) { + if (!mVibratorInfo.hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { + return; + } synchronized (mLock) { - if (!mVibratorInfo.hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { - return; - } mIsUnderExternalControl = externalControl; mNativeWrapper.setExternalControl(externalControl); } @@ -217,10 +212,10 @@ final class VibratorController { * if given {@code effect} is {@code null}. */ public void updateAlwaysOn(int id, @Nullable PrebakedSegment prebaked) { + if (!mVibratorInfo.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { + return; + } synchronized (mLock) { - if (!mVibratorInfo.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { - return; - } if (prebaked == null) { mNativeWrapper.alwaysOnDisable(id); } else { @@ -256,7 +251,7 @@ final class VibratorController { long duration = mNativeWrapper.on(milliseconds, vibrationId); if (duration > 0) { mCurrentAmplitude = -1; - notifyVibratorOnLocked(); + notifyListenerOnVibrating(true); } return duration; } @@ -277,7 +272,7 @@ final class VibratorController { prebaked.getEffectStrength(), vibrationId); if (duration > 0) { mCurrentAmplitude = -1; - notifyVibratorOnLocked(); + notifyListenerOnVibrating(true); } return duration; } @@ -293,14 +288,14 @@ final class VibratorController { * do not support the input or a negative number if the operation failed. */ public long on(PrimitiveSegment[] primitives, long vibrationId) { + if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { + return 0; + } synchronized (mLock) { - if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { - return 0; - } long duration = mNativeWrapper.compose(primitives, vibrationId); if (duration > 0) { mCurrentAmplitude = -1; - notifyVibratorOnLocked(); + notifyListenerOnVibrating(true); } return duration; } @@ -315,15 +310,15 @@ final class VibratorController { * @return The duration of the effect playing, or 0 if unsupported. */ public long on(RampSegment[] primitives, long vibrationId) { + if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) { + return 0; + } synchronized (mLock) { - if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) { - return 0; - } int braking = mVibratorInfo.getDefaultBraking(); long duration = mNativeWrapper.composePwle(primitives, braking, vibrationId); if (duration > 0) { mCurrentAmplitude = -1; - notifyVibratorOnLocked(); + notifyListenerOnVibrating(true); } return duration; } @@ -334,7 +329,7 @@ final class VibratorController { synchronized (mLock) { mNativeWrapper.off(); mCurrentAmplitude = 0; - notifyVibratorOffLocked(); + notifyListenerOnVibrating(false); } } @@ -349,51 +344,31 @@ final class VibratorController { @Override public String toString() { - synchronized (mLock) { - return "VibratorController{" - + "mVibratorInfo=" + mVibratorInfo - + ", mVibratorInfoLoadSuccessful=" + mVibratorInfoLoadSuccessful - + ", mIsVibrating=" + mIsVibrating - + ", mCurrentAmplitude=" + mCurrentAmplitude - + ", mIsUnderExternalControl=" + mIsUnderExternalControl - + ", mVibratorStateListeners count=" - + mVibratorStateListeners.getRegisteredCallbackCount() - + '}'; - } + return "VibratorController{" + + "mVibratorInfo=" + mVibratorInfo + + ", mVibratorInfoLoadSuccessful=" + mVibratorInfoLoadSuccessful + + ", mIsVibrating=" + mIsVibrating + + ", mCurrentAmplitude=" + mCurrentAmplitude + + ", mIsUnderExternalControl=" + mIsUnderExternalControl + + ", mVibratorStateListeners count=" + + mVibratorStateListeners.getRegisteredCallbackCount() + + '}'; } @GuardedBy("mLock") - private void notifyVibratorOnLocked() { - if (!mIsVibrating) { - mIsVibrating = true; - notifyStateListenersLocked(); + private void notifyListenerOnVibrating(boolean isVibrating) { + if (mIsVibrating != isVibrating) { + mIsVibrating = isVibrating; + // The broadcast method is safe w.r.t. register/unregister listener methods, but lock + // is required here to guarantee delivery order. + mVibratorStateListeners.broadcast( + listener -> notifyStateListener(listener, isVibrating)); } } - @GuardedBy("mLock") - private void notifyVibratorOffLocked() { - if (mIsVibrating) { - mIsVibrating = false; - notifyStateListenersLocked(); - } - } - - @GuardedBy("mLock") - private void notifyStateListenersLocked() { - final int length = mVibratorStateListeners.beginBroadcast(); - try { - for (int i = 0; i < length; i++) { - notifyStateListenerLocked(mVibratorStateListeners.getBroadcastItem(i)); - } - } finally { - mVibratorStateListeners.finishBroadcast(); - } - } - - @GuardedBy("mLock") - private void notifyStateListenerLocked(IVibratorStateListener listener) { + private void notifyStateListener(IVibratorStateListener listener, boolean isVibrating) { try { - listener.onVibrating(mIsVibrating); + listener.onVibrating(isVibrating); } catch (RemoteException | RuntimeException e) { Slog.e(TAG, "Vibrator state listener failed to call", e); } diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index 0675ad6451ce..5d40c23610dd 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -391,6 +391,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { fillVibrationFallbacks(vib, effect); synchronized (mLock) { + if (DEBUG) { + Slog.d(TAG, "Starting vibrate for vibration " + vib.id); + } Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(vib); if (ignoreStatus != null) { endVibrationLocked(vib, ignoreStatus); @@ -498,6 +501,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { @VisibleForTesting void updateServiceState() { synchronized (mLock) { + if (DEBUG) { + Slog.d(TAG, "Updating device state..."); + } boolean inputDevicesChanged = mInputDeviceDelegate.updateInputDeviceVibrators( mVibrationSettings.shouldVibrateInputDevices()); @@ -611,6 +617,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); try { Vibration vib = mCurrentVibration.getVibration(); + if (DEBUG) { + Slog.d(TAG, "Reporting vibration " + vib.id + " finished with status " + status); + } endVibrationLocked(vib, status); finishAppOpModeLocked(vib.uid, vib.opPkg); } finally { @@ -1062,11 +1071,17 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { Slog.d(TAG, "Vibrators released after finished vibration"); } synchronized (mLock) { + if (DEBUG) { + Slog.d(TAG, "Processing vibrators released callback"); + } mCurrentVibration = null; if (mNextVibration != null) { VibrationThread vibThread = mNextVibration; mNextVibration = null; - startVibrationThreadLocked(vibThread); + Vibration.Status status = startVibrationThreadLocked(vibThread); + if (status != Vibration.Status.RUNNING) { + endVibrationLocked(vibThread.getVibration(), status); + } } } } @@ -1248,6 +1263,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { void dumpText(PrintWriter pw) { pw.println("Vibrator Manager Service:"); synchronized (mLock) { + if (DEBUG) { + Slog.d(TAG, "Dumping vibrator manager service to text..."); + } pw.println(" mVibrationSettings:"); pw.println(" " + mVibrationSettings); pw.println(); @@ -1290,6 +1308,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { final ProtoOutputStream proto = new ProtoOutputStream(fd); synchronized (mLock) { + if (DEBUG) { + Slog.d(TAG, "Dumping vibrator manager service to proto..."); + } mVibrationSettings.dumpProto(proto); if (mCurrentVibration != null) { mCurrentVibration.getVibration().getDebugInfo().dumpProto(proto, diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java index 210b0aebceb2..ecc85878353a 100644 --- a/services/core/java/com/android/server/wm/ActivityStartController.java +++ b/services/core/java/com/android/server/wm/ActivityStartController.java @@ -496,11 +496,13 @@ public class ActivityStartController { * @param activityIntent intent to start the activity. * @param activityOptions ActivityOptions to start the activity with. * @param resultTo the caller activity + * @param callingUid the caller uid + * @param callingPid the caller pid * @return the start result. */ int startActivityInTaskFragment(@NonNull TaskFragment taskFragment, @NonNull Intent activityIntent, @Nullable Bundle activityOptions, - @Nullable IBinder resultTo) { + @Nullable IBinder resultTo, int callingUid, int callingPid) { final ActivityRecord caller = resultTo != null ? ActivityRecord.forTokenLocked(resultTo) : null; return obtainStarter(activityIntent, "startActivityInTaskFragment") @@ -508,8 +510,8 @@ public class ActivityStartController { .setInTaskFragment(taskFragment) .setResultTo(resultTo) .setRequestCode(-1) - .setCallingUid(Binder.getCallingUid()) - .setCallingPid(Binder.getCallingPid()) + .setCallingUid(callingUid) + .setCallingPid(callingPid) .setUserId(caller != null ? caller.mUserId : mService.getCurrentUserId()) .execute(); } diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index f94777339fae..878822522d08 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -65,7 +65,10 @@ import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_S import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN; import static com.android.server.wm.AppTransition.isNormalTransit; +import static com.android.server.wm.NonAppWindowAnimationAdapter.shouldAttachNavBarToApp; +import static com.android.server.wm.NonAppWindowAnimationAdapter.shouldStartNonAppWindowAnimationsForKeyguardExit; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; +import static com.android.server.wm.WallpaperAnimationAdapter.shouldStartWallpaperAnimation; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -529,18 +532,9 @@ public class AppTransitionController { // Having {@code transit} of those types doesn't mean it will contain non-app windows, but // non-app windows will only be included with those transition types. And we don't currently // have any use case of those for TaskFragment transition. - // @see NonAppWindowAnimationAdapter#startNonAppWindowAnimations - if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY - || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER - || transit == TRANSIT_OLD_TASK_OPEN || transit == TRANSIT_OLD_TASK_TO_FRONT - || transit == TRANSIT_OLD_WALLPAPER_CLOSE) { - return true; - } - - // Check if the wallpaper is going to participate in the transition. We don't want to have - // the client to animate the wallpaper windows. - // @see WallpaperAnimationAdapter#startWallpaperAnimations - return mDisplayContent.mWallpaperController.isWallpaperVisible(); + return shouldStartNonAppWindowAnimationsForKeyguardExit(transit) + || shouldAttachNavBarToApp(mService, mDisplayContent, transit) + || shouldStartWallpaperAnimation(mDisplayContent); } /** @@ -596,7 +590,7 @@ public class AppTransitionController { } // We don't want the organizer to handle transition of non-embedded activity of other // app. - if (r.getUid() != rootActivity.getUid() && !r.isEmbedded()) { + if (r.getUid() != task.effectiveUid && !r.isEmbedded()) { leafTask = null; break; } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index a492b7abacbc..09de6b3ca4fa 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -1577,7 +1577,7 @@ public class DisplayPolicy { applyKeyguardPolicy(win, imeTarget); // Check if the freeform window overlaps with the navigation bar area. - final boolean isOverlappingWithNavBar = isOverlappingWithNavBar(win, mNavigationBar); + final boolean isOverlappingWithNavBar = isOverlappingWithNavBar(win); if (isOverlappingWithNavBar && !mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode()) { mIsFreeformWindowOverlappingWithNavBar = true; @@ -2343,7 +2343,7 @@ public class DisplayPolicy { private int getStatusBarAppearance(WindowState opaque, WindowState opaqueOrDimming) { final boolean onKeyguard = isKeyguardShowing() && !isKeyguardOccluded(); final WindowState colorWin = onKeyguard ? mNotificationShade : opaqueOrDimming; - return isLightBarAllowed(colorWin, ITYPE_STATUS_BAR) && (colorWin == opaque || onKeyguard) + return isLightBarAllowed(colorWin, Type.statusBars()) && (colorWin == opaque || onKeyguard) ? (colorWin.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_STATUS_BARS) : 0; } @@ -2391,7 +2391,7 @@ public class DisplayPolicy { @VisibleForTesting int updateLightNavigationBarLw(int appearance, WindowState navColorWin) { if (navColorWin == null || navColorWin.isDimming() - || !isLightBarAllowed(navColorWin, ITYPE_NAVIGATION_BAR)) { + || !isLightBarAllowed(navColorWin, Type.navigationBars())) { // Clear the light flag while not allowed. appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; return appearance; @@ -2456,12 +2456,11 @@ public class DisplayPolicy { return appearance; } - private boolean isLightBarAllowed(WindowState win, @InternalInsetsType int type) { + private static boolean isLightBarAllowed(WindowState win, @InsetsType int type) { if (win == null) { return false; } - final InsetsSource source = win.getInsetsState().peekSource(type); - return source != null && Rect.intersects(win.getFrame(), source.getFrame()); + return intersectsAnyInsets(win.getFrame(), win.getInsetsState(), type); } private Rect getBarContentFrameForWindow(WindowState win, @InternalInsetsType int type) { @@ -2838,17 +2837,34 @@ public class DisplayPolicy { } @VisibleForTesting - static boolean isOverlappingWithNavBar(@NonNull WindowState targetWindow, - WindowState navBarWindow) { - if (navBarWindow == null || !navBarWindow.isVisible() - || targetWindow.mActivityRecord == null || !targetWindow.isVisible()) { + static boolean isOverlappingWithNavBar(@NonNull WindowState win) { + if (win.mActivityRecord == null || !win.isVisible()) { return false; } // When the window is dimming means it's requesting dim layer to its host container, so - // checking whether it's overlapping with navigation bar by its container's bounds. - return Rect.intersects(targetWindow.isDimming() - ? targetWindow.getBounds() : targetWindow.getFrame(), navBarWindow.getFrame()); + // checking whether it's overlapping with a navigation bar by its container's bounds. + return intersectsAnyInsets(win.isDimming() ? win.getBounds() : win.getFrame(), + win.getInsetsState(), Type.navigationBars()); + } + + /** + * Returns whether the given {@param bounds} intersects with any insets of the + * provided {@param insetsType}. + */ + private static boolean intersectsAnyInsets(Rect bounds, InsetsState insetsState, + @InsetsType int insetsType) { + final ArraySet<Integer> internalTypes = InsetsState.toInternalType(insetsType); + for (int i = 0; i < internalTypes.size(); i++) { + final InsetsSource source = insetsState.peekSource(internalTypes.valueAt(i)); + if (source == null || !source.isVisible()) { + continue; + } + if (Rect.intersects(bounds, source.getFrame())) { + return true; + } + } + return false; } /** diff --git a/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java b/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java index 9f28509c56bd..7c35a2163d6d 100644 --- a/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java +++ b/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java @@ -69,25 +69,32 @@ class NonAppWindowAnimationAdapter implements AnimationAdapter { long durationHint, long statusBarTransitionDelay, ArrayList<NonAppWindowAnimationAdapter> adaptersOut) { final ArrayList<RemoteAnimationTarget> targets = new ArrayList<>(); - if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY - || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER) { + if (shouldStartNonAppWindowAnimationsForKeyguardExit(transit)) { startNonAppWindowAnimationsForKeyguardExit( service, durationHint, statusBarTransitionDelay, targets, adaptersOut); - } else if (transit == TRANSIT_OLD_TASK_OPEN || transit == TRANSIT_OLD_TASK_TO_FRONT - || transit == TRANSIT_OLD_WALLPAPER_CLOSE) { - final boolean shouldAttachNavBarToApp = - displayContent.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition() - && service.getRecentsAnimationController() == null - && displayContent.getFadeRotationAnimationController() == null; - if (shouldAttachNavBarToApp) { - startNavigationBarWindowAnimation( - displayContent, durationHint, statusBarTransitionDelay, targets, - adaptersOut); - } + } else if (shouldAttachNavBarToApp(service, displayContent, transit)) { + startNavigationBarWindowAnimation( + displayContent, durationHint, statusBarTransitionDelay, targets, + adaptersOut); } return targets.toArray(new RemoteAnimationTarget[targets.size()]); } + static boolean shouldStartNonAppWindowAnimationsForKeyguardExit( + @WindowManager.TransitionOldType int transit) { + return transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY + || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER; + } + + static boolean shouldAttachNavBarToApp(WindowManagerService service, + DisplayContent displayContent, @WindowManager.TransitionOldType int transit) { + return (transit == TRANSIT_OLD_TASK_OPEN || transit == TRANSIT_OLD_TASK_TO_FRONT + || transit == TRANSIT_OLD_WALLPAPER_CLOSE) + && displayContent.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition() + && service.getRecentsAnimationController() == null + && displayContent.getFadeRotationAnimationController() == null; + } + /** * Creates and starts remote animations for all the visible non app windows. * diff --git a/services/core/java/com/android/server/wm/PackageConfigPersister.java b/services/core/java/com/android/server/wm/PackageConfigPersister.java index 3de98f18dae8..7a7fb6570694 100644 --- a/services/core/java/com/android/server/wm/PackageConfigPersister.java +++ b/services/core/java/com/android/server/wm/PackageConfigPersister.java @@ -169,21 +169,35 @@ public class PackageConfigPersister { } } + /** + * Returns true when the app specific configuration is successfully stored or removed based on + * the current requested configuration. It will return false when the requested + * configuration is same as the pre-existing app-specific configuration. + */ @GuardedBy("mLock") boolean updateFromImpl(String packageName, int userId, PackageConfigurationUpdaterImpl impl) { synchronized (mLock) { - PackageConfigRecord record = findRecordOrCreate(mModified, packageName, userId); - if (impl.getNightMode() != null) { - record.mNightMode = impl.getNightMode(); - } - if (impl.getLocales() != null) { - record.mLocales = impl.getLocales(); + boolean isRecordPresent = false; + PackageConfigRecord record = findRecord(mModified, packageName, userId); + if (record != null) { + isRecordPresent = true; + } else { + record = findRecordOrCreate(mModified, packageName, userId); } + boolean isNightModeChanged = updateNightMode(impl.getNightMode(), record); + boolean isLocalesChanged = updateLocales(impl.getLocales(), record); + if ((record.mNightMode == null || record.isResetNightMode()) && (record.mLocales == null || record.mLocales.isEmpty())) { // if all values default to system settings, we can remove the package. removePackage(packageName, userId); + // if there was a pre-existing record for the package that was deleted, + // we return true (since it was successfully deleted), else false (since there was + // no change to the previous state). + return isRecordPresent; + } else if (!isNightModeChanged && !isLocalesChanged) { + return false; } else { final PackageConfigRecord pendingRecord = findRecord(mPendingWrite, record.mName, record.mUserId); @@ -195,7 +209,8 @@ public class PackageConfigPersister { writeRecord = pendingRecord; } - if (!updateNightMode(record, writeRecord) && !updateLocales(record, writeRecord)) { + if (!updateNightMode(record.mNightMode, writeRecord) + && !updateLocales(record.mLocales, writeRecord)) { return false; } @@ -203,24 +218,24 @@ public class PackageConfigPersister { Slog.d(TAG, "PackageConfigUpdater save config " + writeRecord); } mPersisterQueue.addItem(new WriteProcessItem(writeRecord), false /* flush */); + return true; } - return true; } } - private boolean updateNightMode(PackageConfigRecord record, PackageConfigRecord writeRecord) { - if (record.mNightMode == null || record.mNightMode.equals(writeRecord.mNightMode)) { + private boolean updateNightMode(Integer requestedNightMode, PackageConfigRecord record) { + if (requestedNightMode == null || requestedNightMode.equals(record.mNightMode)) { return false; } - writeRecord.mNightMode = record.mNightMode; + record.mNightMode = requestedNightMode; return true; } - private boolean updateLocales(PackageConfigRecord record, PackageConfigRecord writeRecord) { - if (record.mLocales == null || record.mLocales.equals(writeRecord.mLocales)) { + private boolean updateLocales(LocaleList requestedLocaleList, PackageConfigRecord record) { + if (requestedLocaleList == null || requestedLocaleList.equals(record.mLocales)) { return false; } - writeRecord.mLocales = record.mLocales; + record.mLocales = requestedLocaleList; return true; } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 0eaa25be3094..929f2212348a 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -1413,29 +1413,29 @@ class TaskFragment extends WindowContainer<WindowContainer> { boolean pauseImmediately = false; boolean shouldAutoPip = false; - if (resuming != null && (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0) { - // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous - // activity to be paused, while at the same time resuming the new resume activity - // only if the previous activity can't go into Pip since we want to give Pip - // activities a chance to enter Pip before resuming the next activity. - final boolean lastResumedCanPip = prev != null && prev.checkEnterPictureInPictureState( - "shouldResumeWhilePausing", userLeaving); + if (resuming != null) { + // Resuming the new resume activity only if the previous activity can't go into Pip + // since we want to give Pip activities a chance to enter Pip before resuming the + // next activity. + final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState( + "shouldAutoPipWhilePausing", userLeaving); if (lastResumedCanPip && prev.pictureInPictureArgs.isAutoEnterEnabled()) { shouldAutoPip = true; } else if (!lastResumedCanPip) { - pauseImmediately = true; + // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous + // activity to be paused. + pauseImmediately = (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0; } else { // The previous activity may still enter PIP even though it did not allow auto-PIP. } } - boolean didAutoPip = false; if (prev.attachedToProcess()) { if (shouldAutoPip) { + boolean didAutoPip = mAtmService.enterPictureInPictureMode( + prev, prev.pictureInPictureArgs); ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode " - + "directly: %s", prev); - - didAutoPip = mAtmService.enterPictureInPictureMode(prev, prev.pictureInPictureArgs); + + "directly: %s, didAutoPip: %b", prev, didAutoPip); } else { schedulePauseActivity(prev, userLeaving, pauseImmediately, reason); } diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java index d91165685c63..6d83fb6d12c9 100644 --- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java @@ -434,6 +434,9 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr private final TaskFragment mTaskFragment; private final IBinder mErrorCallback; private final Throwable mException; + // Set when the event is deferred due to the host task is invisible. The defer time will + // be the last active time of the host task. + private long mDeferTime; private PendingTaskFragmentEvent(TaskFragment taskFragment, ITaskFragmentOrganizer taskFragmentOrg, @EventType int eventType) { @@ -503,11 +506,45 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr || mPendingTaskFragmentEvents.isEmpty()) { return; } + + final ArrayList<Task> visibleTasks = new ArrayList<>(); + final ArrayList<Task> invisibleTasks = new ArrayList<>(); + final ArrayList<PendingTaskFragmentEvent> candidateEvents = new ArrayList<>(); for (int i = 0, n = mPendingTaskFragmentEvents.size(); i < n; i++) { - PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i); - dispatchEvent(event); + final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i); + final Task task = event.mTaskFragment != null ? event.mTaskFragment.getTask() : null; + if (task != null && (task.lastActiveTime <= event.mDeferTime + || !isTaskVisible(task, visibleTasks, invisibleTasks))) { + // Defer sending events to the TaskFragment until the host task is active again. + event.mDeferTime = task.lastActiveTime; + continue; + } + candidateEvents.add(event); + } + final int numEvents = candidateEvents.size(); + for (int i = 0; i < numEvents; i++) { + dispatchEvent(candidateEvents.get(i)); + } + if (numEvents > 0) { + mPendingTaskFragmentEvents.removeAll(candidateEvents); + } + } + + private static boolean isTaskVisible(Task task, ArrayList<Task> knownVisibleTasks, + ArrayList<Task> knownInvisibleTasks) { + if (knownVisibleTasks.contains(task)) { + return true; + } + if (knownInvisibleTasks.contains(task)) { + return false; + } + if (task.shouldBeVisible(null /* starting */)) { + knownVisibleTasks.add(task); + return true; + } else { + knownInvisibleTasks.add(task); + return false; } - mPendingTaskFragmentEvents.clear(); } void dispatchPendingInfoChangedEvent(TaskFragment taskFragment) { diff --git a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java index 26527233aef0..4a5a20e57804 100644 --- a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java +++ b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java @@ -69,7 +69,7 @@ class WallpaperAnimationAdapter implements AnimationAdapter { long durationHint, long statusBarTransitionDelay, Consumer<WallpaperAnimationAdapter> animationCanceledRunnable, ArrayList<WallpaperAnimationAdapter> adaptersOut) { - if (!displayContent.mWallpaperController.isWallpaperVisible()) { + if (!shouldStartWallpaperAnimation(displayContent)) { ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tWallpaper of display=%s is not visible", displayContent); return new RemoteAnimationTarget[0]; @@ -87,6 +87,10 @@ class WallpaperAnimationAdapter implements AnimationAdapter { return targets.toArray(new RemoteAnimationTarget[targets.size()]); } + static boolean shouldStartWallpaperAnimation(DisplayContent displayContent) { + return displayContent.mWallpaperController.isWallpaperVisible(); + } + /** * Create a remote animation target for this animation adapter. */ diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 3d479d1e0d68..0649b25e0f04 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -587,7 +587,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT: { final TaskFragmentCreationParams taskFragmentCreationOptions = hop.getTaskFragmentCreationOptions(); - createTaskFragment(taskFragmentCreationOptions, errorCallbackToken); + createTaskFragment(taskFragmentCreationOptions, errorCallbackToken, caller); break; } case HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT: { @@ -630,7 +630,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub final TaskFragment tf = mLaunchTaskFragments.get(fragmentToken); final int result = mService.getActivityStartController() .startActivityInTaskFragment(tf, activityIntent, activityOptions, - hop.getCallingActivity()); + hop.getCallingActivity(), caller.mUid, caller.mPid); if (!isStartResultSuccessful(result)) { sendTaskFragmentOperationFailure(tf.getTaskFragmentOrganizer(), errorCallbackToken, @@ -1199,7 +1199,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } void createTaskFragment(@NonNull TaskFragmentCreationParams creationParams, - @Nullable IBinder errorCallbackToken) { + @Nullable IBinder errorCallbackToken, @NonNull CallerInfo caller) { final ActivityRecord ownerActivity = ActivityRecord.forTokenLocked(creationParams.getOwnerToken()); final ITaskFragmentOrganizer organizer = ITaskFragmentOrganizer.Stub.asInterface( @@ -1217,9 +1217,9 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); return; } - // The ownerActivity has to belong to the same app as the root Activity of the target Task. - final ActivityRecord rootActivity = ownerActivity.getTask().getRootActivity(); - if (rootActivity.getUid() != ownerActivity.getUid()) { + // The ownerActivity has to belong to the same app as the target Task. + if (ownerActivity.getTask().effectiveUid != ownerActivity.getUid() + || ownerActivity.getTask().effectiveUid != caller.mUid) { final Throwable exception = new IllegalArgumentException("Not allowed to operate with the ownerToken while " + "the root activity of the target task belong to the different app"); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 727f26573fac..3839a9f39158 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -8460,7 +8460,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean hasDeviceOwner() { final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller)); + Preconditions.checkCallAuthorization(isDeviceOwner(caller) + || canManageUsers(caller) + || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); return mOwners.hasDeviceOwner(); } @@ -8640,7 +8642,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return null; } - Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())); + Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()) + || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); synchronized (getLockObject()) { if (!mOwners.hasDeviceOwner()) { @@ -8986,7 +8989,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return DevicePolicyManager.STATE_USER_UNMANAGED; } final CallerIdentity caller = getCallerIdentity(); - Preconditions.checkCallAuthorization(canManageUsers(caller)); + Preconditions.checkCallAuthorization(canManageUsers(caller) + || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); return getUserProvisioningState(caller.getUserId()); } @@ -9240,7 +9244,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return null; } - Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())); + Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()) + || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); return getProfileOwnerNameUnchecked(userHandle); } @@ -16466,7 +16471,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return false; } - Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())); + Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()) + || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); long id = mInjector.binderClearCallingIdentity(); try { @@ -16492,7 +16498,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return false; } - Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())); + Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()) + || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); return mInjector.binderWithCleanCallingIdentity(() -> isUnattendedManagedKioskUnchecked()); } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 6d542bf47386..2f9e3344b29c 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -267,6 +267,8 @@ public final class SystemServer implements Dumpable { "com.android.server.stats.StatsCompanion$Lifecycle"; private static final String STATS_PULL_ATOM_SERVICE_CLASS = "com.android.server.stats.pull.StatsPullAtomService"; + private static final String STATS_BOOTSTRAP_ATOM_SERVICE_LIFECYCLE_CLASS = + "com.android.server.stats.bootstrap.StatsBootstrapAtomService$Lifecycle"; private static final String USB_SERVICE_CLASS = "com.android.server.usb.UsbService$Lifecycle"; private static final String MIDI_SERVICE_CLASS = @@ -371,6 +373,8 @@ public final class SystemServer implements Dumpable { "com.android.server.blob.BlobStoreManagerService"; private static final String APP_SEARCH_MANAGER_SERVICE_CLASS = "com.android.server.appsearch.AppSearchManagerService"; + private static final String ISOLATED_COMPILATION_SERVICE_CLASS = + "com.android.server.compos.IsolatedCompilationService"; private static final String ROLLBACK_MANAGER_SERVICE_CLASS = "com.android.server.rollback.RollbackManagerService"; private static final String ALARM_MANAGER_SERVICE_CLASS = @@ -2541,6 +2545,11 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(STATS_PULL_ATOM_SERVICE_CLASS); t.traceEnd(); + // Log atoms to statsd from bootstrap processes. + t.traceBegin("StatsBootstrapAtomService"); + mSystemServiceManager.startService(STATS_BOOTSTRAP_ATOM_SERVICE_LIFECYCLE_CLASS); + t.traceEnd(); + // Incidentd and dumpstated helper t.traceBegin("StartIncidentCompanionService"); mSystemServiceManager.startService(IncidentCompanionService.class); @@ -2711,6 +2720,12 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(APP_SEARCH_MANAGER_SERVICE_CLASS); t.traceEnd(); + if (SystemProperties.getBoolean("ro.config.isolated_compilation_enabled", false)) { + t.traceBegin("IsolatedCompilationService"); + mSystemServiceManager.startService(ISOLATED_COMPILATION_SERVICE_CLASS); + t.traceEnd(); + } + t.traceBegin("StartMediaCommunicationService"); mSystemServiceManager.startService(MEDIA_COMMUNICATION_SERVICE_CLASS); t.traceEnd(); diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index fb7ef846f813..62a16f7f24fd 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -91,10 +91,12 @@ public final class ProfcollectForwardingService extends SystemService { if (mIProfcollect == null) { return; } - if (serviceHasSupportedTraceProvider()) { - registerObservers(); - } - ProfcollectBGJobService.schedule(getContext()); + BackgroundThread.get().getThreadHandler().post(() -> { + if (serviceHasSupportedTraceProvider()) { + registerObservers(); + ProfcollectBGJobService.schedule(getContext()); + } + }); } } diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt index 349eb2215669..dc93e53a0d24 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt @@ -223,6 +223,7 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag AndroidPackage::isVendor, AndroidPackage::isVisibleToInstantApps, AndroidPackage::isVmSafeMode, + AndroidPackage::isResetEnabledSettingsOnAppDataCleared, AndroidPackage::getMaxAspectRatio, AndroidPackage::getMinAspectRatio, AndroidPackage::hasPreserveLegacyExternalStorage, diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt index bbfa4610feea..cfc81e684a7f 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt @@ -29,6 +29,7 @@ import com.android.server.apphibernation.AppHibernationManagerInternal import com.android.server.apphibernation.AppHibernationService import com.android.server.extendedtestutils.wheneverStatic import com.android.server.testutils.whenever +import org.junit.Assert import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Before @@ -36,7 +37,6 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock -import org.mockito.Mockito import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -102,9 +102,10 @@ class PackageManagerServiceHibernationTests { val pm = createPackageManagerService() rule.system().validateFinalState() - pm.setPackageStoppedState(TEST_PACKAGE_NAME, true, TEST_USER_ID) TestableLooper.get(this).processAllMessages() - Mockito.clearInvocations(appHibernationManager) + + whenever(appHibernationManager.isHibernatingForUser(TEST_PACKAGE_NAME, TEST_USER_ID)) + .thenReturn(true) pm.setPackageStoppedState(TEST_PACKAGE_NAME, false, TEST_USER_ID) @@ -115,6 +116,31 @@ class PackageManagerServiceHibernationTests { } @Test + fun testExitForceStop_nonExistingAppHibernationManager_doesNotThrowException() { + whenever(rule.mocks().injector.getLocalService(AppHibernationManagerInternal::class.java)) + .thenReturn(null) + + rule.system().stageScanExistingPackage( + TEST_PACKAGE_NAME, + 1L, + rule.system().dataAppDirectory) + val pm = createPackageManagerService() + rule.system().validateFinalState() + + TestableLooper.get(this).processAllMessages() + + whenever(appHibernationManager.isHibernatingForUser(TEST_PACKAGE_NAME, TEST_USER_ID)) + .thenReturn(true) + + try { + pm.setPackageStoppedState(TEST_PACKAGE_NAME, false, TEST_USER_ID) + TestableLooper.get(this).processAllMessages() + } catch (e: Exception) { + Assert.fail("Method throws exception when AppHibernationManager is not ready.\n$e") + } + } + + @Test fun testGetOptimizablePackages_ExcludesGloballyHibernatingPackages() { rule.system().stageScanExistingPackage( TEST_PACKAGE_NAME, diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index ba580ecaad16..e3c60fdfc697 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -108,6 +108,7 @@ android_test { data: [ ":JobTestApp", + ":StubTestApp", ], java_resources: [ diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml index 5a0f1ee963a2..4c638d669019 100644 --- a/services/tests/servicestests/AndroidTest.xml +++ b/services/tests/servicestests/AndroidTest.xml @@ -28,6 +28,17 @@ <option name="test-file-name" value="SimpleServiceTestApp3.apk" /> </target_preparer> + <!-- Create place to store apks --> + <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> + <option name="run-command" value="mkdir -p /data/local/tmp/servicestests" /> + <option name="teardown-command" value="rm -rf /data/local/tmp/servicestests"/> + </target_preparer> + + <!-- Load additional APKs onto device --> + <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher"> + <option name="push" value="StubTestApp.apk->/data/local/tmp/servicestests/StubTestApp.apk"/> + </target_preparer> + <option name="test-tag" value="FrameworksServicesTests" /> <test class="com.android.tradefed.testtype.AndroidJUnitTest" > <option name="package" value="com.android.frameworks.servicestests" /> diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java index 734fdbaef919..6a85c8b2e2ba 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java @@ -16,6 +16,8 @@ package com.android.server.pm; +import static com.android.compatibility.common.util.ShellUtils.runShellCommand; + import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.fail; @@ -27,11 +29,17 @@ import static java.lang.reflect.Modifier.isPublic; import static java.lang.reflect.Modifier.isStatic; import android.annotation.Nullable; +import android.app.AppGlobals; import android.content.IIntentReceiver; +import android.content.pm.IPackageManager; +import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.os.Bundle; +import android.os.UserHandle; +import android.os.UserManager; import android.util.SparseArray; +import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.HexDump; @@ -42,6 +50,7 @@ import com.google.android.collect.Lists; import org.junit.After; import org.junit.Assert; +import org.junit.Assume; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -62,6 +71,11 @@ import java.util.regex.Pattern; // bit FrameworksServicesTests:com.android.server.pm.PackageManagerServiceTest @RunWith(AndroidJUnit4.class) public class PackageManagerServiceTest { + + private static final String TEST_DATA_PATH = "/data/local/tmp/servicestests/"; + private static final String TEST_APP_APK = "StubTestApp.apk"; + private static final String TEST_PKG_NAME = "com.android.servicestests.apps.stubapp"; + @Before public void setUp() throws Exception { } @@ -509,6 +523,11 @@ public class PackageManagerServiceTest { for (Method m : coreMethods) { if (m != null) { final String name = "ComputerEngine." + displayName(m); + if (name.contains(".lambda$static")) { + // skip static lambda function + continue; + } + final int modifiers = m.getModifiers(); if (isPrivate(modifiers)) { // Okay @@ -598,4 +617,119 @@ public class PackageManagerServiceTest { Collections.sort(knownPackageIds); return knownPackageIds; } + + @Test + public void testInstallReason_afterUpdate_keepUnchanged() throws Exception { + final IPackageManager pm = AppGlobals.getPackageManager(); + final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK); + try { + // Try to install test APK with reason INSTALL_REASON_POLICY + runShellCommand("pm install --install-reason 1 " + testApk); + assertWithMessage("The install reason of test APK is incorrect.").that( + pm.getInstallReason(TEST_PKG_NAME, UserHandle.myUserId())).isEqualTo( + PackageManager.INSTALL_REASON_POLICY); + + // Try to update test APK with different reason INSTALL_REASON_USER + runShellCommand("pm install --install-reason 4 " + testApk); + assertWithMessage("The install reason should keep unchanged after update.").that( + pm.getInstallReason(TEST_PKG_NAME, UserHandle.myUserId())).isEqualTo( + PackageManager.INSTALL_REASON_POLICY); + } finally { + runShellCommand("pm uninstall " + TEST_PKG_NAME); + } + } + + @Test + public void testInstallReason_userRemainsUninstalled_keepUnknown() throws Exception { + Assume.assumeTrue(UserManager.supportsMultipleUsers()); + final IPackageManager pm = AppGlobals.getPackageManager(); + final UserManager um = UserManager.get( + InstrumentationRegistry.getInstrumentation().getContext()); + final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK); + int userId = UserHandle.USER_NULL; + try { + // Try to install test APK with reason INSTALL_REASON_POLICY + runShellCommand("pm install --install-reason 1 " + testApk); + assertWithMessage("The install reason of test APK is incorrect.").that( + pm.getInstallReason(TEST_PKG_NAME, UserHandle.myUserId())).isEqualTo( + PackageManager.INSTALL_REASON_POLICY); + + // Create and start the 2nd user. + userId = um.createUser("Test User", 0 /* flags */).getUserHandle().getIdentifier(); + runShellCommand("am start-user -w " + userId); + // Since the test APK isn't installed on the 2nd user, the reason should be unknown. + assertWithMessage("The install reason in 2nd user should be unknown.").that( + pm.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo( + PackageManager.INSTALL_REASON_UNKNOWN); + + // Try to update test APK with different reason INSTALL_REASON_USER + runShellCommand("pm install --install-reason 4 " + testApk); + assertWithMessage("The install reason in 2nd user should keep unknown.").that( + pm.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo( + PackageManager.INSTALL_REASON_UNKNOWN); + } finally { + runShellCommand("pm uninstall " + TEST_PKG_NAME); + if (userId != UserHandle.USER_NULL) { + um.removeUser(userId); + } + } + } + + @Test + public void testInstallReason_installForAllUsers_sameReason() throws Exception { + Assume.assumeTrue(UserManager.supportsMultipleUsers()); + final IPackageManager pm = AppGlobals.getPackageManager(); + final UserManager um = UserManager.get( + InstrumentationRegistry.getInstrumentation().getContext()); + final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK); + int userId = UserHandle.USER_NULL; + try { + // Create and start the 2nd user. + userId = um.createUser("Test User", 0 /* flags */).getUserHandle().getIdentifier(); + runShellCommand("am start-user -w " + userId); + + // Try to install test APK to all users with reason INSTALL_REASON_POLICY + runShellCommand("pm install --install-reason 1 " + testApk); + assertWithMessage("The install reason is inconsistent across users.").that( + pm.getInstallReason(TEST_PKG_NAME, UserHandle.myUserId())).isEqualTo( + pm.getInstallReason(TEST_PKG_NAME, userId)); + } finally { + runShellCommand("pm uninstall " + TEST_PKG_NAME); + if (userId != UserHandle.USER_NULL) { + um.removeUser(userId); + } + } + } + + @Test + public void testInstallReason_installSeparately_withSeparatedReason() throws Exception { + Assume.assumeTrue(UserManager.supportsMultipleUsers()); + final IPackageManager pm = AppGlobals.getPackageManager(); + final UserManager um = UserManager.get( + InstrumentationRegistry.getInstrumentation().getContext()); + final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK); + int userId = UserHandle.USER_NULL; + try { + // Create and start the 2nd user. + userId = um.createUser("Test User", 0 /* flags */).getUserHandle().getIdentifier(); + runShellCommand("am start-user -w " + userId); + + // Try to install test APK on the current user with reason INSTALL_REASON_POLICY + runShellCommand("pm install --user cur --install-reason 1 " + testApk); + assertWithMessage("The install reason on the current user is incorrect.").that( + pm.getInstallReason(TEST_PKG_NAME, UserHandle.myUserId())).isEqualTo( + PackageManager.INSTALL_REASON_POLICY); + + // Try to install test APK on the 2nd user with reason INSTALL_REASON_USER + runShellCommand("pm install --user " + userId + " --install-reason 4 " + testApk); + assertWithMessage("The install reason on the 2nd user is incorrect.").that( + pm.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo( + PackageManager.INSTALL_REASON_USER); + } finally { + runShellCommand("pm uninstall " + TEST_PKG_NAME); + if (userId != UserHandle.USER_NULL) { + um.removeUser(userId); + } + } + } } diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index 5d93e3dfadde..ab37e9bf6deb 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -25,6 +25,7 @@ import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND; import static android.content.pm.parsing.ParsingPackageUtils.parsePublicKey; import static android.content.res.Resources.ID_NULL; +import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; @@ -86,7 +87,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.CountDownLatch; @@ -1004,6 +1004,13 @@ public class PackageManagerSettingsTests { } } + private void verifyKeySetData(PackageKeySetData originalData, PackageKeySetData testData) { + assertThat(originalData.getProperSigningKeySet(), + equalTo(testData.getProperSigningKeySet())); + assertThat(originalData.getUpgradeKeySets(), is(testData.getUpgradeKeySets())); + assertThat(originalData.getAliases(), is(testData.getAliases())); + } + private void verifySettingCopy(PackageSetting origPkgSetting, PackageSetting testPkgSetting) { assertThat(origPkgSetting, is(not(testPkgSetting))); assertThat(origPkgSetting.getAppId(), is(testPkgSetting.getAppId())); @@ -1018,8 +1025,7 @@ public class PackageManagerSettingsTests { assertSame(origPkgSetting.getInstallSource(), testPkgSetting.getInstallSource()); assertThat(origPkgSetting.isInstallPermissionsFixed(), is(testPkgSetting.isInstallPermissionsFixed())); - assertSame(origPkgSetting.getKeySetData(), testPkgSetting.getKeySetData()); - assertThat(origPkgSetting.getKeySetData(), is(testPkgSetting.getKeySetData())); + verifyKeySetData(origPkgSetting.getKeySetData(), testPkgSetting.getKeySetData()); assertThat(origPkgSetting.getLastUpdateTime(), is(testPkgSetting.getLastUpdateTime())); assertSame(origPkgSetting.getLegacyNativeLibraryPath(), testPkgSetting.getLegacyNativeLibraryPath()); diff --git a/services/tests/servicestests/test-apps/StubApp/Android.bp b/services/tests/servicestests/test-apps/StubApp/Android.bp new file mode 100644 index 000000000000..99deb3f5bbf0 --- /dev/null +++ b/services/tests/servicestests/test-apps/StubApp/Android.bp @@ -0,0 +1,37 @@ +// 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 { + // 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_helper_app { + name: "StubTestApp", + + sdk_version: "current", + + srcs: ["**/*.java"], + + dex_preopt: { + enabled: false, + }, + optimize: { + enabled: false, + }, +} diff --git a/services/tests/servicestests/test-apps/StubApp/AndroidManifest.xml b/services/tests/servicestests/test-apps/StubApp/AndroidManifest.xml new file mode 100644 index 000000000000..90172e77f958 --- /dev/null +++ b/services/tests/servicestests/test-apps/StubApp/AndroidManifest.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.servicestests.apps.stubapp"> + + <application android:label="StubTestApp"> + <activity android:name=".TestActivity" + android:exported="true" /> + </application> + +</manifest>
\ No newline at end of file diff --git a/services/tests/servicestests/test-apps/StubApp/src/com/android/servicestests/apps/stubapp/TestActivity.java b/services/tests/servicestests/test-apps/StubApp/src/com/android/servicestests/apps/stubapp/TestActivity.java new file mode 100644 index 000000000000..0d94676aeb52 --- /dev/null +++ b/services/tests/servicestests/test-apps/StubApp/src/com/android/servicestests/apps/stubapp/TestActivity.java @@ -0,0 +1,22 @@ +/* + * 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.servicestests.apps.stubapp; + +import android.app.Activity; + +public class TestActivity extends Activity { +} diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 58089648ceca..ea3a4cd865cb 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -8511,6 +8511,18 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse(); + // using the style, but incorrect type in session - blocked + nb.setStyle(new Notification.MediaStyle()); + Bundle extras = new Bundle(); + extras.putParcelable(Notification.EXTRA_MEDIA_SESSION, new Intent()); + nb.addExtras(extras); + sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse(); + // style + media session - bypasses block nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class))); sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java index ea0196306d9f..29ef339a6382 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java @@ -89,6 +89,7 @@ import android.media.AudioManager; import android.media.session.MediaSession; import android.os.Binder; import android.os.Build; +import android.os.Bundle; import android.os.IBinder; import android.os.Looper; import android.os.Process; @@ -746,6 +747,18 @@ public class NotificationPermissionMigrationTest extends UiServiceTestCase { assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse(); + // using the style, but incorrect type in session - blocked + nb.setStyle(new Notification.MediaStyle()); + Bundle extras = new Bundle(); + extras.putParcelable(Notification.EXTRA_MEDIA_SESSION, new Intent()); + nb.addExtras(extras); + sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse(); + // style + media session - bypasses block nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class))); sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java index 1266b2e30859..afc2b8748abb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java @@ -854,12 +854,19 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater = mAtm.mInternal.createPackageConfigurationUpdater(DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID); + + // committing empty locales, when no config is set should return false. + assertFalse(packageConfigUpdater.setLocales(LocaleList.getEmptyLocaleList()).commit()); + // committing new configuration returns true; assertTrue(packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB")) .commit()); // applying the same configuration returns false. assertFalse(packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB")) .commit()); + + // committing empty locales and undefined nightMode should return true (deletes the + // pre-existing record) if some config was previously set. assertTrue(packageConfigUpdater.setLocales(LocaleList.getEmptyLocaleList()) .setNightMode(Configuration.UI_MODE_NIGHT_UNDEFINED).commit()); } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java index 5d0e34a80f3f..6fa306b004a2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java @@ -803,6 +803,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer); final ActivityRecord openingActivity = taskFragment.getTopMostActivity(); openingActivity.allDrawn = true; + task.effectiveUid = openingActivity.getUid(); spyOn(mDisplayContent.mAppTransition); // Prepare a transition. @@ -879,6 +880,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { final ActivityRecord closingActivity = taskFragment.getTopMostActivity(); closingActivity.allDrawn = true; closingActivity.info.applicationInfo.uid = 12345; + task.effectiveUid = closingActivity.getUid(); // Opening non-embedded activity with different UID. final ActivityRecord openingActivity = createActivityRecord(task); openingActivity.info.applicationInfo.uid = 54321; diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index 70aa2a2f32bb..8da8596f47f9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.RoundedCorners.NO_ROUNDED_CORNERS; @@ -251,28 +252,38 @@ public class DisplayPolicyTests extends WindowTestsBase { @Test public void testOverlappingWithNavBar() { + final InsetsSource navSource = new InsetsSource(ITYPE_NAVIGATION_BAR); + navSource.setFrame(new Rect(100, 200, 200, 300)); + testOverlappingWithNavBarType(navSource); + } + + @Test + public void testOverlappingWithExtraNavBar() { + final InsetsSource navSource = new InsetsSource(ITYPE_EXTRA_NAVIGATION_BAR); + navSource.setFrame(new Rect(100, 200, 200, 300)); + testOverlappingWithNavBarType(navSource); + } + + private void testOverlappingWithNavBarType(InsetsSource navSource) { final WindowState targetWin = createApplicationWindow(); final WindowFrames winFrame = targetWin.getWindowFrames(); winFrame.mFrame.set(new Rect(100, 100, 200, 200)); - - final WindowState navigationBar = createNavigationBarWindow(); - - navigationBar.getFrame().set(new Rect(100, 200, 200, 300)); + targetWin.mAboveInsetsState.addSource(navSource); assertFalse("Freeform is overlapping with navigation bar", - DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar)); + DisplayPolicy.isOverlappingWithNavBar(targetWin)); winFrame.mFrame.set(new Rect(100, 101, 200, 201)); assertTrue("Freeform should be overlapping with navigation bar (bottom)", - DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar)); + DisplayPolicy.isOverlappingWithNavBar(targetWin)); winFrame.mFrame.set(new Rect(99, 200, 199, 300)); assertTrue("Freeform should be overlapping with navigation bar (right)", - DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar)); + DisplayPolicy.isOverlappingWithNavBar(targetWin)); winFrame.mFrame.set(new Rect(199, 200, 299, 300)); assertTrue("Freeform should be overlapping with navigation bar (left)", - DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar)); + DisplayPolicy.isOverlappingWithNavBar(targetWin)); } private WindowState createNavigationBarWindow() { diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java index d89d64ad0037..a5c6dc0414dd 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java @@ -21,6 +21,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.testing.Assert.assertThrows; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; @@ -352,28 +353,66 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { } @Test - public void testApplyTransaction_enforceHierarchyChange_createTaskFragment() { + public void testApplyTransaction_enforceHierarchyChange_createTaskFragment() + throws RemoteException { + mController.registerOrganizer(mIOrganizer); + final ActivityRecord activity = createActivityRecord(mDisplayContent); + final int uid = Binder.getCallingUid(); + activity.info.applicationInfo.uid = uid; + activity.getTask().effectiveUid = uid; + final IBinder fragmentToken = new Binder(); + final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder( + mOrganizerToken, fragmentToken, activity.token).build(); mOrganizer.applyTransaction(mTransaction); // Allow organizer to create TaskFragment and start/reparent activity to TaskFragment. - final TaskFragmentCreationParams mockParams = mock(TaskFragmentCreationParams.class); - doReturn(mOrganizerToken).when(mockParams).getOrganizer(); - mTransaction.createTaskFragment(mockParams); + mTransaction.createTaskFragment(params); mTransaction.startActivityInTaskFragment( mFragmentToken, null /* callerToken */, new Intent(), null /* activityOptions */); mTransaction.reparentActivityToTaskFragment(mFragmentToken, mock(IBinder.class)); mTransaction.setAdjacentTaskFragments(mFragmentToken, mock(IBinder.class), null /* options */); + mAtm.getWindowOrganizerController().applyTransaction(mTransaction); - // It is expected to fail for the mock TaskFragmentCreationParams. It is ok as we are - // testing the security check here. - assertThrows(IllegalArgumentException.class, () -> { - try { - mAtm.getWindowOrganizerController().applyTransaction(mTransaction); - } catch (RemoteException e) { - fail(); - } - }); + // Successfully created a TaskFragment. + final TaskFragment taskFragment = mAtm.mWindowOrganizerController + .getTaskFragment(fragmentToken); + assertNotNull(taskFragment); + assertEquals(activity.getTask(), taskFragment.getTask()); + } + + @Test + public void testApplyTransaction_createTaskFragment_failForDifferentUid() + throws RemoteException { + mController.registerOrganizer(mIOrganizer); + final ActivityRecord activity = createActivityRecord(mDisplayContent); + final int uid = Binder.getCallingUid(); + final IBinder fragmentToken = new Binder(); + final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder( + mOrganizerToken, fragmentToken, activity.token).build(); + mOrganizer.applyTransaction(mTransaction); + mTransaction.createTaskFragment(params); + + // Fail to create TaskFragment when the task uid is different from caller. + activity.info.applicationInfo.uid = uid; + activity.getTask().effectiveUid = uid + 1; + mAtm.getWindowOrganizerController().applyTransaction(mTransaction); + + assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken)); + + // Fail to create TaskFragment when the task uid is different from owner activity. + activity.info.applicationInfo.uid = uid + 1; + activity.getTask().effectiveUid = uid; + mAtm.getWindowOrganizerController().applyTransaction(mTransaction); + + assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken)); + + // Successfully created a TaskFragment for same uid. + activity.info.applicationInfo.uid = uid; + activity.getTask().effectiveUid = uid; + mAtm.getWindowOrganizerController().applyTransaction(mTransaction); + + assertNotNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken)); } @Test @@ -424,4 +463,26 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities(); } + + @Test + public void testDeferPendingTaskFragmentEventsOfInvisibleTask() { + // Task - TaskFragment - Activity. + final Task task = createTask(mDisplayContent); + final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm) + .setParentTask(task) + .setOrganizer(mOrganizer) + .build(); + + // Mock the task to invisible + doReturn(false).when(task).shouldBeVisible(any()); + + // Sending events + mController.registerOrganizer(mIOrganizer); + taskFragment.mTaskFragmentAppearedSent = true; + mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment); + mController.dispatchPendingEvents(); + + // Verifies that event was not sent + verify(mOrganizer, never()).onTaskFragmentInfoChanged(any()); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java index c742e5606f06..7dfb5aef7fe7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java @@ -69,10 +69,6 @@ public class TestIWindow extends IWindow.Stub { } @Override - public void windowFocusChanged(boolean hasFocus) throws RemoteException { - } - - @Override public void closeSystemDialogs(String reason) throws RemoteException { } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index f05dd636aa22..e19ea47df3bb 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -841,7 +841,7 @@ final class HotwordDetectionConnection { try { return mContext.bindIsolatedService( mIntent, - Context.BIND_AUTO_CREATE | mBindingFlags, + Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE | mBindingFlags, "hotword_detector_" + mInstanceNumber, mExecutor, serviceConnection); diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index abbce1cd869d..98f619f497d4 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -1687,7 +1687,11 @@ public class TelecomManager { * * @param accountHandle The handle for the account retrieve a number for. * @return A string representation of the line 1 phone number. + * @deprecated use {@link SubscriptionManager#getPhoneNumber(int)} instead, which takes a + * Telephony Subscription ID that can be retrieved with the {@code accountHandle} + * from {@link TelephonyManager#getSubscriptionId(PhoneAccountHandle)}. */ + @Deprecated @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges or default SMS app @RequiresPermission(anyOf = { android.Manifest.permission.READ_PHONE_STATE, diff --git a/telephony/common/Android.bp b/telephony/common/Android.bp index 1cacc0365fe1..b0a812bf57a3 100644 --- a/telephony/common/Android.bp +++ b/telephony/common/Android.bp @@ -21,7 +21,10 @@ filegroup { filegroup { name: "framework-mms-shared-srcs", - visibility: ["//packages/apps/Bluetooth"], + visibility: [ + "//packages/apps/Bluetooth", + "//packages/modules/Bluetooth/android/app", + ], srcs: [ "com/google/android/mms/**/*.java", ], diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index f700d79d67aa..3f0f50c5f62a 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -5207,16 +5207,6 @@ public class CarrierConfigManager { "call_composer_picture_server_url_string"; /** - * For Android 11, provide a temporary solution for OEMs to use the lower of the two MTU values - * for IPv4 and IPv6 if both are sent. - * TODO: remove in later release - * - * @hide - */ - public static final String KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED = - "use_lower_mtu_value_if_both_received"; - - /** * Determines the default RTT mode. * * Upon first boot, when the user has not yet set a value for their preferred RTT mode, @@ -5970,7 +5960,6 @@ public class CarrierConfigManager { sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, ""); sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false); sDefaults.putString(KEY_CALL_COMPOSER_PICTURE_SERVER_URL_STRING, ""); - sDefaults.putBoolean(KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED, false); sDefaults.putBoolean(KEY_USE_ACS_FOR_RCS_BOOL, false); sDefaults.putBoolean(KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL, true); sDefaults.putInt(KEY_DEFAULT_RTT_MODE_INT, 0); diff --git a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java index 2ff4ac5e30d3..9cb80f1814f9 100644 --- a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java +++ b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java @@ -71,12 +71,7 @@ public final class SignalStrengthUpdateRequest implements Parcelable { @Nullable List<SignalThresholdInfo> signalThresholdInfos, boolean isReportingRequestedWhileIdle, boolean isSystemThresholdReportingRequestedWhileIdle) { - // System app (like Bluetooth) can specify the request to report system thresholds while - // device is idle (with permission protection). In this case, the request doesn't need to - // provide a non-empty list of SignalThresholdInfo which is only asked for public apps. - if (!isSystemThresholdReportingRequestedWhileIdle) { - validate(signalThresholdInfos); - } + validate(signalThresholdInfos, isSystemThresholdReportingRequestedWhileIdle); mSignalThresholdInfos = signalThresholdInfos; mIsReportingRequestedWhileIdle = isReportingRequestedWhileIdle; @@ -274,8 +269,12 @@ public final class SignalStrengthUpdateRequest implements Parcelable { * Throw IAE if SignalThresholdInfo collection is null or empty, * or the SignalMeasurementType for the same RAN in the collection is not unique. */ - private static void validate(Collection<SignalThresholdInfo> infos) { - if (infos == null || infos.isEmpty()) { + private static void validate(Collection<SignalThresholdInfo> infos, + boolean isSystemThresholdReportingRequestedWhileIdle) { + // System app (like Bluetooth) can specify the request to report system thresholds while + // device is idle (with permission protection). In this case, the request doesn't need to + // provide a non-empty list of SignalThresholdInfo which is only asked for public apps. + if (infos == null || (infos.isEmpty() && !isSystemThresholdReportingRequestedWhileIdle)) { throw new IllegalArgumentException("SignalThresholdInfo collection is null or empty"); } diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index d6d6775cb40f..d11ad914061d 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -498,7 +498,10 @@ public class SubscriptionInfo implements Parcelable { * * @return the number of this subscription, or an empty string if one of these requirements is * not met + * @deprecated use {@link SubscriptionManager#getPhoneNumber(int)} instead, which takes a + * {@link #getSubscriptionId() subscription ID}. */ + @Deprecated public String getNumber() { return mNumber; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 04e7b7c8711c..88b21e0428b0 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -4791,7 +4791,10 @@ public class TelephonyManager { * for any API level. * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * for apps targeting SDK API level 29 and below. + * + * @deprecated use {@link SubscriptionManager#getPhoneNumber(int)} instead. */ + @Deprecated @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges or default SMS app @RequiresPermission(anyOf = { android.Manifest.permission.READ_PHONE_STATE, @@ -4864,7 +4867,9 @@ public class TelephonyManager { * @param alphaTag alpha-tagging of the dailing nubmer * @param number The dialing number * @return true if the operation was executed correctly. + * @deprecated use {@link SubscriptionManager#setCarrierPhoneNumber(int, String)} instead. */ + @Deprecated public boolean setLine1NumberForDisplay(String alphaTag, String number) { return setLine1NumberForDisplay(getSubId(), alphaTag, number); } @@ -4885,6 +4890,10 @@ public class TelephonyManager { */ public boolean setLine1NumberForDisplay(int subId, String alphaTag, String number) { try { + // This API is deprecated; call the new API to allow smooth migartion. + // The new API doesn't accept null so convert null to empty string. + mSubscriptionManager.setCarrierPhoneNumber(subId, (number == null ? "" : number)); + ITelephony telephony = getITelephony(); if (telephony != null) return telephony.setLine1NumberForDisplayForSubscriber(subId, alphaTag, number); diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.java b/telephony/java/android/telephony/ims/DelegateRegistrationState.java index c00c741a0d60..1b1040430fd2 100644 --- a/telephony/java/android/telephony/ims/DelegateRegistrationState.java +++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java @@ -117,6 +117,7 @@ public final class DelegateRegistrationState implements Parcelable { }) public @interface DeregisteringReason {} + private ArraySet<String> mRegisteringTags = new ArraySet<>(); private ArraySet<String> mRegisteredTags = new ArraySet<>(); private final ArraySet<FeatureTagState> mDeregisteringTags = new ArraySet<>(); private final ArraySet<FeatureTagState> mDeregisteredTags = new ArraySet<>(); @@ -134,6 +135,20 @@ public final class DelegateRegistrationState implements Parcelable { } /** + * Add the set of feature tags that are associated with this SipDelegate and + * the IMS stack is actively trying to register on the carrier network. + * + * The feature tags will either move to the registered or deregistered state + * depending on the result of the registration. + * @param featureTags The IMS media feature tags that are in the progress of registering. + * @return The in-progress Builder instance for RegistrationState. ] + */ + public @NonNull Builder addRegisteringFeatureTags(@NonNull Set<String> featureTags) { + mState.mRegisteringTags.addAll(featureTags); + return this; + } + + /** * Add a feature tag that is currently included in the current network IMS Registration. * @param featureTag The IMS media feature tag included in the current IMS registration. * @return The in-progress Builder instance for RegistrationState. @@ -209,6 +224,17 @@ public final class DelegateRegistrationState implements Parcelable { mRegisteredTags = (ArraySet<String>) source.readArraySet(null); readStateFromParcel(source, mDeregisteringTags); readStateFromParcel(source, mDeregisteredTags); + mRegisteringTags = (ArraySet<String>) source.readArraySet(null); + } + + /** + * Get the feature tags that are associated with this SipDelegate that the IMS stack is actively + * trying to register on the carrier network. + * @return A Set of feature tags associated with this SipDelegate that the IMS service is + * currently trying to register on the carrier network. + */ + public @NonNull Set<String> getRegisteringFeatureTags() { + return new ArraySet<>(mRegisteringTags); } /** @@ -286,6 +312,7 @@ public final class DelegateRegistrationState implements Parcelable { dest.writeArraySet(mRegisteredTags); writeStateToParcel(dest, mDeregisteringTags); writeStateToParcel(dest, mDeregisteredTags); + dest.writeArraySet(mRegisteringTags); } private void writeStateToParcel(Parcel dest, Set<FeatureTagState> state) { @@ -311,19 +338,22 @@ public final class DelegateRegistrationState implements Parcelable { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; DelegateRegistrationState that = (DelegateRegistrationState) o; - return mRegisteredTags.equals(that.mRegisteredTags) + return mRegisteringTags.equals(that.mRegisteringTags) + && mRegisteredTags.equals(that.mRegisteredTags) && mDeregisteringTags.equals(that.mDeregisteringTags) && mDeregisteredTags.equals(that.mDeregisteredTags); } @Override public int hashCode() { - return Objects.hash(mRegisteredTags, mDeregisteringTags, mDeregisteredTags); + return Objects.hash(mRegisteringTags, mRegisteredTags, + mDeregisteringTags, mDeregisteredTags); } @Override public String toString() { return "DelegateRegistrationState{ registered={" + mRegisteredTags + + "}, registering={" + mRegisteringTags + "}, deregistering={" + mDeregisteringTags + "}, deregistered={" + mDeregisteredTags + "}}"; } diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java index e4e535d3240d..da5468e48f19 100644 --- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java @@ -157,8 +157,18 @@ public class StagedInstallInternalTest { @Test public void testStagedSessionShouldCleanUpOnVerificationFailure() throws Exception { + // APEX verification InstallUtils.commitExpectingFailure(AssertionError.class, "apexd verification failed", Install.single(APEX_WRONG_SHA_V2).setStaged()); + InstallUtils.commitExpectingFailure(AssertionError.class, "apexd verification failed", + Install.multi(APEX_WRONG_SHA_V2, TestApp.A1).setStaged()); + // APK verification + Install.single(TestApp.A2).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + InstallUtils.commitExpectingFailure(AssertionError.class, "Downgrade detected", + Install.single(TestApp.A1).setStaged()); + InstallUtils.commitExpectingFailure(AssertionError.class, "Downgrade detected", + Install.multi(TestApp.A1, TestApp.B1).setStaged()); } @Test @@ -176,6 +186,12 @@ public class StagedInstallInternalTest { } @Test + public void testStagedSessionShouldCleanUpOnOnSuccessMultiPackage_Commit() throws Exception { + int sessionId = Install.multi(TestApp.A1, TestApp.Apex2).setStaged().commit(); + storeSessionId(sessionId); + } + + @Test public void testStagedInstallationShouldCleanUpOnValidationFailure() throws Exception { InstallUtils.commitExpectingFailure(AssertionError.class, "INSTALL_FAILED_INVALID_APK", Install.single(TestApp.AIncompleteSplit).setStaged()); diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java index 78cf9aca66c0..926bf1b88fee 100644 --- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java @@ -301,6 +301,18 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { } @Test + @LargeTest + public void testStagedSessionShouldCleanUpOnOnSuccessMultiPackage() throws Exception { + List<String> before = getStagingDirectories(); + runPhase("testStagedSessionShouldCleanUpOnOnSuccessMultiPackage_Commit"); + assertThat(getStagingDirectories()).isNotEqualTo(before); + getDevice().reboot(); + runPhase("testStagedSessionShouldCleanUpOnOnSuccess_Verify"); + List<String> after = getStagingDirectories(); + assertThat(after).isEqualTo(before); + } + + @Test public void testStagedInstallationShouldCleanUpOnValidationFailure() throws Exception { List<String> before = getStagingDirectories(); runPhase("testStagedInstallationShouldCleanUpOnValidationFailure"); diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh index ac23c3d9cb4a..36bea57b710f 100755 --- a/tools/aosp/aosp_sha.sh +++ b/tools/aosp/aosp_sha.sh @@ -1,7 +1,7 @@ #!/bin/bash LOCAL_DIR="$( dirname "${BASH_SOURCE}" )" -if git branch -vv | grep -q -P "^\*[^\[]+\[aosp/"; then +if git branch -vv | grep -q -E "^\*[^\[]+\[aosp/"; then # Change appears to be in AOSP exit 0 elif git log -n 1 --format='%B' $1 | grep -q -E "^Ignore-AOSP-First: .+" ; then |